diff --git a/Generals/Code/GameEngine/Include/Common/GameEngine.h b/Generals/Code/GameEngine/Include/Common/GameEngine.h index 3022de14faa..014a8628fa3 100644 --- a/Generals/Code/GameEngine/Include/Common/GameEngine.h +++ b/Generals/Code/GameEngine/Include/Common/GameEngine.h @@ -81,7 +81,6 @@ class GameEngine : public SubsystemInterface virtual void serviceWindowsOS(void) {}; ///< service the native OS virtual Bool isActive(void) {return m_isActive;} ///< returns whether app has OS focus. virtual void setIsActive(Bool isActive) { m_isActive = isActive; }; - virtual void checkAbnormalQuitting(void); ///< check if user is quitting at an unusual time - as in cheating! protected: diff --git a/Generals/Code/GameEngine/Include/GameClient/GUICallbacks.h b/Generals/Code/GameEngine/Include/GameClient/GUICallbacks.h index 07e3ded5e01..8cd3209dbdf 100644 --- a/Generals/Code/GameEngine/Include/GameClient/GUICallbacks.h +++ b/Generals/Code/GameEngine/Include/GameClient/GUICallbacks.h @@ -263,12 +263,6 @@ extern WindowMsgHandledType WOLBuddyOverlayInput( GameWindow *window, UnsignedIn extern void WOLBuddyOverlayRCMenuInit( WindowLayout *layout, void *userData ); extern WindowMsgHandledType WOLBuddyOverlayRCMenuSystem( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 ); -// GameSpy Player Info Overlay --------------------------------------------------------------------------------- -extern void GameSpyPlayerInfoOverlayInit( WindowLayout *layout, void *userData ); -extern void GameSpyPlayerInfoOverlayUpdate( WindowLayout *layout, void *userData ); -extern void GameSpyPlayerInfoOverlayShutdown( WindowLayout *layout, void *userData ); -extern WindowMsgHandledType GameSpyPlayerInfoOverlaySystem( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 ); -extern WindowMsgHandledType GameSpyPlayerInfoOverlayInput( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 ); // Popup host Game Internet ----------------------------------------------------------------------------------- extern void PopupHostGameInit( WindowLayout *layout, void *userData ); diff --git a/Generals/Code/GameEngine/Include/GameClient/LoadScreen.h b/Generals/Code/GameEngine/Include/GameClient/LoadScreen.h index 6cb73b7b203..54a412ab799 100644 --- a/Generals/Code/GameEngine/Include/GameClient/LoadScreen.h +++ b/Generals/Code/GameEngine/Include/GameClient/LoadScreen.h @@ -179,37 +179,6 @@ class MultiPlayerLoadScreen : public LoadScreen /////////////////////////////////////////////////////////////////////////////////////////////////// // class MultiPlayerLoadScreen is to be used for multiplayer communication on the loadscreens //// /////////////////////////////////////////////////////////////////////////////////////////////// -class GameSpyLoadScreen : public LoadScreen -{ -public: - GameSpyLoadScreen( void ); - virtual ~GameSpyLoadScreen( void ); - - virtual void init( GameInfo *game ); ///< Init the loadscreen - virtual void reset( void ); ///< Reset the system - virtual void update( void ) - { - DEBUG_CRASH(("Call update(Int) instead. This update isn't supported")); - }; - virtual void update(Int percent); ///< Update the state of the progress bar - void processProgress(Int playerId, Int percentage); - virtual void setProgressRange( Int min, Int max ) { } -private: - GameWindow *m_progressBars[MAX_SLOTS]; ///< pointer array to all the progress bars on the window - GameWindow *m_playerNames[MAX_SLOTS]; ///< pointer array to all the static text player names on the window - GameWindow *m_playerSide[MAX_SLOTS]; ///< pointer array to all the static text player sides - GameWindow *m_playerFavoriteFactions[MAX_SLOTS]; ///< pointer array to all the static text player sides - GameWindow *m_playerTotalDisconnects[MAX_SLOTS]; ///< pointer array to all the static text player sides - GameWindow *m_playerWin[MAX_SLOTS]; ///< pointer array to all the static text player sides - GameWindow *m_playerWinLosses[MAX_SLOTS]; ///< pointer array to all the static text player sides - GameWindow *m_playerRank[MAX_SLOTS]; ///< pointer array to all the static text player sides - GameWindow *m_playerOfficerMedal[MAX_SLOTS]; ///< pointer array to all the static text player munkees - GameWindow *m_mapPreview; - GameWindow *m_buttonMapStartPosition[MAX_SLOTS]; - - Int m_playerLookup[MAX_SLOTS]; ///< lookup table to translate network slot info screen slot (to account for holes in the slot list) -}; - /////////////////////////////////////////////////////////////////////////////////////////////////// // class MapTransferLoadScreen is to be used for map transfers before multiplayer game load screens //// /////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy.h deleted file mode 100644 index 9b3ba17a4c9..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy.h +++ /dev/null @@ -1,148 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameSpy.h ////////////////////////////////////////////////////// -// Generals GameSpy stuff -// Author: Matthew D. Campbell, February 2002 - -#pragma once - -#ifndef __GameSpy_H__ -#define __GameSpy_H__ - -#include "GameSpy/Peer/Peer.h" - -#include "GameClient/Color.h" -#include "Common/STLTypedefs.h" - -class GameSpyGroupRoom -{ -public: - GameSpyGroupRoom() { m_name = AsciiString::TheEmptyString; m_groupID = m_numWaiting = m_maxWaiting = m_numGames = m_numPlaying = 0; } - AsciiString m_name; - Int m_groupID; - Int m_numWaiting; - Int m_maxWaiting; - Int m_numGames; - Int m_numPlaying; -}; -typedef std::map GroupRoomMap; - -class GameSpyChatInterface : public SubsystemInterface -{ -public: - virtual ~GameSpyChatInterface() { }; - - virtual void init( void ) = 0; - virtual void reset( void ) = 0; - virtual void update( void ) = 0; - - virtual Bool isConnected( void ) = 0; - virtual void login(AsciiString loginName, AsciiString password = AsciiString::TheEmptyString, AsciiString email = AsciiString::TheEmptyString) = 0; - virtual void reconnectProfile( void ) = 0; - virtual void disconnectFromChat( void ) = 0; - - virtual void UTMRoom( RoomType roomType, const char *key, const char *val, Bool authenticate = FALSE ) = 0; - virtual void UTMPlayer( const char *name, const char *key, const char *val, Bool authenticate = FALSE ) = 0; - virtual void startGame( void ) = 0; - virtual void leaveRoom( RoomType roomType ) = 0; - virtual void setReady( Bool ready ) = 0; - virtual void enumPlayers( RoomType roomType, peerEnumPlayersCallback callback, void *userData ) = 0; - virtual void startListingGames( peerListingGamesCallback callback ) = 0; - virtual void stopListingGames( void ) = 0; - - virtual void joinGroupRoom( Int ID ) = 0; - virtual void joinStagingRoom( GServer server, AsciiString password ) = 0; - virtual void createStagingRoom( AsciiString gameName, AsciiString password, Int maxPlayers ) = 0; - virtual void joinBestGroupRoom( void ) = 0; - - inline PEER getPeer( void ) { return m_peer; } - inline AsciiString getLoginName( void ) { return m_loginName; } - inline AsciiString getPassword( void ) { return m_password; } - inline GroupRoomMap* getGroupRooms( void ) { return &m_groupRooms; } - inline Int getCurrentGroupRoomID( void ) { return m_currentGroupRoomID; } - inline Bool getUsingProfile( void ) { return m_usingProfiles; } - inline Int getProfileID( void ) { return m_profileID; } - - inline void setCurrentGroupRoomID( Int ID ) { m_currentGroupRoomID = ID; } - void clearGroupRoomList(void); - inline Int getNumGroupRooms( void ) { return m_groupRooms.size(); } - - -protected: - - AsciiString m_loginName; - AsciiString m_password; - AsciiString m_email; - Bool m_usingProfiles; - Int m_profileID; - PEER m_peer; - - GroupRoomMap m_groupRooms; - Int m_currentGroupRoomID; -}; - -GameSpyChatInterface *createGameSpyChat( void ); - -extern GameSpyChatInterface *TheGameSpyChat; - - -void JoinRoomCallback(PEER peer, PEERBool success, - PEERJoinResult result, RoomType roomType, - void *param); ///< Called when we (fail to) join a room. param is address of Bool to store result - -void ListGroupRoomsCallback(PEER peer, PEERBool success, - int groupID, GServer server, - const char * name, int numWaiting, - int maxWaiting, int numGames, - int numPlaying, void * param); ///< Called while listing group rooms - -enum GameSpyColors { - GSCOLOR_DEFAULT = 0, - GSCOLOR_CURRENTROOM, - GSCOLOR_ROOM, - GSCOLOR_GAME, - GSCOLOR_PLAYER_NORMAL, - GSCOLOR_PLAYER_OWNER, - GSCOLOR_PLAYER_BUDDY, - GSCOLOR_PLAYER_SELF, - GSCOLOR_CHAT_NORMAL, - GSCOLOR_CHAT_EMOTE, - GSCOLOR_CHAT_OWNER, - GSCOLOR_CHAT_OWNER_EMOTE, - GSCOLOR_CHAT_PRIVATE, - GSCOLOR_CHAT_PRIVATE_EMOTE, - GSCOLOR_CHAT_PRIVATE_OWNER, - GSCOLOR_CHAT_PRIVATE_OWNER_EMOTE, - GSCOLOR_CHAT_BUDDY, - GSCOLOR_CHAT_SELF, - GSCOLOR_ACCEPT_TRUE, - GSCOLOR_ACCEPT_FALSE, - GSCOLOR_MAX -}; - -extern const Color GameSpyColor[GSCOLOR_MAX]; - - -#endif // __GameSpy_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyDefs.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyDefs.h deleted file mode 100644 index 6a2cac82b7e..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyDefs.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: BuddyDefs.h ////////////////////////////////////////////////////// -// Generals GameSpy Buddy (GP) definitions -// Author: Matthew D. Campbell, July 2002 - -#pragma once - -#ifndef __BUDDYDEFS_H__ -#define __BUDDYDEFS_H__ - -void HandleBuddyResponses(void); -void PopulateOldBuddyMessages(void); - -#endif // __BUDDYDEFS_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyThread.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyThread.h deleted file mode 100644 index c368acc3921..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyThread.h +++ /dev/null @@ -1,179 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: BuddyThread.h ////////////////////////////////////////////////////// -// Generals GameSpy BuddyList thread class interface -// Author: Matthew D. Campbell, June 2002 - -#pragma once - -#ifndef __BUDDYTHREAD_H__ -#define __BUDDYTHREAD_H__ - -#include "GameSpy/GP/GP.h" - -#define MAX_BUDDY_CHAT_LEN 128 - -// this class encapsulates a request for the buddy thread -class BuddyRequest -{ -public: - enum - { - BUDDYREQUEST_LOGIN, // attempt to login - BUDDYREQUEST_RELOGIN, // log in after being disconnected - BUDDYREQUEST_LOGOUT, // log out if connected - BUDDYREQUEST_MESSAGE, - BUDDYREQUEST_LOGINNEW, // attempt to create a new nick and login - //BUDDYREQUEST_DELETELOGIN, - BUDDYREQUEST_ADDBUDDY, // add someone to your buddy list - BUDDYREQUEST_DELBUDDY, // delete someone from your buddy list - BUDDYREQUEST_OKADD, // allow someone to add you to their buddy list - BUDDYREQUEST_DENYADD, // don't allow someone to add you to their buddy list - BUDDYREQUEST_SETSTATUS, // Set our status - BUDDYREQUEST_DELETEACCT, // Delete our account - BUDDYREQUEST_MAX - } buddyRequestType; - - union - { - struct - { - GPProfile recipient; - WideChar text[MAX_BUDDY_CHAT_LEN]; - } message; - - struct - { - char nick[GP_NICK_LEN]; - char email[GP_EMAIL_LEN]; - char password[GP_PASSWORD_LEN]; - Bool hasFirewall; - } login; - - struct - { - GPProfile id; - WideChar text[MAX_BUDDY_CHAT_LEN]; - } addbuddy; - - struct - { - GPProfile id; - } profile; - - struct - { - GPEnum status; - char statusString[GP_STATUS_STRING_LEN]; - char locationString[GP_LOCATION_STRING_LEN]; - } status; - - } arg; -}; - -//------------------------------------------------------------------------- - -// this class encapsulates an action the buddy thread wants from the UI -class BuddyResponse -{ -public: - enum - { - BUDDYRESPONSE_LOGIN, - BUDDYRESPONSE_DISCONNECT, - BUDDYRESPONSE_MESSAGE, - BUDDYRESPONSE_REQUEST, - BUDDYRESPONSE_STATUS, - BUDDYRESPONSE_MAX - } buddyResponseType; - - GPProfile profile; - GPResult result; - - union - { - struct - { - UnsignedInt date; - char nick[GP_NICK_LEN]; - WideChar text[MAX_BUDDY_CHAT_LEN]; - } message; - - struct - { - char nick[GP_NICK_LEN]; - char email[GP_EMAIL_LEN]; - char countrycode[GP_COUNTRYCODE_LEN]; - WideChar text[GP_REASON_LEN]; - } request; - - struct - { - //GPResult result; - GPErrorCode errorCode; - char errorString[MAX_BUDDY_CHAT_LEN]; - GPEnum fatal; - } error; - - struct - { - char nick[GP_NICK_LEN]; - char email[GP_EMAIL_LEN]; - char countrycode[GP_COUNTRYCODE_LEN]; - char location[GP_LOCATION_STRING_LEN]; - GPEnum status; - char statusString[GP_STATUS_STRING_LEN]; - } status; - } arg; -}; - -//------------------------------------------------------------------------- - -// this is the actual message queue used to pass messages between threads -class GameSpyBuddyMessageQueueInterface -{ -public: - virtual ~GameSpyBuddyMessageQueueInterface() {} - virtual void startThread( void ) = 0; - virtual void endThread( void ) = 0; - virtual Bool isThreadRunning( void ) = 0; - virtual Bool isConnected( void ) = 0; - virtual Bool isConnecting( void ) = 0; - - virtual void addRequest( const BuddyRequest& req ) = 0; - virtual Bool getRequest( BuddyRequest& req ) = 0; - - virtual void addResponse( const BuddyResponse& resp ) = 0; - virtual Bool getResponse( BuddyResponse& resp ) = 0; - - virtual GPProfile getLocalProfileID( void ) = 0; - - static GameSpyBuddyMessageQueueInterface* createNewMessageQueue( void ); -}; - -extern GameSpyBuddyMessageQueueInterface *TheGameSpyBuddyMessageQueue; - - -#endif // __BUDDYTHREAD_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/GSConfig.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/GSConfig.h deleted file mode 100644 index 561c2f232a5..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/GSConfig.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GSConfig.h /////////////////////////////////////////////////////////// -// Author: Matthew D. Campbell, Sept 2002 -// Description: GameSpy online config -/////////////////////////////////////////////////////////////////////////////// - -#pragma once - -#ifndef __GSCONFIG_H__ -#define __GSCONFIG_H__ - -#include "Common/AsciiString.h" -#include "Common/STLTypedefs.h" - -class GameSpyConfigInterface -{ -public: - virtual ~GameSpyConfigInterface() {} - - // Pings - virtual std::list getPingServers(void) = 0; - virtual Int getNumPingRepetitions(void) = 0; - virtual Int getPingTimeoutInMs(void) = 0; - virtual Int getPingCutoffGood( void ) = 0; - virtual Int getPingCutoffBad( void ) = 0; - - // QM - virtual std::list getQMMaps(void) = 0; - virtual Int getQMBotID(void) = 0; - virtual Int getQMChannel(void) = 0; - virtual void setQMChannel(Int channel) = 0; - - // Player Info - virtual Int getPointsForRank(Int rank) = 0; - virtual Bool isPlayerVIP(Int id) = 0; - - // mangler Info - virtual Bool getManglerLocation(Int index, AsciiString& host, UnsignedShort& port) = 0; - - // Ladder / Any other external parsing - virtual AsciiString getLeftoverConfig(void) = 0; - - // NAT Timeouts - virtual Int getTimeBetweenRetries() = 0; - virtual Int getMaxManglerRetries() = 0; - virtual time_t getRetryInterval() = 0; - virtual time_t getKeepaliveInterval() = 0; - virtual time_t getPortTimeout() = 0; - virtual time_t getRoundTimeout() = 0; - - // Custom match - virtual Bool restrictGamesToLobby() = 0; - - static GameSpyConfigInterface* create(AsciiString config); -}; - -extern GameSpyConfigInterface *TheGameSpyConfig; - -#endif // __GSCONFIG_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/GameResultsThread.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/GameResultsThread.h deleted file mode 100644 index 4cb190ca0f3..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/GameResultsThread.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameResultsThread.h ////////////////////////////////////////////////////// -// Generals game results thread class interface -// Author: Matthew D. Campbell, August 2002 - -#pragma once - -#ifndef __GAMERESULTSTHREAD_H__ -#define __GAMERESULTSTHREAD_H__ - -#include "Common/SubsystemInterface.h" - -// this class encapsulates a request for the thread -class GameResultsRequest -{ -public: - std::string hostname; - UnsignedShort port; - std::string results; -}; - -//------------------------------------------------------------------------- - -// this class encapsulates a response from the thread -class GameResultsResponse -{ -public: - std::string hostname; - UnsignedShort port; - Bool sentOk; -}; - -//------------------------------------------------------------------------- - -// this is the actual message queue used to pass messages between threads -class GameResultsInterface : public SubsystemInterface -{ -public: - virtual ~GameResultsInterface() {} - virtual void startThreads( void ) = 0; - virtual void endThreads( void ) = 0; - virtual Bool areThreadsRunning( void ) = 0; - - virtual void addRequest( const GameResultsRequest& req ) = 0; - virtual Bool getRequest( GameResultsRequest& resp ) = 0; - - virtual void addResponse( const GameResultsResponse& resp ) = 0; - virtual Bool getResponse( GameResultsResponse& resp ) = 0; - - static GameResultsInterface* createNewGameResultsInterface( void ); - - virtual Bool areGameResultsBeingSent( void ) = 0; -}; - -extern GameResultsInterface *TheGameResultsQueue; - - -#endif // __GAMERESULTSTHREAD_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/LadderDefs.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/LadderDefs.h deleted file mode 100644 index b7f1ba53834..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/LadderDefs.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: LadderDefs.h ////////////////////////////////////////////////////// -// Generals ladder definitions -// Author: Matthew D. Campbell, August 2002 - -#pragma once - -#ifndef __LADDERDEFS_H__ -#define __LADDERDEFS_H__ - -#include "Common/UnicodeString.h" -#include "Common/AsciiString.h" -#include "Common/STLTypedefs.h" - -class GameWindow; - -class LadderInfo -{ -public: - LadderInfo(); - UnicodeString name; - UnicodeString description; - UnicodeString location; - Int playersPerTeam; - Int minWins; - Int maxWins; - Bool randomMaps; - Bool randomFactions; - Bool validQM; - Bool validCustom; - std::list validMaps; - std::list validFactions; - AsciiString cryptedPassword; - AsciiString address; - UnsignedShort port; - AsciiString homepageURL; - Bool submitReplay; // with game results - Int index; -}; - -typedef std::list LadderInfoList; - -class LadderList -{ -public: - LadderList(); - ~LadderList(); - - const LadderInfo* findLadder( const AsciiString& addr, UnsignedShort port ); - const LadderInfo* findLadderByIndex( Int index ); // doesn't look in local ladders - const LadderInfoList* getLocalLadders( void ); - const LadderInfoList* getSpecialLadders( void ); - const LadderInfoList* getStandardLadders( void ); - -private: - void loadLocalLadders( void ); - void checkLadder( AsciiString fname, Int index ); - LadderInfoList m_localLadders; - LadderInfoList m_specialLadders; - LadderInfoList m_standardLadders; -}; - -extern LadderList *TheLadderList; - -#endif // __LADDERDEFS_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/LobbyUtils.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/LobbyUtils.h deleted file mode 100644 index 5d34c8a711a..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/LobbyUtils.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: LobbyUtils.h ////////////////////////////////////////////////////// -// Generals lobby utils -// Author: Matthew D. Campbell, Sept 2002 - -#pragma once - -#ifndef __LOBBYUTILS_H__ -#define __LOBBYUTILS_H__ - -class GameWindow; - -GameWindow *GetGameListBox( void ); -GameWindow *GetGameInfoListBox( void ); -NameKeyType GetGameListBoxID( void ); -NameKeyType GetGameInfoListBoxID( void ); -void GrabWindowInfo( void ); -void ReleaseWindowInfo( void ); -void RefreshGameInfoListBox( GameWindow *mainWin, GameWindow *win ); -void RefreshGameListBoxes( void ); -void ToggleGameListType( void ); - -enum GameSortType -{ - GAMESORT_ALPHA_ASCENDING = 0, - GAMESORT_ALPHA_DESCENDING, - GAMESORT_PING_ASCENDING, - GAMESORT_PING_DESCENDING, - GAMESORT_MAX, -}; - -Bool HandleSortButton( NameKeyType sortButton ); -void PopulateLobbyPlayerListbox(void); - -#endif // __LOBBYUTILS_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/MainMenuUtils.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/MainMenuUtils.h deleted file mode 100644 index af283c8d085..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/MainMenuUtils.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: MainMenuUtils.h ////////////////////////////////////////////////////// -// Author: Matthew D. Campbell, Sept 2002 -// Description: GameSpy version check, patch download, etc utils -/////////////////////////////////////////////////////////////////////////////// - -#pragma once - -#ifndef __MAINMENUUTILS_H__ -#define __MAINMENUUTILS_H__ - -void HTTPThinkWrapper( void ); -void StopAsyncDNSCheck( void ); -void StartPatchCheck( void ); -void CancelPatchCheckCallback( void ); -void StartDownloadingPatches( void ); -void HandleCanceledDownload( Bool resetDropDown = TRUE ); - -enum OverallStatsPeriod -{ - STATS_TODAY = 0, - STATS_YESTERDAY, - STATS_ALLTIME, - STATS_LASTWEEK, - STATS_MAX -}; - -struct OverallStats -{ - OverallStats(); - Int wins[STATS_MAX]; - Int losses[STATS_MAX]; -}; - -void CheckOverallStats( void ); -void HandleOverallStats( const OverallStats& USA, const OverallStats& China, const OverallStats& GLA ); - -void CheckNumPlayersOnline( void ); -void HandleNumPlayersOnline( Int numPlayersOnline ); - -#endif // __MAINMENUUTILS_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefs.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefs.h deleted file mode 100644 index 56d60fe831e..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefs.h +++ /dev/null @@ -1,303 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PeerDefs.h ////////////////////////////////////////////////////// -// Generals GameSpy Peer (chat) definitions -// Author: Matthew D. Campbell, June 2002 - -#pragma once - -#ifndef __PEERDEFS_H__ -#define __PEERDEFS_H__ - -#include "GameSpy/Peer/Peer.h" -#include "GameSpy/GP/GP.h" - -#include "GameClient/Color.h" -#include "Common/STLTypedefs.h" -#include "GameNetwork/GameSpy/StagingRoomGameInfo.h" - -class GameWindow; -class PSPlayerStats; - -typedef std::set IgnoreList; -typedef std::map SavedIgnoreMap; - -enum RCItemType -{ - ITEM_BUDDY, - ITEM_REQUEST, - ITEM_NONBUDDY, - ITEM_NONE, -}; - -class GameSpyRCMenuData -{ -public: - AsciiString m_nick; - GPProfile m_id; - RCItemType m_itemType; -}; - -class BuddyInfo -{ -public: - GPProfile m_id; - AsciiString m_name; - AsciiString m_email; - AsciiString m_countryCode; - GPEnum m_status; - UnicodeString m_statusString; - UnicodeString m_locationString; -}; -typedef std::map BuddyInfoMap; - -class BuddyMessage -{ -public: - UnsignedInt m_timestamp; - GPProfile m_senderID; - AsciiString m_senderNick; - GPProfile m_recipientID; - AsciiString m_recipientNick; - UnicodeString m_message; -}; -typedef std::list BuddyMessageList; - -class GameSpyGroupRoom -{ -public: - GameSpyGroupRoom() { m_name = AsciiString::TheEmptyString; m_translatedName = UnicodeString::TheEmptyString; m_groupID = m_numWaiting = m_maxWaiting = m_numGames = m_numPlaying = 0; } - AsciiString m_name; - UnicodeString m_translatedName; - Int m_groupID; - Int m_numWaiting; - Int m_maxWaiting; - Int m_numGames; - Int m_numPlaying; -}; -typedef std::map GroupRoomMap; - -class Transport; -class NAT; - -typedef std::map StagingRoomMap; - -class PlayerInfo -{ -public: - PlayerInfo() { m_name = m_locale = AsciiString::TheEmptyString; m_wins = m_losses = m_rankPoints = m_side = m_preorder = m_profileID = m_flags = 0; } - AsciiString m_name; - AsciiString m_locale; - Int m_wins; - Int m_losses; - Int m_profileID; - Int m_flags; - Int m_rankPoints; - Int m_side; - Int m_preorder; - Bool isIgnored( void ); -}; -struct AsciiComparator -{ - bool operator()(AsciiString s1, AsciiString s2) const; -}; - - -typedef std::map PlayerInfoMap; - -enum GameSpyColors { - GSCOLOR_DEFAULT = 0, - GSCOLOR_CURRENTROOM, - GSCOLOR_ROOM, - GSCOLOR_GAME, - GSCOLOR_GAME_FULL, - GSCOLOR_GAME_CRCMISMATCH, - GSCOLOR_PLAYER_NORMAL, - GSCOLOR_PLAYER_OWNER, - GSCOLOR_PLAYER_BUDDY, - GSCOLOR_PLAYER_SELF, - GSCOLOR_PLAYER_IGNORED, - GSCOLOR_CHAT_NORMAL, - GSCOLOR_CHAT_EMOTE, - GSCOLOR_CHAT_OWNER, - GSCOLOR_CHAT_OWNER_EMOTE, - GSCOLOR_CHAT_PRIVATE, - GSCOLOR_CHAT_PRIVATE_EMOTE, - GSCOLOR_CHAT_PRIVATE_OWNER, - GSCOLOR_CHAT_PRIVATE_OWNER_EMOTE, - GSCOLOR_CHAT_BUDDY, - GSCOLOR_CHAT_SELF, - GSCOLOR_ACCEPT_TRUE, - GSCOLOR_ACCEPT_FALSE, - GSCOLOR_MAP_SELECTED, - GSCOLOR_MAP_UNSELECTED, - GSCOLOR_MOTD, - GSCOLOR_MOTD_HEADING, - GSCOLOR_MAX -}; - -extern Color GameSpyColor[GSCOLOR_MAX]; - -enum GameSpyBuddyStatus { - BUDDY_OFFLINE, - BUDDY_ONLINE, - BUDDY_LOBBY, - BUDDY_STAGING, - BUDDY_LOADING, - BUDDY_PLAYING, - BUDDY_MATCHING, - BUDDY_MAX -}; - -// --------------------------------------------------- -// this class holds info used in the main thread -class GameSpyInfoInterface -{ -public: - virtual ~GameSpyInfoInterface() {}; - virtual void reset( void ) {}; - virtual void clearGroupRoomList( void ) = 0; - virtual GroupRoomMap* getGroupRoomList( void ) = 0; - virtual void addGroupRoom( GameSpyGroupRoom room ) = 0; - virtual Bool gotGroupRoomList( void ) = 0; - virtual void joinGroupRoom( Int groupID ) = 0; - virtual void leaveGroupRoom( void ) = 0; - virtual void joinBestGroupRoom( void ) = 0; - virtual void setCurrentGroupRoom( Int groupID ) = 0; - virtual Int getCurrentGroupRoom( void ) = 0; - virtual void updatePlayerInfo( PlayerInfo pi, AsciiString oldNick = AsciiString::TheEmptyString ) = 0; - virtual void playerLeftGroupRoom( AsciiString nick ) = 0; - virtual PlayerInfoMap* getPlayerInfoMap( void ) = 0; - - virtual BuddyInfoMap* getBuddyMap( void ) = 0; - virtual BuddyInfoMap* getBuddyRequestMap( void ) = 0; - virtual BuddyMessageList* getBuddyMessages( void ) = 0; - virtual Bool isBuddy( Int id ) = 0; - - virtual void setLocalName( AsciiString name ) = 0; - virtual AsciiString getLocalName( void ) = 0; - virtual void setLocalProfileID( Int profileID ) = 0; - virtual Int getLocalProfileID( void ) = 0; - virtual AsciiString getLocalEmail( void ) = 0; - virtual void setLocalEmail( AsciiString email ) = 0; - virtual AsciiString getLocalPassword( void ) = 0; - virtual void setLocalPassword( AsciiString passwd ) = 0; - virtual void setLocalBaseName( AsciiString name ) = 0; - virtual AsciiString getLocalBaseName( void ) = 0; - - virtual void setCachedLocalPlayerStats( PSPlayerStats stats ) = 0; - virtual PSPlayerStats getCachedLocalPlayerStats( void ) = 0; - - virtual void clearStagingRoomList( void ) = 0; - virtual StagingRoomMap* getStagingRoomList( void ) = 0; - virtual GameSpyStagingRoom* findStagingRoomByID( Int id ) = 0; - virtual void addStagingRoom( GameSpyStagingRoom room ) = 0; - virtual void updateStagingRoom( GameSpyStagingRoom room ) = 0; - virtual void removeStagingRoom( GameSpyStagingRoom room ) = 0; - virtual Bool hasStagingRoomListChanged( void ) = 0; - virtual void leaveStagingRoom( void ) = 0; - virtual void markAsStagingRoomHost( void ) = 0; - virtual void markAsStagingRoomJoiner( Int game ) = 0; - virtual void sawFullGameList( void ) = 0; - - virtual Bool amIHost( void ) = 0; - virtual GameSpyStagingRoom* getCurrentStagingRoom( void ) = 0; - virtual void setGameOptions( void ) = 0; - virtual Int getCurrentStagingRoomID( void ) = 0; - - virtual void setDisallowAsianText( Bool val ) = 0; - virtual void setDisallowNonAsianText( Bool val ) = 0; - virtual Bool getDisallowAsianText( void ) = 0; - virtual Bool getDisallowNonAsianText(void ) = 0; - - // chat - virtual void registerTextWindow( GameWindow *win ) = 0; - virtual void unregisterTextWindow( GameWindow *win ) = 0; - virtual Int addText( UnicodeString message, Color c, GameWindow *win ) = 0; - virtual void addChat( PlayerInfo p, UnicodeString msg, Bool isPublic, Bool isAction, GameWindow *win ) = 0; - virtual void addChat( AsciiString nick, Int profileID, UnicodeString msg, Bool isPublic, Bool isAction, GameWindow *win ) = 0; - virtual Bool sendChat( UnicodeString message, Bool isAction, GameWindow *playerListbox ) = 0; - - virtual void setMOTD( const AsciiString& motd ) = 0; - virtual const AsciiString& getMOTD( void ) = 0; - - virtual void setConfig( const AsciiString& config ) = 0; - virtual const AsciiString& getConfig( void ) = 0; - - virtual void setPingString( const AsciiString& ping ) = 0; - virtual const AsciiString& getPingString( void ) = 0; - virtual Int getPingValue( const AsciiString& otherPing ) = 0; - - static GameSpyInfoInterface* createNewGameSpyInfoInterface( void ); - - virtual void addToSavedIgnoreList( Int profileID, AsciiString nick ) = 0; - virtual void removeFromSavedIgnoreList( Int profileID ) = 0; - virtual Bool isSavedIgnored( Int profileID ) = 0; - virtual SavedIgnoreMap returnSavedIgnoreList( void ) = 0; - virtual void loadSavedIgnoreList( void ) = 0; - - virtual IgnoreList returnIgnoreList( void ) = 0; - virtual void addToIgnoreList( AsciiString nick ) = 0; - virtual void removeFromIgnoreList( AsciiString nick ) = 0; - virtual Bool isIgnored( AsciiString nick ) = 0; - - virtual void setLocalIPs(UnsignedInt internalIP, UnsignedInt externalIP) = 0; - virtual UnsignedInt getInternalIP(void) = 0; - virtual UnsignedInt getExternalIP(void) = 0; - - virtual Bool isDisconnectedAfterGameStart(Int *reason) const = 0; - virtual void markAsDisconnectedAfterGameStart(Int reason) = 0; - - virtual Bool didPlayerPreorder( Int profileID ) const = 0; - virtual void markPlayerAsPreorder( Int profileID ) = 0; - - virtual void setMaxMessagesPerUpdate( Int num ) = 0; - virtual Int getMaxMessagesPerUpdate( void ) = 0; - - virtual Int getAdditionalDisconnects( void ) = 0; - virtual void clearAdditionalDisconnects( void ) = 0; - virtual void readAdditionalDisconnects( void ) = 0; - virtual void updateAdditionalGameSpyDisconnections(Int count) = 0; -}; - -extern GameSpyInfoInterface *TheGameSpyInfo; - -void WOLDisplayGameOptions( void ); -void WOLDisplaySlotList( void ); -Bool GetLocalChatConnectionAddress(AsciiString serverName, UnsignedShort serverPort, UnsignedInt& localIP); -void SetLobbyAttemptHostJoin(Bool start); -void SendStatsToOtherPlayers(const GameInfo *game); - -class PSPlayerStats; -void GetAdditionalDisconnectsFromUserFile(PSPlayerStats *stats); -extern Int GetAdditionalDisconnectsFromUserFile(Int playerID); - -//------------------------------------------------------------------------- -// These functions set up the globals and threads neccessary for our GameSpy impl. - -void SetUpGameSpy( const char *motdBuffer, const char *configBuffer ); -void TearDownGameSpy( void ); - -#endif // __PEERDEFS_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefsImplementation.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefsImplementation.h deleted file mode 100644 index f086b48b93b..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefsImplementation.h +++ /dev/null @@ -1,184 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PeerDefsImplementation.h ////////////////////////////////////////////////////// -// Generals GameSpy Peer (chat) implementation definitions -// Author: Matthew D. Campbell, Sept 2002 - -#pragma once - -#ifndef __PEERDEFSIMPLEMENTATION_H__ -#define __PEERDEFSIMPLEMENTATION_H__ - -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" - - -class GameSpyInfo : public GameSpyInfoInterface -{ -public: - GameSpyInfo(); - virtual ~GameSpyInfo(); - virtual void reset( void ); - virtual void clearGroupRoomList( void ) { m_groupRooms.clear(); m_gotGroupRoomList = false; } - virtual GroupRoomMap* getGroupRoomList( void ) { return &m_groupRooms; } - virtual void addGroupRoom( GameSpyGroupRoom room ); - virtual Bool gotGroupRoomList( void ) { return m_gotGroupRoomList; } - virtual void joinGroupRoom( Int groupID ); - virtual void leaveGroupRoom( void ); - virtual void joinBestGroupRoom( void ); - virtual void setCurrentGroupRoom( Int groupID ) { m_currentGroupRoomID = groupID; m_playerInfoMap.clear(); } - virtual Int getCurrentGroupRoom( void ) { return m_currentGroupRoomID; } - virtual void updatePlayerInfo( PlayerInfo pi, AsciiString oldNick = AsciiString::TheEmptyString ); - virtual void playerLeftGroupRoom( AsciiString nick ); - virtual PlayerInfoMap* getPlayerInfoMap( void ) { return &m_playerInfoMap; } - - virtual void setLocalName( AsciiString name ) { m_localName = name; } - virtual AsciiString getLocalName( void ) { return m_localName; } - virtual void setLocalProfileID( Int profileID ) { m_localProfileID = profileID; } - virtual Int getLocalProfileID( void ) { return m_localProfileID; } - virtual AsciiString getLocalEmail( void ) { return m_localEmail; } - virtual void setLocalEmail( AsciiString email ) { m_localEmail = email; } - virtual AsciiString getLocalPassword( void ){ return m_localPasswd; } - virtual void setLocalPassword( AsciiString passwd ) { m_localPasswd = passwd; } - virtual void setLocalBaseName( AsciiString name ) { m_localBaseName = name; } - virtual AsciiString getLocalBaseName( void ){ return m_localBaseName; } - - virtual void setCachedLocalPlayerStats( PSPlayerStats stats ) {m_cachedLocalPlayerStats = stats; } - virtual PSPlayerStats getCachedLocalPlayerStats( void ){ return m_cachedLocalPlayerStats; } - - virtual BuddyInfoMap* getBuddyMap( void ) { return &m_buddyMap; } - virtual BuddyInfoMap* getBuddyRequestMap( void ) { return &m_buddyRequestMap; } - virtual BuddyMessageList* getBuddyMessages( void ) { return &m_buddyMessages; } - virtual Bool isBuddy( Int id ); - - virtual void clearStagingRoomList( void ); - virtual StagingRoomMap* getStagingRoomList( void ) { return &m_stagingRooms; } - virtual GameSpyStagingRoom* findStagingRoomByID( Int id ); - virtual void addStagingRoom( GameSpyStagingRoom room ); - virtual void updateStagingRoom( GameSpyStagingRoom room ); - virtual void removeStagingRoom( GameSpyStagingRoom room ); - virtual Bool hasStagingRoomListChanged( void ); - virtual void leaveStagingRoom( void ); - virtual void markAsStagingRoomHost( void ); - virtual void markAsStagingRoomJoiner( Int game ); - virtual Int getCurrentStagingRoomID( void ) { return m_localStagingRoomID; } - - virtual void sawFullGameList( void ) { m_sawFullGameList = TRUE; } - - virtual void setDisallowAsianText( Bool val ); - virtual void setDisallowNonAsianText( Bool val ); - virtual Bool getDisallowAsianText( void ); - virtual Bool getDisallowNonAsianText(void ); - // chat - virtual void registerTextWindow( GameWindow *win ); - virtual void unregisterTextWindow( GameWindow *win ); - virtual Int addText( UnicodeString message, Color c, GameWindow *win ); - virtual void addChat( PlayerInfo p, UnicodeString msg, Bool isPublic, Bool isAction, GameWindow *win ); - virtual void addChat( AsciiString nick, Int profileID, UnicodeString msg, Bool isPublic, Bool isAction, GameWindow *win ); - virtual Bool sendChat( UnicodeString message, Bool isAction, GameWindow *playerListbox ); - - virtual void setMOTD( const AsciiString& motd ); - virtual const AsciiString& getMOTD( void ); - virtual void setConfig( const AsciiString& config ); - virtual const AsciiString& getConfig( void ); - - virtual void setPingString( const AsciiString& ping ) { m_pingString = ping; } - virtual const AsciiString& getPingString( void ) { return m_pingString; } - virtual Int getPingValue( const AsciiString& otherPing ); - - virtual Bool amIHost( void ); - virtual GameSpyStagingRoom* getCurrentStagingRoom( void ); - virtual void setGameOptions( void ); - - virtual void addToIgnoreList( AsciiString nick ); - virtual void removeFromIgnoreList( AsciiString nick ); - virtual Bool isIgnored( AsciiString nick ); - virtual IgnoreList returnIgnoreList( void ); - - virtual void loadSavedIgnoreList( void ); - virtual SavedIgnoreMap returnSavedIgnoreList( void ); - virtual void addToSavedIgnoreList( Int profileID, AsciiString nick); - virtual void removeFromSavedIgnoreList( Int profileID ); - virtual Bool isSavedIgnored( Int profileID ); - virtual void setLocalIPs(UnsignedInt internalIP, UnsignedInt externalIP); - virtual UnsignedInt getInternalIP(void) { return m_internalIP; } - virtual UnsignedInt getExternalIP(void) { return m_externalIP; } - - virtual Bool isDisconnectedAfterGameStart(Int *reason) const { if (reason) *reason = m_disconReason; return m_isDisconAfterGameStart; } - virtual void markAsDisconnectedAfterGameStart(Int reason) { m_isDisconAfterGameStart = TRUE; m_disconReason = reason; } - - virtual Bool didPlayerPreorder( Int profileID ) const; - virtual void markPlayerAsPreorder( Int profileID ); - - virtual void setMaxMessagesPerUpdate( Int num ); - virtual Int getMaxMessagesPerUpdate( void ); - - virtual Int getAdditionalDisconnects( void ); - virtual void clearAdditionalDisconnects( void ); - virtual void readAdditionalDisconnects( void ); - virtual void updateAdditionalGameSpyDisconnections(Int count); -private: - Bool m_sawFullGameList; - Bool m_isDisconAfterGameStart; - Int m_disconReason; - AsciiString m_rawMotd; - AsciiString m_rawConfig; - AsciiString m_pingString; - GroupRoomMap m_groupRooms; - StagingRoomMap m_stagingRooms; - Bool m_stagingRoomsDirty; - BuddyInfoMap m_buddyMap; - BuddyInfoMap m_buddyRequestMap; - PlayerInfoMap m_playerInfoMap; - BuddyMessageList m_buddyMessages; - Int m_currentGroupRoomID; - Bool m_gotGroupRoomList; - AsciiString m_localName; - Int m_localProfileID; - AsciiString m_localPasswd; - AsciiString m_localEmail; - AsciiString m_localBaseName; - PSPlayerStats m_cachedLocalPlayerStats; - Bool m_disallowAsainText; - Bool m_disallowNonAsianText; - UnsignedInt m_internalIP, m_externalIP; - Int m_maxMessagesPerUpdate; - - Int m_joinedStagingRoom; // if we join a staging room, this holds its ID (0 otherwise) - Bool m_isHosting; // if we host, this is true, and - GameSpyStagingRoom m_localStagingRoom; // this holds the GameInfo for it. - Int m_localStagingRoomID; - - IgnoreList m_ignoreList; - SavedIgnoreMap m_savedIgnoreMap; - - std::set m_textWindows; - - std::set m_preorderPlayers; - - Int m_additionalDisconnects; -}; - -#endif // __PEERDEFS_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PeerThread.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PeerThread.h deleted file mode 100644 index 99e7cf47b49..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PeerThread.h +++ /dev/null @@ -1,390 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PeerThread.h ////////////////////////////////////////////////////// -// Generals GameSpy Peer-to-peer chat thread class interface -// Author: Matthew D. Campbell, June 2002 - -#pragma once - -#ifndef __PEERTHREAD_H__ -#define __PEERTHREAD_H__ - -#include "GameSpy/Peer/Peer.h" -#include "GameNetwork/NetworkDefs.h" - -enum SerialAuthResult -{ - SERIAL_NONEXISTENT, - SERIAL_AUTHFAILED, - SERIAL_BANNED, - SERIAL_OK -}; - -// this class encapsulates a request for the peer thread -class PeerRequest -{ -public: - enum - { - PEERREQUEST_LOGIN, // attempt to login - PEERREQUEST_LOGOUT, // log out if connected - PEERREQUEST_MESSAGEPLAYER, - PEERREQUEST_MESSAGEROOM, - PEERREQUEST_JOINGROUPROOM, - PEERREQUEST_LEAVEGROUPROOM, - PEERREQUEST_STARTGAMELIST, - PEERREQUEST_STOPGAMELIST, - PEERREQUEST_CREATESTAGINGROOM, - PEERREQUEST_SETGAMEOPTIONS, - PEERREQUEST_JOINSTAGINGROOM, - PEERREQUEST_LEAVESTAGINGROOM, - PEERREQUEST_UTMPLAYER, - PEERREQUEST_UTMROOM, - PEERREQUEST_STARTGAME, - PEERREQUEST_STARTQUICKMATCH, - PEERREQUEST_WIDENQUICKMATCHSEARCH, - PEERREQUEST_STOPQUICKMATCH, - PEERREQUEST_PUSHSTATS, - PEERREQUEST_GETEXTENDEDSTAGINGROOMINFO, - PEERREQUEST_MAX - } peerRequestType; - - std::string nick; // only used by login, but must be outside the union b/c of copy constructor - std::wstring text; // can't be in a union - std::string password; - std::string email; - std::string id; - - // gameopts - std::string options; // full string for UTMs - std::string ladderIP; - std::string hostPingStr; - std::string gameOptsMapName; - std::string gameOptsPlayerNames[MAX_SLOTS]; - - std::vector qmMaps; - - union - { - struct - { - Int profileID; - } login; - - struct - { - Int id; - } groupRoom; - - struct - { - Bool restrictGameList; - } gameList; - - struct - { - Bool isAction; - } message; - - struct - { - Int id; - } stagingRoom; - - struct - { - UnsignedInt exeCRC; - UnsignedInt iniCRC; - UnsignedInt gameVersion; - Bool allowObservers; - UnsignedShort ladPort; - UnsignedInt ladPassCRC; - Bool restrictGameList; - } stagingRoomCreation; - - struct - { - Int wins[MAX_SLOTS]; - Int losses[MAX_SLOTS]; - Int profileID[MAX_SLOTS]; - Int faction[MAX_SLOTS]; - Int color[MAX_SLOTS]; - Int numPlayers; - Int maxPlayers; - Int numObservers; - } gameOptions; - - struct - { - Bool isStagingRoom; - } UTM; - - struct - { - Int minPointPercentage, maxPointPercentage, points; - Int widenTime; - Int ladderID; - UnsignedInt ladderPassCRC; - Int maxPing; - Int maxDiscons, discons; - char pings[17]; // 8 servers (0-ff), 1 NULL - Int numPlayers; - Int botID; - Int roomID; - Int side; - Int color; - Int NAT; - UnsignedInt exeCRC; - UnsignedInt iniCRC; - } QM; - - struct - { - Int locale; - Int wins; - Int losses; - Int rankPoints; - Int side; - Bool preorder; - } statsToPush; - - }; -}; - -//------------------------------------------------------------------------- - -enum DisconnectReason -{ - DISCONNECT_NICKTAKEN = 1, - DISCONNECT_BADNICK, - DISCONNECT_LOSTCON, - DISCONNECT_COULDNOTCONNECT, - DISCONNECT_GP_LOGIN_TIMEOUT, - DISCONNECT_GP_LOGIN_BAD_NICK, - DISCONNECT_GP_LOGIN_BAD_EMAIL, - DISCONNECT_GP_LOGIN_BAD_PASSWORD, - DISCONNECT_GP_LOGIN_BAD_PROFILE, - DISCONNECT_GP_LOGIN_PROFILE_DELETED, - DISCONNECT_GP_LOGIN_CONNECTION_FAILED, - DISCONNECT_GP_LOGIN_SERVER_AUTH_FAILED, - DISCONNECT_SERIAL_INVALID, - DISCONNECT_SERIAL_NOT_PRESENT, - DISCONNECT_SERIAL_BANNED, - DISCONNECT_GP_NEWUSER_BAD_NICK, - DISCONNECT_GP_NEWUSER_BAD_PASSWORD, - DISCONNECT_GP_NEWPROFILE_BAD_NICK, - DISCONNECT_GP_NEWPROFILE_BAD_OLD_NICK, - DISCONNECT_MAX, -}; - -enum QMStatus -{ - QM_IDLE, - QM_JOININGQMCHANNEL, - QM_LOOKINGFORBOT, - QM_SENTINFO, - QM_WORKING, - QM_POOLSIZE, - QM_WIDENINGSEARCH, - QM_MATCHED, - QM_INCHANNEL, - QM_NEGOTIATINGFIREWALLS, - QM_STARTINGGAME, - QM_COULDNOTFINDBOT, - QM_COULDNOTFINDCHANNEL, - QM_COULDNOTNEGOTIATEFIREWALLS, - QM_STOPPED, -}; - -// this class encapsulates an action the peer thread wants from the UI -class PeerResponse -{ -public: - enum - { - PEERRESPONSE_LOGIN, - PEERRESPONSE_DISCONNECT, - PEERRESPONSE_MESSAGE, - PEERRESPONSE_GROUPROOM, - PEERRESPONSE_STAGINGROOM, - PEERRESPONSE_STAGINGROOMLISTCOMPLETE, - PEERRESPONSE_STAGINGROOMPLAYERINFO, - PEERRESPONSE_JOINGROUPROOM, - PEERRESPONSE_CREATESTAGINGROOM, - PEERRESPONSE_JOINSTAGINGROOM, - PEERRESPONSE_PLAYERJOIN, - PEERRESPONSE_PLAYERLEFT, - PEERRESPONSE_PLAYERCHANGEDNICK, - PEERRESPONSE_PLAYERINFO, - PEERRESPONSE_PLAYERCHANGEDFLAGS, - PEERRESPONSE_ROOMUTM, - PEERRESPONSE_PLAYERUTM, - PEERRESPONSE_QUICKMATCHSTATUS, - PEERRESPONSE_GAMESTART, - PEERRESPONSE_FAILEDTOHOST, - PEERRESPONSE_MAX - } peerResponseType; - - std::string groupRoomName; // can't be in union - - std::string nick; // can't be in a union - std::string oldNick; // can't be in a union - std::wstring text; // can't be in a union - std::string locale; // can't be in a union - - std::string stagingServerGameOptions; // full string from UTMs - - // game opts sent with PEERRESPONSE_STAGINGROOM - std::wstring stagingServerName; - std::string stagingServerPingString; - std::string stagingServerLadderIP; - std::string stagingRoomMapName; - - // game opts sent with PEERRESPONSE_STAGINGROOMPLAYERINFO - std::string stagingRoomPlayerNames[MAX_SLOTS]; - - std::string command; - std::string commandOptions; - - union - { - struct - { - DisconnectReason reason; - } discon; - - struct - { - Int id; - Int numWaiting; - Int maxWaiting; - Int numGames; - Int numPlaying; - } groupRoom; - - struct - { - Int id; - Bool ok; - } joinGroupRoom; - - struct - { - Int result; - } createStagingRoom; - - struct - { - Int id; - Bool ok; - Bool isHostPresent; - Int result; // for failures - } joinStagingRoom; - - struct - { - Bool isPrivate; - Bool isAction; - Int profileID; - } message; - - struct - { - Int profileID; - Int wins; - Int losses; - RoomType roomType; - Int flags; - UnsignedInt IP; - Int rankPoints; - Int side; - Int preorder; - UnsignedInt internalIP; // for us, on connection - UnsignedInt externalIP; // for us, on connection - } player; - - struct - { - Int id; - Int action; - Bool isStaging; - Bool requiresPassword; - Bool allowObservers; - UnsignedInt version; - UnsignedInt exeCRC; - UnsignedInt iniCRC; - UnsignedShort ladderPort; - Int wins[MAX_SLOTS]; - Int losses[MAX_SLOTS]; - Int profileID[MAX_SLOTS]; - Int faction[MAX_SLOTS]; - Int color[MAX_SLOTS]; - Int numPlayers; - Int numObservers; - Int maxPlayers; - Int percentComplete; - } stagingRoom; - - struct - { - QMStatus status; - Int poolSize; - Int mapIdx; // when matched - Int seed; // when matched - UnsignedInt IP[MAX_SLOTS]; // when matched - Int side[MAX_SLOTS]; // when matched - Int color[MAX_SLOTS]; // when matched - Int nat[MAX_SLOTS]; - } qmStatus; - }; -}; - -//------------------------------------------------------------------------- - -// this is the actual message queue used to pass messages between threads -class GameSpyPeerMessageQueueInterface -{ -public: - virtual ~GameSpyPeerMessageQueueInterface() {} - virtual void startThread( void ) = 0; - virtual void endThread( void ) = 0; - virtual Bool isThreadRunning( void ) = 0; - virtual Bool isConnected( void ) = 0; - virtual Bool isConnecting( void ) = 0; - - virtual void addRequest( const PeerRequest& req ) = 0; - virtual Bool getRequest( PeerRequest& req ) = 0; - - virtual void addResponse( const PeerResponse& resp ) = 0; - virtual Bool getResponse( PeerResponse& resp ) = 0; - - virtual SerialAuthResult getSerialAuthResult( void ) = 0; - - static GameSpyPeerMessageQueueInterface* createNewMessageQueue( void ); -}; - -extern GameSpyPeerMessageQueueInterface *TheGameSpyPeerMessageQueue; - -#endif // __PEERTHREAD_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageDefs.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageDefs.h deleted file mode 100644 index 68b27ed94cb..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageDefs.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PersistentStorageDefs.h ////////////////////////////////////////////////////// -// Generals GameSpy Persistent Storage definitions -// Author: Matthew D. Campbell, July 2002 - -#pragma once - -#ifndef __PERSISTENTSTORAGEDEFS_H__ -#define __PERSISTENTSTORAGEDEFS_H__ - -enum LocaleType -{ - LOC_UNKNOWN = 0, - LOC_MIN = 1, - LOC_MAX = 37 -}; - -void HandlePersistentStorageResponses(void); -void UpdateLocalPlayerStats(void); - -void SetLookAtPlayer( Int id, AsciiString nick ); -void PopulatePlayerInfoWindows( AsciiString parentWindowName ); - -#endif // __PERSISTENTSTORAGEDEFS_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageThread.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageThread.h deleted file mode 100644 index 0d500f1e24e..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageThread.h +++ /dev/null @@ -1,187 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PersistentStorageThread.h ////////////////////////////////////////////////////// -// Generals GameSpy Persistent Storage thread class interface -// Author: Matthew D. Campbell, July 2002 - -#pragma once - -#ifndef __PERSISTENTSTORAGETHREAD_H__ -#define __PERSISTENTSTORAGETHREAD_H__ - -#include "GameSpy/gstats/gpersist.h" - -#define MAX_BUDDY_CHAT_LEN 128 - -typedef std::map PerGeneralMap; -// this structure holds all info on a player that is stored online -class PSPlayerStats -{ -public: - PSPlayerStats( void ); - PSPlayerStats( const PSPlayerStats& other ); - void reset(void); - - Int id; - PerGeneralMap wins; - PerGeneralMap losses; - PerGeneralMap games; - PerGeneralMap duration; - PerGeneralMap unitsKilled; - PerGeneralMap unitsLost; - PerGeneralMap unitsBuilt; - PerGeneralMap buildingsKilled; - PerGeneralMap buildingsLost; - PerGeneralMap buildingsBuilt; - PerGeneralMap earnings; - PerGeneralMap techCaptured; - PerGeneralMap discons; - PerGeneralMap desyncs; - PerGeneralMap surrenders; - PerGeneralMap gamesOf2p; - PerGeneralMap gamesOf3p; - PerGeneralMap gamesOf4p; - PerGeneralMap gamesOf5p; - PerGeneralMap gamesOf6p; - PerGeneralMap gamesOf7p; - PerGeneralMap gamesOf8p; - PerGeneralMap customGames; - PerGeneralMap QMGames; - Int locale; - Int gamesAsRandom; - std::string options; - std::string systemSpec; - Real lastFPS; - Int lastGeneral; - Int gamesInRowWithLastGeneral; - Int challengeMedals; - Int battleHonors; - Int QMwinsInARow; - Int maxQMwinsInARow; - - Int winsInARow; - Int maxWinsInARow; - Int lossesInARow; - Int maxLossesInARow; - Int disconsInARow; - Int maxDisconsInARow; - Int desyncsInARow; - Int maxDesyncsInARow; - - Int builtParticleCannon; - Int builtNuke; - Int builtSCUD; - - Int lastLadderPort; - std::string lastLadderHost; - - void incorporate( const PSPlayerStats& other ); -}; - -// this class encapsulates a request for the thread -class PSRequest -{ -public: - PSRequest(); - enum - { - PSREQUEST_READPLAYERSTATS, // read stats for a player - PSREQUEST_UPDATEPLAYERSTATS, // update stats on the server - PSREQUEST_UPDATEPLAYERLOCALE, // update locale on the server - PSREQUEST_READCDKEYSTATS, // read stats for a cdkey - PSREQUEST_SENDGAMERESTOGAMESPY, // report game results to GameSpy - PSREQUEST_MAX - } requestType; - - // player stats for the *PLAYERSTATS - PSPlayerStats player; - - // cdkey for READCDKEYSTATS; - std::string cdkey; - - // our info for UPDATEPLAYERSTATS - std::string nick; - std::string password; - std::string email; - Bool addDiscon; - Bool addDesync; - Int lastHouse; - - // for GameRes - std::string results; -}; - -//------------------------------------------------------------------------- - -// this class encapsulates a response from the thread -class PSResponse -{ -public: - enum - { - PSRESPONSE_PLAYERSTATS, - PSRESPONSE_COULDNOTCONNECT, - PSRESPONSE_PREORDER, - PSRESPONSE_MAX - } responseType; - - // player stats for the *PLAYERSTATS - PSPlayerStats player; - - // preorder flag - Bool preorder; -}; - -//------------------------------------------------------------------------- - -// this is the actual message queue used to pass messages between threads -class GameSpyPSMessageQueueInterface -{ -public: - virtual ~GameSpyPSMessageQueueInterface() {} - virtual void startThread( void ) = 0; - virtual void endThread( void ) = 0; - virtual Bool isThreadRunning( void ) = 0; - - virtual void addRequest( const PSRequest& req ) = 0; - virtual Bool getRequest( PSRequest& req ) = 0; - - virtual void addResponse( const PSResponse& resp ) = 0; - virtual Bool getResponse( PSResponse& resp ) = 0; - - // called from the main thread - virtual void trackPlayerStats( PSPlayerStats stats ) = 0; - virtual PSPlayerStats findPlayerStatsByID( Int id ) = 0; - - static GameSpyPSMessageQueueInterface* createNewMessageQueue( void ); - - static std::string formatPlayerKVPairs( PSPlayerStats stats ); - static PSPlayerStats parsePlayerKVPairs( std::string kvPairs ); -}; - -extern GameSpyPSMessageQueueInterface *TheGameSpyPSMessageQueue; - - -#endif // __PERSISTENTSTORAGETHREAD_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PingThread.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PingThread.h deleted file mode 100644 index 0ed12049189..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PingThread.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PingThread.h ////////////////////////////////////////////////////// -// Generals ping thread class interface -// Author: Matthew D. Campbell, August 2002 -// Note: adapted from WOLAPI - -#pragma once - -#ifndef __PINGTHREAD_H__ -#define __PINGTHREAD_H__ - -// this class encapsulates a request for the thread -class PingRequest -{ -public: - std::string hostname; - Int repetitions; - Int timeout; -}; - -//------------------------------------------------------------------------- - -// this class encapsulates a response from the thread -class PingResponse -{ -public: - std::string hostname; - Int avgPing; - Int repetitions; -}; - -//------------------------------------------------------------------------- - -// this is the actual message queue used to pass messages between threads -class PingerInterface -{ -public: - virtual ~PingerInterface() {} - virtual void startThreads( void ) = 0; - virtual void endThreads( void ) = 0; - virtual Bool areThreadsRunning( void ) = 0; - - virtual void addRequest( const PingRequest& req ) = 0; - virtual Bool getRequest( PingRequest& resp ) = 0; - - virtual void addResponse( const PingResponse& resp ) = 0; - virtual Bool getResponse( PingResponse& resp ) = 0; - - static PingerInterface* createNewPingerInterface( void ); - - virtual Bool arePingsInProgress( void ) = 0; - virtual Int getPing( AsciiString hostname ) = 0; - virtual void clearPingMap( void ) = 0; - virtual AsciiString getPingString( Int timeout ) = 0; -}; - -extern PingerInterface *ThePinger; - - -#endif // __PINGTHREAD_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/StagingRoomGameInfo.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/StagingRoomGameInfo.h deleted file mode 100644 index a66e9a1e180..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/StagingRoomGameInfo.h +++ /dev/null @@ -1,161 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: StagingRoomGameInfo.h ////////////////////////////////////////////////////// -// Generals GameSpy GameInfo -// Author: Matthew D. Campbell, Sept 2002 - -#pragma once - -#ifndef __STAGINGROOMGAMEINFO_H__ -#define __STAGINGROOMGAMEINFO_H__ - -#include "GameNetwork/GameInfo.h" -#include "GameNetwork/Transport.h" - -class GameSpyGameSlot : public GameSlot -{ -public: - GameSpyGameSlot(); - Int getProfileID( void ) const { return m_profileID; } - void setProfileID( Int id ) { m_profileID = id; } - AsciiString getLoginName( void ) const { return m_gameSpyLogin; } - void setLoginName( AsciiString name ) { m_gameSpyLogin = name; } - AsciiString getLocale( void ) const { return m_gameSpyLocale; } - void setLocale( AsciiString name ) { m_gameSpyLocale = name; } - Int getWins( void ) const { return m_wins; } - Int getLosses( void ) const { return m_losses; } - void setWins( Int wins ) { m_wins = wins; } - void setLosses( Int losses ) { m_losses = losses; } - - Int getSlotRankPoints( void ) const { return m_rankPoints; } - Int getFavoriteSide( void ) const { return m_favoriteSide; } - void setSlotRankPoints( Int val ) { m_rankPoints = val; } - void setFavoriteSide( Int val ) { m_favoriteSide = val; } - - void setPingString( AsciiString pingStr ); - inline AsciiString getPingString( void ) const { return m_pingStr; } - inline Int getPingAsInt( void ) const { return m_pingInt; } - -protected: - Int m_profileID; - AsciiString m_gameSpyLogin; - AsciiString m_gameSpyLocale; - - AsciiString m_pingStr; - Int m_pingInt; - Int m_wins, m_losses; - Int m_rankPoints, m_favoriteSide; -}; - -/** - * GameSpyStagingRoom class - maintains information about the GameSpy game and - * the contents of its slot list throughout the game. - */ -class GameSpyStagingRoom : public GameInfo -{ -private: - GameSpyGameSlot m_GameSpySlot[MAX_SLOTS]; ///< The GameSpy Games Slot List - UnicodeString m_gameName; - Int m_id; - Transport *m_transport; - AsciiString m_localName; - Bool m_requiresPassword; - Bool m_allowObservers; - UnsignedInt m_version; - UnsignedInt m_exeCRC; - UnsignedInt m_iniCRC; - Bool m_isQM; - - AsciiString m_ladderIP; - AsciiString m_pingStr; - Int m_pingInt; - UnsignedShort m_ladderPort; - - Int m_reportedNumPlayers; - Int m_reportedMaxPlayers; - Int m_reportedNumObservers; - -public: - GameSpyStagingRoom(); - virtual void reset( void ); - - void cleanUpSlotPointers(void); - inline void setID(Int id) { m_id = id; } - inline Int getID( void ) const { return m_id; } - - inline void setHasPassword(Bool val) { m_requiresPassword = val; } - inline Bool getHasPassword(void) const { return m_requiresPassword; } - inline void setAllowObservers(Bool val) { m_allowObservers = val; } - inline Bool getAllowObservers(void) const { return m_allowObservers; } - - inline void setVersion(UnsignedInt val) { m_version = val; } - inline UnsignedInt getVersion(void) const { return m_version; } - inline void setExeCRC(UnsignedInt val) { m_exeCRC = val; } - inline UnsignedInt getExeCRC(void) const { return m_exeCRC; } - inline void setIniCRC(UnsignedInt val) { m_iniCRC = val; } - inline UnsignedInt getIniCRC(void) const { return m_iniCRC; } - - inline void setReportedNumPlayers(Int val) { m_reportedNumPlayers = val; } - inline Int getReportedNumPlayers(void) const { return m_reportedNumPlayers; } - - inline void setReportedMaxPlayers(Int val) { m_reportedMaxPlayers = val; } - inline Int getReportedMaxPlayers(void) const { return m_reportedMaxPlayers; } - - inline void setReportedNumObservers(Int val) { m_reportedNumObservers = val; } - inline Int getReportedNumObservers(void) const { return m_reportedNumObservers; } - - inline void setLadderIP( AsciiString ladderIP ) { m_ladderIP = ladderIP; } - inline AsciiString getLadderIP( void ) const { return m_ladderIP; } - inline void setLadderPort( UnsignedShort ladderPort ) { m_ladderPort = ladderPort; } - inline UnsignedShort getLadderPort( void ) const { return m_ladderPort; } - void setPingString( AsciiString pingStr ); - inline AsciiString getPingString( void ) const { return m_pingStr; } - inline Int getPingAsInt( void ) const { return m_pingInt; } - - virtual Bool amIHost( void ) const; ///< Convenience function - is the local player the game host? - - GameSpyGameSlot *getGameSpySlot( Int index ); - - AsciiString generateGameSpyGameResultsPacket( void ); - AsciiString generateLadderGameResultsPacket( void ); - void markGameAsQM( void ) { m_isQM = TRUE; } - Bool isQMGame( void ) { return m_isQM; } - - virtual void init(void); - virtual void resetAccepted(void); ///< Reset the accepted flag on all players - - virtual void startGame(Int gameID); ///< Mark our game as started and record the game ID. - void launchGame( void ); ///< NAT negotiation has finished - really start - virtual Int getLocalSlotNum( void ) const; ///< Get the local slot number, or -1 if we're not present - - inline void setGameName( UnicodeString name ) { m_gameName = name; } - inline UnicodeString getGameName( void ) const { return m_gameName; } - - inline void setLocalName( AsciiString name ) { m_localName = name; } -}; - -extern GameSpyStagingRoom *TheGameSpyGame; - -#endif // __STAGINGROOMGAMEINFO_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/ThreadUtils.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/ThreadUtils.h deleted file mode 100644 index be97c956eba..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/ThreadUtils.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ThreadUtils.h ////////////////////////////////////////////////////// -// Generals GameSpy thread utils -// Author: Matthew D. Campbell, July 2002 - -#pragma once - -#ifndef __GAMESPY_THREADUTILS_H__ -#define __GAMESPY_THREADUTILS_H__ - -std::wstring MultiByteToWideCharSingleLine( const char *orig ); -std::string WideCharStringToMultiByte( const WideChar *orig ); - -#endif // __GAMESPY_THREADUTILS_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpyChat.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpyChat.h deleted file mode 100644 index e68b6ad7be3..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpyChat.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameSpyChat.h ////////////////////////////////////////////////////// -// Generals GameSpy Chat -// Author: Matthew D. Campbell, February 2002 - -#pragma once - -#ifndef __GAMESPYCHAT_H__ -#define __GAMESPYCHAT_H__ - -#include "GameSpy/Peer/Peer.h" - -class GameWindow; -class WindowLayout; - -Bool GameSpySendChat(UnicodeString message, Bool isEmote, GameWindow *playerListbox = NULL); -void GameSpyAddText( UnicodeString message, GameSpyColors color = GSCOLOR_DEFAULT ); - -extern GameWindow *progressTextWindow; ///< Text box on the progress screen -extern GameWindow *quickmatchTextWindow; ///< Text box on the quickmatch screen -extern GameWindow *quickmatchTextWindow; ///< Text box on the quickmatch screen -extern GameWindow *listboxLobbyChat; ///< Chat box on the custom lobby screen -extern GameWindow *listboxLobbyPlayers; ///< Player box on the custom lobby screen -extern GameWindow *listboxLobbyGames; ///< Game box on the custom lobby screen -extern GameWindow *listboxLobbyChatChannels; ///< Chat channel box on the custom lobby screen -extern GameWindow *listboxGameSetupChat; ///< Chat box on the custom game setup screen -extern WindowLayout *WOLMapSelectLayout; ///< Map selection overlay - -void RoomMessageCallback(PEER peer, RoomType roomType, - const char * nick, const char * message, - MessageType messageType, void * param); ///< Called when a message arrives in a room. - -void PlayerMessageCallback(PEER peer, const char * nick, - const char * message, MessageType messageType, - void * param); ///< Called when a private message is received from another player. - -#endif // __GAMESPYCHAT_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpyGP.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpyGP.h deleted file mode 100644 index d54c71a96fb..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpyGP.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameSpyGP.h ////////////////////////////////////////////////////// -// Generals GameSpy GP (Buddy) -// Author: Matthew D. Campbell, March 2002 - -#pragma once - -#ifndef __GAMESPYGP_H__ -#define __GAMESPYGP_H__ - -#include "GameSpy/GP/GP.h" - -void GPRecvBuddyRequestCallback(GPConnection * connection, GPRecvBuddyRequestArg * arg, void * param); -void GPRecvBuddyMessageCallback(GPConnection * pconnection, GPRecvBuddyMessageArg * arg, void * param); -void GPRecvBuddyStatusCallback(GPConnection * connection, GPRecvBuddyStatusArg * arg, void * param); -void GPErrorCallback(GPConnection * pconnection, GPErrorArg * arg, void * param); -void GPConnectCallback(GPConnection * pconnection, GPConnectResponseArg * arg, void * param); -void GameSpyUpdateBuddyOverlay(void); - -extern GPConnection *TheGPConnection; - -Bool IsGameSpyBuddy(GPProfile id); - -#endif // __GAMESPYGP_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpyGameInfo.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpyGameInfo.h deleted file mode 100644 index 1673b8ba15a..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpyGameInfo.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameSpyGameInfo.h ////////////////////////////////////////////////////// -// Generals GameSpy game setup information -// Author: Matthew D. Campbell, February 2002 - -#pragma once - -#error this file is obsolete - -#ifndef __GAMESPYGAMEINFO_H__ -#define __GAMESPYGAMEINFO_H__ - -#include "GameSpy/Peer/Peer.h" - -#include "GameNetwork/GameInfo.h" - -class Transport; -class NAT; - -class GameSpyGameSlot : public GameSlot -{ -public: - GameSpyGameSlot(); - Int getProfileID( void ) { return m_profileID; } - void setProfileID( Int id ) { m_profileID = id; } - AsciiString getLoginName( void ) { return m_gameSpyLogin; } - void setLoginName( AsciiString name ) { m_gameSpyLogin = name; } - AsciiString getLocale( void ) { return m_gameSpyLocale; } - void setLocale( AsciiString name ) { m_gameSpyLocale = name; } -protected: - Int m_profileID; - AsciiString m_gameSpyLogin; - AsciiString m_gameSpyLocale; -}; - -/** - * GameSpyGameInfo class - maintains information about the GameSpy game and - * the contents of its slot list throughout the game. - */ -class GameSpyGameInfo : public GameInfo -{ -private: - GameSpyGameSlot m_GameSpySlot[MAX_SLOTS]; ///< The GameSpy Games Slot List - SBServer m_server; - Bool m_hasBeenQueried; - Transport *m_transport; - Bool m_isQM; - -public: - GameSpyGameInfo(); - - inline void setServer(SBServer server) { m_server = server; } - inline SBServer getServer( void ) { return m_server; } - - AsciiString generateGameResultsPacket( void ); - - virtual void init(void); - virtual void resetAccepted(void); ///< Reset the accepted flag on all players - - void markGameAsQM( void ) { m_isQM = TRUE; } - virtual void startGame(Int gameID); ///< Mark our game as started and record the game ID. - virtual Int getLocalSlotNum( void ) const; ///< Get the local slot number, or -1 if we're not present - - void gotGOACall( void ); ///< Mark the game info as having been queried -}; - -extern GameSpyGameInfo *TheGameSpyGame; - -void WOLDisplayGameOptions( void ); -void WOLDisplaySlotList( void ); -void GameSpyStartGame( void ); -void GameSpyLaunchGame( void ); -Bool GetLocalChatConnectionAddress(AsciiString serverName, UnsignedShort serverPort, UnsignedInt& localIP); - -#endif // __LANGAMEINFO_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpyOverlay.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpyOverlay.h deleted file mode 100644 index f2890111495..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpyOverlay.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GamespyOverlay.h ////////////////////////////////////////////////////// -// Generals GameSpy overlay screens -// Author: Matthew D. Campbell, March 2002 - -#pragma once - -#ifndef __GAMESPYOVERLAY_H__ -#define __GAMESPYOVERLAY_H__ - -#include "Common/NameKeyGenerator.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" - -void ClearGSMessageBoxes( void ); ///< Tear down any GS message boxes (e.g. in case we have a new one to put up) -void GSMessageBoxOk(UnicodeString titleString,UnicodeString bodyString, GameWinMsgBoxFunc okFunc = NULL); ///< Display a Message box with Ok button and track it -void GSMessageBoxOkCancel(UnicodeString title, UnicodeString message, GameWinMsgBoxFunc okFunc, GameWinMsgBoxFunc cancelFunc); ///< Display a Message box with Ok/Cancel buttons and track it -void GSMessageBoxYesNo(UnicodeString title, UnicodeString message, GameWinMsgBoxFunc yesFunc, GameWinMsgBoxFunc noFunc); ///< Display a Message box with Yes/No buttons and track it -void RaiseGSMessageBox( void ); ///< Bring GS message box to the foreground (if we transition screens while a message box is up) - -enum GSOverlayType -{ - GSOVERLAY_PLAYERINFO, - GSOVERLAY_MAPSELECT, - GSOVERLAY_BUDDY, - GSOVERLAY_PAGE, - GSOVERLAY_GAMEOPTIONS, - GSOVERLAY_GAMEPASSWORD, - GSOVERLAY_LADDERSELECT, - GSOVERLAY_LOCALESELECT, - GSOVERLAY_OPTIONS, - GSOVERLAY_MAX -}; - -void GameSpyOpenOverlay( GSOverlayType ); -void GameSpyCloseOverlay( GSOverlayType ); -void GameSpyCloseAllOverlays( void ); -Bool GameSpyIsOverlayOpen( GSOverlayType ); -void GameSpyToggleOverlay( GSOverlayType ); -void GameSpyUpdateOverlays( void ); -void ReOpenPlayerInfo( void ); -void CheckReOpenPlayerInfo(void ); -#endif // __GAMESPYOVERLAY_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpyPersistentStorage.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpyPersistentStorage.h deleted file mode 100644 index d16363b63ec..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpyPersistentStorage.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameSpyPersistentStorage.h ////////////////////////////////////////////////////// -// Generals GameSpy Persistent Storage -// Author: Matthew D. Campbell, March 2002 - -#pragma once - -#ifndef __GAMESPYPersistentStorage_H__ -#define __GAMESPYPersistentStorage_H__ - -class GameSpyPlayerInfoInterface : public SubsystemInterface -{ -public: - virtual ~GameSpyPlayerInfoInterface() { }; - - virtual void init( void ) = 0; - virtual void reset( void ) = 0; - virtual void update( void ) = 0; - - virtual void setLocale( AsciiString locale, Bool setOnServer = true ) = 0; - virtual AsciiString getLocale( void ) = 0; - virtual void setWins( Int wins, Bool setOnServer = true ) = 0; - virtual Int getWins( void ) = 0; - virtual void setLosses( Int losses, Bool setOnServer = true ) = 0; - virtual Int getLosses( void ) = 0; - - virtual void readFromServer( void ) = 0; - - virtual void threadReadFromServer( void ) = 0; - virtual void threadSetLocale( AsciiString val ) = 0; - virtual void threadSetWins ( AsciiString val ) = 0; - virtual void threadSetLosses( AsciiString val ) = 0; -}; - -GameSpyPlayerInfoInterface *createGameSpyPlayerInfo( void ); - -extern GameSpyPlayerInfoInterface *TheGameSpyPlayerInfo; - -#endif // __GAMESPYPersistentStorage_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpyThread.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpyThread.h deleted file mode 100644 index 2a06a2ddeb5..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpyThread.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameSpyThread.h ////////////////////////////////////////////////////// -// Generals GameSpy thread class -// Author: Matthew D. Campbell, March 2002 - -#pragma once - -#ifndef __GAMESPYTHREAD_H__ -#define __GAMESPYTHREAD_H__ - -#include "mutex.h" -#include "thread.h" - -class GameSpyThreadClass : public ThreadClass -{ - -public: - GameSpyThreadClass::GameSpyThreadClass() : ThreadClass() { m_doLogin = false; m_readStats = false; m_updateWins = false; m_updateLosses = false; m_updateLocale = false; m_showLocaleSelect = false; m_nextShellScreen.clear(); } - void queueLogin(AsciiString nick, AsciiString pass, AsciiString email) { m_nick = nick; m_pass = pass; m_email = email; m_doLogin = true; } - void queueReadPersistentStatsFromServer( void ) { m_readStats = true; } - void queueUpdateLocale( AsciiString locale ) { m_locale = locale; m_updateLocale = true; } - void queueUpdateWins ( AsciiString wins ) { m_wins = wins; m_updateWins = true; } - void queueUpdateLosses( AsciiString losses ) { m_losses = losses; m_updateLosses = true; } - - void Thread_Function(); - - AsciiString getNextShellScreen( void ); - Bool showLocaleSelect( void ); - - void setNextShellScreen( AsciiString nextShellScreen ); - void setShowLocaleSelect( Bool val ); - -private: - AsciiString m_nick, m_pass, m_email; - Bool m_doLogin, m_readStats, m_updateWins, m_updateLosses, m_updateLocale; - AsciiString m_locale, m_wins, m_losses; - AsciiString m_nextShellScreen; - Bool m_showLocaleSelect; -}; - -extern GameSpyThreadClass *TheGameSpyThread; -extern MutexClass TheGameSpyMutex; - -#endif // __GAMESPYTHREAD_H__ diff --git a/Generals/Code/GameEngine/Include/GameNetwork/NAT.h b/Generals/Code/GameEngine/Include/GameNetwork/NAT.h deleted file mode 100644 index 802c3d68623..00000000000 --- a/Generals/Code/GameEngine/Include/GameNetwork/NAT.h +++ /dev/null @@ -1,162 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: NAT.h ///////////////////////////////////////////////////////////////////////////////// -// Author: Bryan Cleveland April 2002 -// Desc: Resolves NAT'd IPs and port numbers for the other players in a game. -/////////////////////////////////////////////////////////////////////////////////////////////////// - -#pragma once - -#ifndef __NAT_H -#define __NAT_H - -#include "Lib\BaseType.h" -#include "GameNetwork/NetworkInterface.h" -#include "GameNetwork/FirewallHelper.h" - -class Transport; -class GameSlot; - -enum NATStateType { - NATSTATE_IDLE, - NATSTATE_DOCONNECTIONPATHS, - NATSTATE_WAITFORSTATS, - NATSTATE_DONE, - NATSTATE_FAILED -}; - -enum NATConnectionState { - NATCONNECTIONSTATE_NOSTATE, - NATCONNECTIONSTATE_WAITINGTOBEGIN, -// NATCONNECTIONSTATE_NETGEARDELAY, - NATCONNECTIONSTATE_WAITINGFORMANGLERRESPONSE, - NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT, - NATCONNECTIONSTATE_WAITINGFORRESPONSE, - NATCONNECTIONSTATE_DONE, - NATCONNECTIONSTATE_FAILED -}; - -struct ConnectionNodeType { - FirewallHelperClass::tFirewallBehaviorType m_behavior; ///< the NAT/Firewall behavior of this node. - UnsignedInt m_slotIndex; ///< the player list index of this node. -}; - -class NAT { -public: - NAT(); - virtual ~NAT(); - - NATStateType update(); - - void attachSlotList(GameSlot **slotList, Int localSlot, UnsignedInt localIP); - void establishConnectionPaths(); - - Int getSlotPort(Int slot); - Transport * getTransport(); ///< return the newly created Transport layer that has all the connections and whatnot. - - // Notification messages from GameSpy - void processGlobalMessage(Int slotNum, const char *options); - -protected: - NATConnectionState connectionUpdate(); ///< the update function for the connections. - void sendMangledSourcePort(); ///< starts the process to get the next mangled source port. - void processManglerResponse(UnsignedShort mangledPort); - - Bool allConnectionsDoneThisRound(); - Bool allConnectionsDone(); - - void generatePortNumbers(GameSlot **slotList, Int localSlot); ///< generate all of the slots' port numbers to be used. - - void doThisConnectionRound(); ///< compute who will connect with who for this round. - void setConnectionState(Int nodeNumber, NATConnectionState state); ///< central point for changing a connection's state. - void sendAProbe(UnsignedInt ip, UnsignedShort port, Int fromNode); ///< send a "PROBE" packet to this IP and port. - void notifyTargetOfProbe(GameSlot *targetSlot); - void notifyUsersOfConnectionDone(Int nodeIndex); - void notifyUsersOfConnectionFailed(Int nodeIndex); - void sendMangledPortNumberToTarget(UnsignedShort mangledPort, GameSlot *targetSlot); - - void probed(Int nodeNumber); - void gotMangledPort(Int nodeNumber, UnsignedShort mangledPort); - void gotInternalAddress(Int nodeNumber, UnsignedInt address); - void connectionComplete(Int slotIndex); - void connectionFailed(Int slotIndex); - - Transport *m_transport; - GameSlot **m_slotList; - NATStateType m_NATState; - Int m_localNodeNumber; ///< The node number of the local player. - Int m_targetNodeNumber; ///< The node number of the player we are connecting to this round. - UnsignedInt m_localIP; ///< The IP of the local computer. - UnsignedInt m_numNodes; ///< The number of players we have to connect together. - UnsignedInt m_connectionRound; ///< The "round" of connections we are currently on. - - Int m_numRetries; - Int m_maxNumRetriesAllowed; - - UnsignedShort m_packetID; - UnsignedShort m_spareSocketPort; - time_t m_manglerRetryTime; - Int m_manglerRetries; - UnsignedShort m_previousSourcePort; - - Bool m_beenProbed; ///< have I been notified that I've been probed this round? - - UnsignedInt m_manglerAddress; - - time_t m_timeTillNextSend; ///< The number of milliseconds till we send to the other guy's port again. - NATConnectionState m_connectionStates[MAX_SLOTS]; ///< connection states for this round for all the nodes. - - ConnectionNodeType m_connectionNodes[MAX_SLOTS]; ///< info regarding the nodes that are being connected. - - UnsignedShort m_sourcePorts[MAX_SLOTS]; ///< the source ports that the other players communicate to us on. - - Bool m_myConnections[MAX_SLOTS]; ///< keeps track of all the nodes I've connected to. For keepalive. - time_t m_nextKeepaliveTime; ///< the next time we will send out our keepalive packets. - - static Int m_connectionPairs[MAX_SLOTS-1][MAX_SLOTS-1][MAX_SLOTS]; - Int m_connectionPairIndex; - - UnsignedShort m_startingPortNumber; ///< the starting port number for this game. The slots all get port numbers with their port numbers based on this number. - ///< this is done so that games that are played right after each other with the same players in the same - ///< slot order will not use the old source port allocation scheme in case their NAT - ///< hasn't timed out that connection. - - time_t m_nextPortSendTime; ///< Last time we sent our mangled port number to our target this round. - - time_t m_timeoutTime; ///< the time at which we will time out waiting for the other player's port number. - time_t m_roundTimeout; ///< the time at which we will time out this connection round. - - static Int m_timeBetweenRetries; // 1 second between retries sounds good to me. - static time_t m_manglerRetryTimeInterval; // sounds good to me. - static Int m_maxAllowedManglerRetries; // works for me. - static time_t m_keepaliveInterval; // 15 seconds between keepalive packets seems good. - static time_t m_timeToWaitForPort; // wait for ten seconds for the other player's port number. - static time_t m_timeForRoundTimeout; // wait for at most ten seconds for each connection round to finish. - -}; - -extern NAT *TheNAT; - -#endif // #ifndef __NAT_H \ No newline at end of file diff --git a/Generals/Code/GameEngine/Source/Common/GameEngine.cpp b/Generals/Code/GameEngine/Source/Common/GameEngine.cpp index e90e63ea727..88634fe34b9 100644 --- a/Generals/Code/GameEngine/Source/Common/GameEngine.cpp +++ b/Generals/Code/GameEngine/Source/Common/GameEngine.cpp @@ -101,9 +101,6 @@ #include "GameNetwork/NetworkInterface.h" #include "GameNetwork/LANAPI.h" -#include "GameNetwork/GameSpy/GameResultsThread.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" #include "Common/Player.h" @@ -744,113 +741,6 @@ logging code that is usually called from another thread. I'm doing it here because there's no way to guarantee the other thread will execute before we exit the app. */ -void GameEngine::checkAbnormalQuitting(void) -{ - if (TheRecorder->isMultiplayer() && TheGameLogic->isInInternetGame()) - { //Should not be quitting at this time, record it as a cheat. - - Int localID = TheGameSpyInfo->getLocalProfileID(); - PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(localID); - - Player *player=ThePlayerList->getLocalPlayer(); - - Int ptIdx; - const PlayerTemplate *myTemplate = player->getPlayerTemplate(); - DEBUG_LOG(("myTemplate = %X(%s)\n", myTemplate, myTemplate->getName().str())); - for (ptIdx = 0; ptIdx < ThePlayerTemplateStore->getPlayerTemplateCount(); ++ptIdx) - { - const PlayerTemplate *nthTemplate = ThePlayerTemplateStore->getNthPlayerTemplate(ptIdx); - DEBUG_LOG(("nthTemplate = %X(%s)\n", nthTemplate, nthTemplate->getName().str())); - if (nthTemplate == myTemplate) - { - break; - } - } - - PSRequest req; - - req.requestType = PSRequest::PSREQUEST_UPDATEPLAYERSTATS; - req.email = TheGameSpyInfo->getLocalEmail().str(); - req.nick = TheGameSpyInfo->getLocalBaseName().str(); - req.password = TheGameSpyInfo->getLocalPassword().str(); - req.player = stats; - req.addDesync = FALSE; - req.addDiscon = TRUE; - req.lastHouse = ptIdx; - - UserPreferences pref; - AsciiString userPrefFilename; - userPrefFilename.format("GeneralsOnline\\MiscPref%d.ini", stats.id); - DEBUG_LOG(("using the file %s\n", userPrefFilename.str())); - pref.load(userPrefFilename); - - Int addedInDesyncs2 = pref.getInt("0", 0); - DEBUG_LOG(("addedInDesyncs2 = %d\n", addedInDesyncs2)); - if (addedInDesyncs2 < 0) - addedInDesyncs2 = 10; - Int addedInDesyncs3 = pref.getInt("1", 0); - DEBUG_LOG(("addedInDesyncs3 = %d\n", addedInDesyncs3)); - if (addedInDesyncs3 < 0) - addedInDesyncs3 = 10; - Int addedInDesyncs4 = pref.getInt("2", 0); - DEBUG_LOG(("addedInDesyncs4 = %d\n", addedInDesyncs4)); - if (addedInDesyncs4 < 0) - addedInDesyncs4 = 10; - Int addedInDiscons2 = pref.getInt("3", 0); - DEBUG_LOG(("addedInDiscons2 = %d\n", addedInDiscons2)); - if (addedInDiscons2 < 0) - addedInDiscons2 = 10; - Int addedInDiscons3 = pref.getInt("4", 0); - DEBUG_LOG(("addedInDiscons3 = %d\n", addedInDiscons3)); - if (addedInDiscons3 < 0) - addedInDiscons3 = 10; - Int addedInDiscons4 = pref.getInt("5", 0); - DEBUG_LOG(("addedInDiscons4 = %d\n", addedInDiscons4)); - if (addedInDiscons4 < 0) - addedInDiscons4 = 10; - - DEBUG_LOG(("req.addDesync=%d, req.addDiscon=%d, addedInDesync=%d,%d,%d, addedInDiscon=%d,%d,%d\n", - req.addDesync, req.addDiscon, addedInDesyncs2, addedInDesyncs3, addedInDesyncs4, - addedInDiscons2, addedInDiscons3, addedInDiscons4)); - - if (req.addDesync || req.addDiscon) - { - AsciiString val; - if (req.lastHouse == 2) - { - val.format("%d", addedInDesyncs2 + req.addDesync); - pref["0"] = val; - val.format("%d", addedInDiscons2 + req.addDiscon); - pref["3"] = val; - DEBUG_LOG(("house 2 req.addDesync || req.addDiscon: %d %d\n", - addedInDesyncs2 + req.addDesync, addedInDiscons2 + req.addDiscon)); - } - else if (req.lastHouse == 3) - { - val.format("%d", addedInDesyncs3 + req.addDesync); - pref["1"] = val; - val.format("%d", addedInDiscons3 + req.addDiscon); - pref["4"] = val; - DEBUG_LOG(("house 3 req.addDesync || req.addDiscon: %d %d\n", - addedInDesyncs3 + req.addDesync, addedInDiscons3 + req.addDiscon)); - } - else - { - val.format("%d", addedInDesyncs4 + req.addDesync); - pref["2"] = val; - val.format("%d", addedInDiscons4 + req.addDiscon); - pref["5"] = val; - DEBUG_LOG(("house 4 req.addDesync || req.addDiscon: %d %d\n", - addedInDesyncs4 + req.addDesync, addedInDiscons4 + req.addDiscon)); - } - pref.write(); - } - } -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- #define CONVERT_EXEC1 "..\\Build\\nvdxt -list buildDDS.txt -dxt5 -full -outdir Art\\Textures > buildDDS.out" void updateTGAtoDDS() diff --git a/Generals/Code/GameEngine/Source/Common/Recorder.cpp b/Generals/Code/GameEngine/Source/Common/Recorder.cpp index 4ca4750ace0..4805328b9da 100644 --- a/Generals/Code/GameEngine/Source/Common/Recorder.cpp +++ b/Generals/Code/GameEngine/Source/Common/Recorder.cpp @@ -38,7 +38,6 @@ #include "GameNetwork/LANAPICallbacks.h" #include "GameNetwork/GameMessageParser.h" -#include "GameNetwork/GameSpy/PeerDefs.h" #include "GameNetwork/NetworkUtil.h" #include "GameLogic/GameLogic.h" #include "Common/RandomValue.h" diff --git a/Generals/Code/GameEngine/Source/Common/UserPreferences.cpp b/Generals/Code/GameEngine/Source/Common/UserPreferences.cpp index c2702fc144e..6075f652534 100644 --- a/Generals/Code/GameEngine/Source/Common/UserPreferences.cpp +++ b/Generals/Code/GameEngine/Source/Common/UserPreferences.cpp @@ -48,7 +48,6 @@ #include "Common/QuotedPrintable.h" #include "Common/MultiplayerSettings.h" #include "GameClient/MapUtil.h" -#include "GameNetwork/GameSpy/PeerDefs.h" #ifdef _INTERNAL // for occasional debugging... diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/DownloadMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/DownloadMenu.cpp deleted file mode 100644 index 3a77f3b253c..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/DownloadMenu.cpp +++ /dev/null @@ -1,436 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: DownloadMenu.cpp ///////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -// -// Electronic Arts Pacific. -// -// Confidential Information -// Copyright (C) 2002 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// Project: RTS3 -// -// File name: DownloadMenu.cpp -// -// Created: Matthew D. Campbell, July 2002 -// -// Desc: the Patch Download window control -// -//----------------------------------------------------------------------------- -/////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "Common/NameKeyGenerator.h" -#include "GameClient/GUICallbacks.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/GadgetProgressBar.h" -#include "GameClient/GameText.h" -#include "GameClient/MessageBox.h" - -#include "GameLogic/GameLogic.h" - -#include "GameNetwork/DownloadManager.h" -#include "GameNetwork/GameSpy/MainMenuUtils.h" - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -static NameKeyType buttonCancelID = NAMEKEY_INVALID; -static NameKeyType staticTextSizeID = NAMEKEY_INVALID; -static NameKeyType staticTextTimeID = NAMEKEY_INVALID; -static NameKeyType staticTextFileID = NAMEKEY_INVALID; -static NameKeyType staticTextStatusID = NAMEKEY_INVALID; -static NameKeyType progressBarMunkeeID = NAMEKEY_INVALID; - -static GameWindow * staticTextSize = NULL; -static GameWindow * staticTextTime = NULL; -static GameWindow * staticTextFile = NULL; -static GameWindow * staticTextStatus = NULL; -static GameWindow * progressBarMunkee = NULL; - -static GameWindow *parent = NULL; - -static void closeDownloadWindow( void ) -{ - DEBUG_ASSERTCRASH(parent, ("No Parent")); - if (!parent) - return; - - WindowLayout *menuLayout = parent->winGetLayout(); - menuLayout->runShutdown(); - menuLayout->destroyWindows(); - menuLayout->deleteInstance(); - menuLayout = NULL; - - GameWindow *mainWin = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("MainMenu.wnd:MainMenuParent") ); - if (mainWin) - TheWindowManager->winSetFocus( mainWin ); -} - -static void errorCallback( void ) -{ - HandleCanceledDownload(); - closeDownloadWindow(); -} - -static void successQuitCallback( void ) -{ - TheGameEngine->setQuitting( TRUE ); - closeDownloadWindow(); - - // Clean up game data. No crashy-crash for you! - if (TheGameLogic->isInGame()) - TheMessageStream->appendMessage( GameMessage::MSG_CLEAR_GAME_DATA ); -} - -static void successNoQuitCallback( void ) -{ - HandleCanceledDownload(); - closeDownloadWindow(); -} - -class DownloadManagerMunkee : public DownloadManager -{ -public: - DownloadManagerMunkee() {m_shouldQuitOnSuccess = true; m_shouldQuitOnSuccess = false;} - virtual HRESULT OnError( Int error ); - virtual HRESULT OnEnd(); - virtual HRESULT OnProgressUpdate( Int bytesread, Int totalsize, Int timetaken, Int timeleft ); - virtual HRESULT OnStatusUpdate( Int status ); - virtual HRESULT downloadFile( AsciiString server, AsciiString username, AsciiString password, AsciiString file, AsciiString localfile, AsciiString regkey, Bool tryResume ); - -private: - Bool m_shouldQuitOnSuccess; -}; - -HRESULT DownloadManagerMunkee::downloadFile( AsciiString server, AsciiString username, AsciiString password, AsciiString file, AsciiString localfile, AsciiString regkey, Bool tryResume ) -{ - // see if we'll need to restart - if (strstr(localfile.str(), "patches\\") != NULL) - { - m_shouldQuitOnSuccess = true; - } - - if (staticTextFile) - { - AsciiString bob = file; - - // just get the filename, not the pathname - const char *tmp = bob.reverseFind('/'); - if (tmp) - bob = tmp+1; - tmp = bob.reverseFind('\\'); - if (tmp) - bob = tmp+1; - - UnicodeString fileString; - fileString.translate(bob); - GadgetStaticTextSetText(staticTextFile, fileString); - } - - password.format("-%s", password.str()); - return DownloadManager::downloadFile( server, username, password, file, localfile, regkey, tryResume ); -} -HRESULT DownloadManagerMunkee::OnError( Int error ) -{ - HRESULT ret = DownloadManager::OnError( error ); - - MessageBoxOk(TheGameText->fetch("GUI:DownloadErrorTitle"), getErrorString(), errorCallback); - return ret; -} -HRESULT DownloadManagerMunkee::OnEnd() -{ - HRESULT ret = DownloadManager::OnEnd(); - - if (isFileQueuedForDownload()) - { - return downloadNextQueuedFile(); - } - if (m_shouldQuitOnSuccess) - MessageBoxOk(TheGameText->fetch("GUI:DownloadSuccessTitle"), TheGameText->fetch("GUI:DownloadSuccessMustQuit"), successQuitCallback); - else - MessageBoxOk(TheGameText->fetch("GUI:DownloadSuccessTitle"), TheGameText->fetch("GUI:DownloadSuccess"), successNoQuitCallback); - return ret; -} - -static time_t lastUpdate = 0; -static Int timeLeft = 0; -HRESULT DownloadManagerMunkee::OnProgressUpdate( Int bytesread, Int totalsize, Int timetaken, Int timeleft ) -{ - HRESULT ret = DownloadManager::OnProgressUpdate( bytesread, totalsize, timetaken, timeleft ); - - if (progressBarMunkee) - { - Int percent = bytesread * 100 / totalsize; - GadgetProgressBarSetProgress( progressBarMunkee, percent ); - } - - if (staticTextSize) - { - UnicodeString sizeString; - sizeString.format(TheGameText->fetch("GUI:DownloadBytesRatio"), bytesread, totalsize); - GadgetStaticTextSetText(staticTextSize, sizeString); - } - timeLeft = timeleft; - if (staticTextTime && GadgetStaticTextGetText(staticTextTime).isEmpty()) // only update immediately the first time - { - lastUpdate = time(NULL); - UnicodeString timeString; - if (timeleft) - { - DEBUG_ASSERTCRASH(timeleft > 0, ("Time left is negative!")); - timeleft = max(1, timeleft); - Int takenHour, takenMin, takenSec; - takenHour = timeleft / 60 / 60; - takenMin = timeleft / 60; - takenSec = timeleft % 60; - timeString.format(TheGameText->fetch("GUI:DownloadTimeLeft"), takenHour, takenMin, takenSec); - } - else - { - timeString = TheGameText->fetch("GUI:DownloadUnknownTime"); - } - GadgetStaticTextSetText(staticTextTime, timeString); - } - return ret; -} - -HRESULT DownloadManagerMunkee::OnStatusUpdate( Int status ) -{ - HRESULT ret = DownloadManager::OnStatusUpdate( status ); - - if (staticTextStatus) - { - GadgetStaticTextSetText(staticTextStatus, getStatusString()); - } - return ret; -} - -// PUBLIC FUNCTIONS /////////////////////////////////////////////////////////////////////////////// - -//------------------------------------------------------------------------------------------------- -/** Initialize the menu */ -//------------------------------------------------------------------------------------------------- -void DownloadMenuInit( WindowLayout *layout, void *userData ) -{ - - //set keyboard focus to main parent and set modal - NameKeyType parentID = TheNameKeyGenerator->nameToKey("DownloadMenu.wnd:ParentDownload"); - parent = TheWindowManager->winGetWindowFromId( NULL, parentID ); - - // get ids for our children controls - buttonCancelID = TheNameKeyGenerator->nameToKey( "DownloadMenu.wnd:ButtonCancel" ); - staticTextSizeID = TheNameKeyGenerator->nameToKey( "DownloadMenu.wnd:StaticTextSize" ); - staticTextTimeID = TheNameKeyGenerator->nameToKey( "DownloadMenu.wnd:StaticTextTime" ); - staticTextFileID = TheNameKeyGenerator->nameToKey( "DownloadMenu.wnd:StaticTextFile" ); - staticTextStatusID = TheNameKeyGenerator->nameToKey( "DownloadMenu.wnd:StaticTextStatus" ); - progressBarMunkeeID = TheNameKeyGenerator->nameToKey( "DownloadMenu.wnd:ProgressBarMunkee" ); - - staticTextSize = TheWindowManager->winGetWindowFromId( parent, staticTextSizeID ); - staticTextTime = TheWindowManager->winGetWindowFromId( parent, staticTextTimeID ); - staticTextFile = TheWindowManager->winGetWindowFromId( parent, staticTextFileID ); - staticTextStatus = TheWindowManager->winGetWindowFromId( parent, staticTextStatusID ); - progressBarMunkee = TheWindowManager->winGetWindowFromId( parent, progressBarMunkeeID ); - - DEBUG_ASSERTCRASH(!TheDownloadManager, ("Download manager already exists")); - if (TheDownloadManager) - { - delete TheDownloadManager; - } - TheDownloadManager = NEW DownloadManagerMunkee; - -} // end DownloadMenuInit - -//------------------------------------------------------------------------------------------------- -/** menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void DownloadMenuShutdown( WindowLayout *layout, void *userData ) -{ - DEBUG_ASSERTCRASH(TheDownloadManager, ("No download manager")); - if (TheDownloadManager) - { - delete TheDownloadManager; - TheDownloadManager = NULL; - } - - staticTextSize = NULL; - staticTextTime = NULL; - staticTextFile = NULL; - staticTextStatus = NULL; - progressBarMunkee = NULL; - parent = NULL; - -} // end DownloadMenuShutdown - -//------------------------------------------------------------------------------------------------- -/** menu update method */ -//------------------------------------------------------------------------------------------------- -void DownloadMenuUpdate( WindowLayout *layout, void *userData ) -{ - if (staticTextTime && !GadgetStaticTextGetText(staticTextTime).isEmpty()) - { - time_t now = time(NULL); - if (now <= lastUpdate) - return; - - lastUpdate = now; - - UnicodeString timeString; - if (timeLeft) - { - DEBUG_ASSERTCRASH(timeLeft > 0, ("Time left is negative!")); - timeLeft = max(1, timeLeft); - Int takenHour, takenMin, takenSec; - takenHour = timeLeft / 60 / 60; - takenMin = timeLeft / 60; - takenSec = timeLeft % 60; - timeString.format(TheGameText->fetch("GUI:DownloadTimeLeft"), takenHour, takenMin, takenSec); - } - else - { - timeString = TheGameText->fetch("GUI:DownloadUnknownTime"); - } - GadgetStaticTextSetText(staticTextTime, timeString); - } - -} // end DownloadMenuUpdate - -//------------------------------------------------------------------------------------------------- -/** menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType DownloadMenuInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - AsciiString buttonName( "DownloadMenu.wnd:ButtonCancel" ); - NameKeyType buttonID = TheNameKeyGenerator->nameToKey( buttonName ); - GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonID ); - - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)button, buttonID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; - -} // end DownloadMenuInput - -//------------------------------------------------------------------------------------------------- -/** menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType DownloadMenuSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CREATE: - { - - break; - - } // end create - //--------------------------------------------------------------------------------------------- - case GWM_DESTROY: - { - - break; - - } // end case - - //---------------------------------------------------------------------------------------------- - case GWM_INPUT_FOCUS: - { - - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - break; - - } // end input - //--------------------------------------------------------------------------------------------- - case GBM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if( controlID == buttonCancelID ) - { - HandleCanceledDownload(); - closeDownloadWindow(); - } // end if - - break; - - } // end selected - - default: - return MSG_IGNORED; - - } // end switch - - return MSG_HANDLED; - -} // end DownloadMenuSystem \ No newline at end of file diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MainMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MainMenu.cpp index f188e0d4e11..072c197cf3d 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MainMenu.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MainMenu.cpp @@ -30,8 +30,6 @@ // INCLUDES /////////////////////////////////////////////////////////////////////////////////////// #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine -#include "GameSpy/ghttp/ghttp.h" - #include "Lib/BaseType.h" #include "Common/GameEngine.h" #include "Common/GameState.h" @@ -60,15 +58,10 @@ #include "GameClient/HotKey.h" #include "GameLogic/GameLogic.h" #include "GameLogic/ScriptEngine.h" -#include "GameNetwork/GameSpyOverlay.h" #include "GameClient/GameWindowTransitions.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/BuddyThread.h" #include "GameNetwork/DownloadManager.h" -#include "GameNetwork/GameSpy/MainMenuUtils.h" //Added By Saad //for accessing the InGameUI @@ -452,7 +445,9 @@ void MainMenuInit( WindowLayout *layout, void *userData ) buttonSinglePlayer = TheWindowManager->winGetWindowFromId( parentMainMenu, buttonSinglePlayerID ); buttonMultiPlayer = TheWindowManager->winGetWindowFromId( parentMainMenu, buttonMultiPlayerID ); buttonSkirmish = TheWindowManager->winGetWindowFromId( parentMainMenu, skirmishID ); - buttonOnline = TheWindowManager->winGetWindowFromId( parentMainMenu, onlineID ); + buttonOnline = TheWindowManager->winGetWindowFromId( parentMainMenu, onlineID ); + if (buttonOnline) + buttonOnline->winHide(TRUE); buttonNetwork = TheWindowManager->winGetWindowFromId( parentMainMenu, networkID ); buttonOptions = TheWindowManager->winGetWindowFromId( parentMainMenu, optionsID ); buttonExit = TheWindowManager->winGetWindowFromId( parentMainMenu, exitID ); @@ -565,12 +560,6 @@ void MainMenuInit( WindowLayout *layout, void *userData ) //getUpdate->winEnable( FALSE ); } /**/ - - if (TheGameSpyPeerMessageQueue && !TheGameSpyPeerMessageQueue->isConnected()) - { - DEBUG_LOG(("Tearing down GameSpy from MainMenuInit()\n")); - TearDownGameSpy(); - } if (TheMapCache) TheMapCache->updateCache(); @@ -891,7 +880,6 @@ void MainMenuUpdate( WindowLayout *layout, void *userData ) } HTTPThinkWrapper(); - GameSpyUpdateOverlays(); // if(localAnimateWindowManager) // localAnimateWindowManager->update(); // if(localAnimateWindowManager && pendingDropDown != DROPDOWN_NONE && localAnimateWindowManager->isFinished()) @@ -1021,15 +1009,12 @@ WindowMsgHandledType MainMenuSystem( GameWindow *window, UnsignedInt msg, } // end case //--------------------------------------------------------------------------------------------- - case GWM_DESTROY: - { - ghttpCleanup(); - DEBUG_LOG(("Tearing down GameSpy from MainMenuSystem(GWM_DESTROY)\n")); - TearDownGameSpy(); - StopAsyncDNSCheck(); // kill off the async DNS check thread in case it is still running - break; + case GWM_DESTROY: + { + StopAsyncDNSCheck(); // kill off the async DNS check thread in case it is still running + break; - } // end case + } // end case // -------------------------------------------------------------------------------------------- case GWM_INPUT_FOCUS: @@ -1046,13 +1031,9 @@ WindowMsgHandledType MainMenuSystem( GameWindow *window, UnsignedInt msg, //--------------------------------------------------------------------------------------------- case GBM_MOUSE_ENTERING: { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if(controlID == onlineID) - { - TheScriptEngine->signalUIInteract(TheShellHookNames[SHELL_SCRIPT_HOOK_MAIN_MENU_ONLINE_HIGHLIGHTED]); - } - else if(controlID == networkID) +GameWindow *control = (GameWindow *)mData1; +Int controlID = control->winGetWindowId(); +if(controlID == networkID) { TheScriptEngine->signalUIInteract(TheShellHookNames[SHELL_SCRIPT_HOOK_MAIN_MENU_NETWORK_HIGHLIGHTED]); } @@ -1155,11 +1136,7 @@ WindowMsgHandledType MainMenuSystem( GameWindow *window, UnsignedInt msg, GameWindow *control = (GameWindow *)mData1; Int controlID = control->winGetWindowId(); - if(controlID == onlineID) - { - TheScriptEngine->signalUIInteract(TheShellHookNames[SHELL_SCRIPT_HOOK_MAIN_MENU_ONLINE_UNHIGHLIGHTED]); - } - else if(controlID == networkID) +if(controlID == networkID) { TheScriptEngine->signalUIInteract(TheShellHookNames[SHELL_SCRIPT_HOOK_MAIN_MENU_NETWORK_UNHIGHLIGHTED]); } @@ -1382,20 +1359,6 @@ WindowMsgHandledType MainMenuSystem( GameWindow *window, UnsignedInt msg, TheShell->push( AsciiString("Menus/SkirmishGameOptionsMenu.wnd") ); TheScriptEngine->signalUIInteract(TheShellHookNames[SHELL_SCRIPT_HOOK_MAIN_MENU_SKIRMISH_SELECTED]); } - else if( controlID == onlineID ) - { - if(dontAllowTransitions) - break; - dontAllowTransitions = TRUE; - buttonPushed = TRUE; - dropDownWindows[DROPDOWN_MULTIPLAYER]->winHide(FALSE); - TheTransitionHandler->reverse("MainMenuMultiPlayerMenuTransitionToNext"); - - StartPatchCheck(); -// localAnimateWindowManager->reverseAnimateWindow(); - dropDown = DROPDOWN_NONE; - - } // end else if else if( controlID == networkID ) { if(dontAllowTransitions) diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp deleted file mode 100644 index d8d69a75b79..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp +++ /dev/null @@ -1,537 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: NetworkDirectConnect.cpp -// Author: Bryan Cleveland, November 2001 -// Description: Lan Lobby Menu -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "GameSpy/peer/peer.h" - -#include "Common/QuotedPrintable.h" -#include "Common/UserPreferences.h" -#include "GameClient/AnimateWindowManager.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/GameText.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetComboBox.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/Shell.h" -#include "GameClient/GameWindowTransitions.h" - -#include "GameNetwork/IPEnumeration.h" -#include "GameNetwork/LANAPI.h" -#include "GameNetwork/LANAPICallbacks.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -// window ids ------------------------------------------------------------------------------ - -// Window Pointers ------------------------------------------------------------------------ - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// - -extern Bool LANbuttonPushed; -extern Bool LANisShuttingDown; - -static Bool isShuttingDown = false; -static Bool buttonPushed = false; - -static NameKeyType buttonBackID = NAMEKEY_INVALID; -static NameKeyType buttonHostID = NAMEKEY_INVALID; -static NameKeyType buttonJoinID = NAMEKEY_INVALID; -static NameKeyType editPlayerNameID = NAMEKEY_INVALID; -static NameKeyType comboboxRemoteIPID = NAMEKEY_INVALID; -static NameKeyType staticLocalIPID = NAMEKEY_INVALID; - -static GameWindow *buttonBack = NULL; -static GameWindow *buttonHost = NULL; -static GameWindow *buttonJoin = NULL; -static GameWindow *editPlayerName = NULL; -static GameWindow *comboboxRemoteIP = NULL; -static GameWindow *staticLocalIP = NULL; - -void PopulateRemoteIPComboBox() -{ - LANPreferences userprefs; - GadgetComboBoxReset(comboboxRemoteIP); - - Int numRemoteIPs = userprefs.getNumRemoteIPs(); - Color white = GameMakeColor(255,255,255,255); - - for (Int i = 0; i < numRemoteIPs; ++i) - { - UnicodeString entry; - entry = userprefs.getRemoteIPEntry(i); - GadgetComboBoxAddEntry(comboboxRemoteIP, entry, white); - } - - if (numRemoteIPs > 0) - { - GadgetComboBoxSetSelectedPos(comboboxRemoteIP, 0, TRUE); - } - userprefs.write(); -} - -void UpdateRemoteIPList() -{ - Int n1[4], n2[4]; - LANPreferences prefs; - Int numEntries = GadgetComboBoxGetLength(comboboxRemoteIP); - Int currentSelection = -1; - GadgetComboBoxGetSelectedPos(comboboxRemoteIP, ¤tSelection); - UnicodeString unisel = GadgetComboBoxGetText(comboboxRemoteIP); - AsciiString sel; - sel.translate(unisel); - -// UnicodeString newEntry = prefs.getRemoteIPEntry(0); - UnicodeString newEntry = unisel; - UnicodeString newIP; - newEntry.nextToken(&newIP, UnicodeString(L":")); - Int numFields = swscanf(newIP.str(), L"%d.%d.%d.%d", &(n1[0]), &(n1[1]), &(n1[2]), &(n1[3])); - - if (numFields != 4) { - // this is not a properly formatted IP, don't change a thing. - return; - } - - prefs["RemoteIP0"] = sel; - - Int currentINIEntry = 1; - - for (Int i = 0; i < numEntries; ++i) - { - if (i != currentSelection) - { - GadgetComboBoxSetSelectedPos(comboboxRemoteIP, i, FALSE); - UnicodeString uni; - uni = GadgetComboBoxGetText(comboboxRemoteIP); - AsciiString ascii; - ascii.translate(uni); - - // prevent more than one copy of an IP address from being put in the list. - if (currentSelection == -1) - { - UnicodeString oldEntry = uni; - UnicodeString oldIP; - oldEntry.nextToken(&oldIP, UnicodeString(L":")); - - swscanf(oldIP.str(), L"%d.%d.%d.%d", &(n2[0]), &(n2[1]), &(n2[2]), &(n2[3])); - - Bool isEqual = TRUE; - for (Int i = 0; (i < 4) && (isEqual == TRUE); ++i) { - if (n1[i] != n2[i]) { - isEqual = FALSE; - } - } - // check to see if this is a duplicate or if this is not a properly formatted IP address. - if (isEqual == TRUE) - { - --numEntries; - continue; - } - } - AsciiString temp; - temp.format("RemoteIP%d", currentINIEntry); - ++currentINIEntry; - prefs[temp.str()] = ascii; - } - } - - if (currentSelection == -1) - { - ++numEntries; - } - - AsciiString numRemoteIPs; - numRemoteIPs.format("%d", numEntries); - - prefs["NumRemoteIPs"] = numRemoteIPs; - - prefs.write(); -} - -void HostDirectConnectGame() -{ - // Init LAN API Singleton - DEBUG_ASSERTCRASH(TheLAN != NULL, ("TheLAN is NULL!")); - if (!TheLAN) - { - TheLAN = NEW LANAPI(); - } - - UnsignedInt localIP = TheLAN->GetLocalIP(); - UnicodeString localIPString; - localIPString.format(L"%d.%d.%d.%d", localIP >> 24, (localIP & 0xff0000) >> 16, (localIP & 0xff00) >> 8, localIP & 0xff); - - UnicodeString name; - name = GadgetTextEntryGetText(editPlayerName); - - LANPreferences prefs; - prefs["UserName"] = UnicodeStringToQuotedPrintable(name); - prefs.write(); - - while (name.getLength() > g_lanPlayerNameLength) - name.removeLastChar(); - TheLAN->RequestSetName(name); - TheLAN->RequestGameCreate(localIPString, TRUE); -} - -void JoinDirectConnectGame() -{ - // Init LAN API Singleton - - if (!TheLAN) - { - TheLAN = NEW LANAPI(); - } - - UnsignedInt ipaddress = 0; - UnicodeString ipunistring = GadgetComboBoxGetText(comboboxRemoteIP); - AsciiString asciientry; - asciientry.translate(ipunistring); - - AsciiString ipstring; - asciientry.nextToken(&ipstring, "("); - - char ipstr[16]; - strcpy(ipstr, ipstring.str()); - - Int ip1, ip2, ip3, ip4; - sscanf(ipstr, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4); - - DEBUG_LOG(("JoinDirectConnectGame - joining at %d.%d.%d.%d\n", ip1, ip2, ip3, ip4)); - - ipaddress = (ip1 << 24) + (ip2 << 16) + (ip3 << 8) + ip4; -// ipaddress = htonl(ipaddress); - - UnicodeString name; - name = GadgetTextEntryGetText(editPlayerName); - - LANPreferences prefs; - prefs["UserName"] = UnicodeStringToQuotedPrintable(name); - prefs.write(); - - UpdateRemoteIPList(); - PopulateRemoteIPComboBox(); - - while (name.getLength() > g_lanPlayerNameLength) - name.removeLastChar(); - TheLAN->RequestSetName(name); - - TheLAN->RequestGameJoinDirectConnect(ipaddress); -} - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Welcome Menu */ -//------------------------------------------------------------------------------------------------- -void NetworkDirectConnectInit( WindowLayout *layout, void *userData ) -{ - LANbuttonPushed = false; - LANisShuttingDown = false; - - if (TheLAN == NULL) - { - TheLAN = NEW LANAPI(); - TheLAN->init(); - } - TheLAN->reset(); - - buttonPushed = false; - isShuttingDown = false; - TheShell->showShellMap(TRUE); - buttonBackID = TheNameKeyGenerator->nameToKey( AsciiString( "NetworkDirectConnect.wnd:ButtonBack" ) ); - buttonHostID = TheNameKeyGenerator->nameToKey( AsciiString( "NetworkDirectConnect.wnd:ButtonHost" ) ); - buttonJoinID = TheNameKeyGenerator->nameToKey( AsciiString( "NetworkDirectConnect.wnd:ButtonJoin" ) ); - editPlayerNameID = TheNameKeyGenerator->nameToKey( AsciiString( "NetworkDirectConnect.wnd:EditPlayerName" ) ); - comboboxRemoteIPID = TheNameKeyGenerator->nameToKey( AsciiString( "NetworkDirectConnect.wnd:ComboboxRemoteIP" ) ); - staticLocalIPID = TheNameKeyGenerator->nameToKey( AsciiString( "NetworkDirectConnect.wnd:StaticLocalIP" ) ); - - buttonBack = TheWindowManager->winGetWindowFromId( NULL, buttonBackID); - buttonHost = TheWindowManager->winGetWindowFromId( NULL, buttonHostID); - buttonJoin = TheWindowManager->winGetWindowFromId( NULL, buttonJoinID); - editPlayerName = TheWindowManager->winGetWindowFromId( NULL, editPlayerNameID); - comboboxRemoteIP = TheWindowManager->winGetWindowFromId( NULL, comboboxRemoteIPID); - staticLocalIP = TheWindowManager->winGetWindowFromId( NULL, staticLocalIPID); - -// // animate controls -// TheShell->registerWithAnimateManager(buttonBack, WIN_ANIMATION_SLIDE_LEFT, TRUE, 800); -// TheShell->registerWithAnimateManager(buttonHost, WIN_ANIMATION_SLIDE_LEFT, TRUE, 600); -// TheShell->registerWithAnimateManager(buttonJoin, WIN_ANIMATION_SLIDE_LEFT, TRUE, 200); -// - LANPreferences userprefs; - UnicodeString name; - name = userprefs.getUserName(); - - if (name.getLength() == 0) - { - name = TheGameText->fetch("GUI:Player"); - } - - GadgetTextEntrySetText(editPlayerName, name); - - PopulateRemoteIPComboBox(); - - UnicodeString ipstr; - - delete TheLAN; - TheLAN = NULL; - - if (TheLAN == NULL) { -// DEBUG_ASSERTCRASH(TheLAN != NULL, ("TheLAN is null initializing the direct connect screen.")); - TheLAN = NEW LANAPI(); - - OptionPreferences prefs; - UnsignedInt IP = prefs.getOnlineIPAddress(); - - IPEnumeration IPs; - -// if (!IP) -// { - EnumeratedIP *IPlist = IPs.getAddresses(); - DEBUG_ASSERTCRASH(IPlist, ("No IP addresses found!")); - if (!IPlist) - { - /// @todo: display error and exit lan lobby if no IPs are found - } - - Bool foundIP = FALSE; - EnumeratedIP *tempIP = IPlist; - while ((tempIP != NULL) && (foundIP == FALSE)) { - if (IP == tempIP->getIP()) { - foundIP = TRUE; - } - tempIP = tempIP->getNext(); - } - - if (foundIP == FALSE) { - // The IP that we had no longer exists, we need to pick a new one. - IP = IPlist->getIP(); - } - -// IP = IPlist->getIP(); -// } - TheLAN->init(); - TheLAN->SetLocalIP(IP); - } - - UnsignedInt ip = TheLAN->GetLocalIP(); - ipstr.format(L"%d.%d.%d.%d", ip >> 24, (ip & 0xff0000) >> 16, (ip & 0xff00) >> 8, ip & 0xff); - GadgetStaticTextSetText(staticLocalIP, ipstr); - - TheLAN->RequestLobbyLeave(true); - layout->hide(FALSE); - layout->bringForward(); - TheTransitionHandler->setGroup("NetworkDirectConnectFade"); - - -} // NetworkDirectConnectInit - -//------------------------------------------------------------------------------------------------- -/** This is called when a shutdown is complete for this menu */ -//------------------------------------------------------------------------------------------------- -static void shutdownComplete( WindowLayout *layout ) -{ - - isShuttingDown = false; - - // hide the layout - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout ); - -} // end if - -//------------------------------------------------------------------------------------------------- -/** WOL Welcome Menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void NetworkDirectConnectShutdown( WindowLayout *layout, void *userData ) -{ - isShuttingDown = true; - - // if we are shutting down for an immediate pop, skip the animations - Bool popImmediate = *(Bool *)userData; - if( popImmediate ) - { - - shutdownComplete( layout ); - return; - - } //end if - - TheShell->reverseAnimatewindow(); - - TheTransitionHandler->reverse("NetworkDirectConnectFade"); -} // NetworkDirectConnectShutdown - - -//------------------------------------------------------------------------------------------------- -/** WOL Welcome Menu update method */ -//------------------------------------------------------------------------------------------------- -void NetworkDirectConnectUpdate( WindowLayout * layout, void *userData) -{ - // We'll only be successful if we've requested to - if(isShuttingDown && TheShell->isAnimFinished() && TheTransitionHandler->isFinished()) - shutdownComplete(layout); -}// NetworkDirectConnectUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Welcome Menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType NetworkDirectConnectInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - if (buttonPushed) - break; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonBack, buttonBackID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// NetworkDirectConnectInput - -//------------------------------------------------------------------------------------------------- -/** WOL Welcome Menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType NetworkDirectConnectSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - - switch( msg ) - { - - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - case GBM_SELECTED: - { - if (buttonPushed) - break; - - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if ( controlID == buttonBackID ) - { - UnicodeString name; - name = GadgetTextEntryGetText(editPlayerName); - - LANPreferences prefs; - prefs["UserName"] = UnicodeStringToQuotedPrintable(name); - prefs.write(); - - while (name.getLength() > g_lanPlayerNameLength) - name.removeLastChar(); - TheLAN->RequestSetName(name); - - buttonPushed = true; - LANbuttonPushed = true; - TheShell->pop(); - } //if ( controlID == buttonBack ) - else if (controlID == buttonHostID) - { - HostDirectConnectGame(); - } - else if (controlID == buttonJoinID) - { - JoinDirectConnectGame(); - } - break; - }// case GBM_SELECTED: - - case GEM_EDIT_DONE: - { - break; - } - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// NetworkDirectConnectSystem diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp index da7081488e8..6411147a8d6 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp @@ -30,8 +30,6 @@ // INCLUDES /////////////////////////////////////////////////////////////////////////////////////// #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine -#include "GameSpy/ghttp/ghttp.h" - #include "Common/AudioAffect.h" #include "Common/AudioSettings.h" #include "Common/GameAudio.h" @@ -63,8 +61,6 @@ #include "GameClient/GUICallbacks.h" #include "GameNetwork/FirewallHelper.h" #include "GameNetwork/IPEnumeration.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameNetwork/GameSpy/PeerDefs.h" #include "GameLogic/GameLogic.h" #include "GameLogic/ScriptEngine.h" #include "WWDownload/Registry.h" @@ -82,9 +78,6 @@ #endif -static NameKeyType comboBoxOnlineIPID = NAMEKEY_INVALID; -static GameWindow * comboBoxOnlineIP = NULL; - static NameKeyType comboBoxLANIPID = NAMEKEY_INVALID; static GameWindow * comboBoxLANIP = NULL; @@ -763,7 +756,7 @@ static void setDefaults( void ) //------------------------------------------------------------------------------------------------- // Resolution //Find index of 800x600 mode. - if ((TheGameLogic->isInGame() == FALSE) || (TheGameLogic->isInShellGame() == TRUE) && !TheGameSpyInfo) { + if ((TheGameLogic->isInGame() == FALSE) || (TheGameLogic->isInShellGame() == TRUE)) { Int numResolutions = TheDisplay->getDisplayModeCount(); Int defaultResIndex=0; for( Int i = 0; i < numResolutions; ++i ) @@ -1073,13 +1066,6 @@ static void saveOptions( void ) TheWritableGlobalData->m_defaultIP = ip; pref->setLANIPAddress(ip); } - GadgetComboBoxGetSelectedPos(comboBoxOnlineIP, &index); - if (index>=0) - { - ip = (UnsignedInt)GadgetComboBoxGetItemData(comboBoxOnlineIP, index); - pref->setOnlineIPAddress(ip); - } - //------------------------------------------------------------------------------------------------- // HTTP Proxy GameWindow *textEntryHTTPProxy = TheWindowManager->winGetWindowFromId(NULL, NAMEKEY("OptionsMenu.wnd:TextEntryHTTPProxy")); @@ -1089,7 +1075,6 @@ static void saveOptions( void ) AsciiString aStr; aStr.translate(uStr); SetStringInRegistry("", "Proxy", aStr.str()); - ghttpSetProxy(aStr.str()); } //------------------------------------------------------------------------------------------------- @@ -1287,8 +1272,10 @@ void OptionsMenuInit( WindowLayout *layout, void *userData ) comboBoxLANIPID = TheNameKeyGenerator->nameToKey( AsciiString( "OptionsMenu.wnd:ComboBoxIP" ) ); comboBoxLANIP = TheWindowManager->winGetWindowFromId( NULL, comboBoxLANIPID); - comboBoxOnlineIPID = TheNameKeyGenerator->nameToKey( AsciiString( "OptionsMenu.wnd:ComboBoxOnlineIP" ) ); - comboBoxOnlineIP = TheWindowManager->winGetWindowFromId( NULL, comboBoxOnlineIPID); + NameKeyType comboBoxOnlineIPID = TheNameKeyGenerator->nameToKey( AsciiString( "OptionsMenu.wnd:ComboBoxOnlineIP" ) ); + if ( GameWindow *comboBoxOnlineIP = TheWindowManager->winGetWindowFromId( NULL, comboBoxOnlineIPID ) ) + comboBoxOnlineIP->winHide( TRUE ); + checkAlternateMouseID = TheNameKeyGenerator->nameToKey( AsciiString( "OptionsMenu.wnd:CheckAlternateMouse" ) ); checkAlternateMouse = TheWindowManager->winGetWindowFromId( NULL, checkAlternateMouseID); sliderScrollSpeedID = TheNameKeyGenerator->nameToKey( AsciiString( "OptionsMenu.wnd:SliderScrollSpeed" ) ); @@ -1447,53 +1434,16 @@ void OptionsMenuInit( WindowLayout *layout, void *userData ) { GadgetComboBoxSetSelectedPos(comboBoxLANIP, selectedIndex); } - else - { - GadgetComboBoxSetSelectedPos(comboBoxLANIP, 0); - if (IPs.getAddresses()) - { - pref->setLANIPAddress(IPs.getAddresses()->getIPstring()); - } - } + else + { + GadgetComboBoxSetSelectedPos(comboBoxLANIP, 0); + if (IPs.getAddresses()) + { + pref->setLANIPAddress(IPs.getAddresses()->getIPstring()); + } + } - // And now the GameSpy one - if (comboBoxOnlineIP) - { - UnsignedInt selectedIP = pref->getOnlineIPAddress(); - UnicodeString str; - IPEnumeration IPs; - EnumeratedIP *IPlist = IPs.getAddresses(); - Int index; - Int selectedIndex = -1; - Int count = 0; - GadgetComboBoxReset(comboBoxOnlineIP); - while (IPlist) - { - count++; - str.translate(IPlist->getIPstring()); - index = GadgetComboBoxAddEntry(comboBoxOnlineIP, str, color); - GadgetComboBoxSetItemData(comboBoxOnlineIP, index, (void *)(IPlist->getIP())); - if (selectedIP == IPlist->getIP()) - { - selectedIndex = index; - } - IPlist = IPlist->getNext(); - } - if (selectedIndex >= 0) - { - GadgetComboBoxSetSelectedPos(comboBoxOnlineIP, selectedIndex); - } - else - { - GadgetComboBoxSetSelectedPos(comboBoxOnlineIP, 0); - if (IPs.getAddresses()) - { - pref->setOnlineIPAddress(IPs.getAddresses()->getIPstring()); - } - } - } - - // HTTP Proxy + // HTTP Proxy GameWindow *textEntryHTTPProxy = TheWindowManager->winGetWindowFromId(NULL, NAMEKEY("OptionsMenu.wnd:TextEntryHTTPProxy")); if (textEntryHTTPProxy) { @@ -1728,12 +1678,10 @@ void OptionsMenuInit( WindowLayout *layout, void *userData ) GameWindow *parent = TheWindowManager->winGetWindowFromId( NULL, parentID ); TheWindowManager->winSetFocus( parent ); - if( (TheGameLogic->isInGame() && TheGameLogic->getGameMode() != GAME_SHELL) || TheGameSpyInfo ) + if( (TheGameLogic->isInGame() && TheGameLogic->getGameMode() != GAME_SHELL) ) { // disable controls that you can't change the options for in game comboBoxLANIP->winEnable(FALSE); - if (comboBoxOnlineIP) - comboBoxOnlineIP->winEnable(FALSE); checkSendDelay->winEnable(FALSE); buttonFirewallRefresh->winEnable(FALSE); @@ -1928,15 +1876,8 @@ WindowMsgHandledType OptionsMenuSystem( GameWindow *window, UnsignedInt msg, pref = NULL; } - comboBoxLANIP = NULL; - comboBoxOnlineIP = NULL; - - if(GameSpyIsOverlayOpen(GSOVERLAY_OPTIONS)) - GameSpyCloseOverlay(GSOVERLAY_OPTIONS); - else - { - DestroyOptionsLayout(); - } +comboBoxLANIP = NULL; +DestroyOptionsLayout(); } // end if else if (controlID == buttonAccept ) @@ -1950,23 +1891,15 @@ WindowMsgHandledType OptionsMenuSystem( GameWindow *window, UnsignedInt msg, pref = NULL; } - comboBoxLANIP = NULL; - comboBoxOnlineIP = NULL; - - if(!TheGameLogic->isInGame() || TheGameLogic->isInShellGame()) - destroyQuitMenu(); // if we're in a game, the change res then enter the same kind of game, we nee the quit menu to be gone. - +comboBoxLANIP = NULL; +if(!TheGameLogic->isInGame() || TheGameLogic->isInShellGame()) +destroyQuitMenu(); // if we're in a game, the change res then enter the same kind of game, we nee the quit menu to be gone. - if(GameSpyIsOverlayOpen(GSOVERLAY_OPTIONS)) - GameSpyCloseOverlay(GSOVERLAY_OPTIONS); - else - { - DestroyOptionsLayout(); - if (dispChanged) - { - DoResolutionDialog(); - } - } +DestroyOptionsLayout(); +if (dispChanged) +{ +DoResolutionDialog(); +} } else if (controlID == buttonDefaults ) diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/PopupLadderSelect.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/PopupLadderSelect.cpp deleted file mode 100644 index b66b8b717e1..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/PopupLadderSelect.cpp +++ /dev/null @@ -1,682 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PopupLadderSelect.cpp //////////////////////////////////////////////// -//----------------------------------------------------------------------------- -// -// Electronic Arts Pacific. -// -// Confidential Information -// Copyright (C) 2002 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// created: August 2002 -// -// Filename: PopupLadderSelect.cpp -// -// author: Matthew D. Campbell -// -// purpose: Contains the Callbacks for the Ladder Select Popup -// -//----------------------------------------------------------------------------- -/////////////////////////////////////////////////////////////////////////////// - -//----------------------------------------------------------------------------- -// SYSTEM INCLUDES //////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// USER INCLUDES ////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GlobalData.h" -#include "Common/Encrypt.h" -#include "Common/NameKeyGenerator.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/GameText.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/MapUtil.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameNetwork/GameSpy/LadderDefs.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -//#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpyOverlay.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -//----------------------------------------------------------------------------- -// DEFINES //////////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -static NameKeyType parentID = NAMEKEY_INVALID; -static NameKeyType listboxLadderSelectID = NAMEKEY_INVALID; -static NameKeyType listboxLadderDetailsID = NAMEKEY_INVALID; -static NameKeyType staticTextLadderNameID = NAMEKEY_INVALID; -static NameKeyType buttonOkID = NAMEKEY_INVALID; -static NameKeyType buttonCancelID = NAMEKEY_INVALID; - -static GameWindow *parent = NULL; -static GameWindow *listboxLadderSelect = NULL; -static GameWindow *listboxLadderDetails = NULL; -static GameWindow *staticTextLadderName = NULL; -static GameWindow *buttonOk = NULL; -static GameWindow *buttonCancel = NULL; - -// password entry popup -static NameKeyType passwordParentID = NAMEKEY_INVALID; -static NameKeyType buttonPasswordOkID = NAMEKEY_INVALID; -static NameKeyType buttonPasswordCancelID = NAMEKEY_INVALID; -static NameKeyType textEntryPasswordID = NAMEKEY_INVALID; -static GameWindow *passwordParent = NULL; -static GameWindow *textEntryPassword = NULL; - -// incorrect password popup -static NameKeyType badPasswordParentID = NAMEKEY_INVALID; -static NameKeyType buttonBadPasswordOkID = NAMEKEY_INVALID; -static GameWindow *badPasswordParent = NULL; - -static void updateLadderDetails( Int ladderID, GameWindow *staticTextLadderName, GameWindow *listboxLadderDetails ); - -void PopulateQMLadderComboBox( void ); -void PopulateCustomLadderComboBox( void ); - -void PopulateQMLadderListBox( GameWindow *win ); -void PopulateCustomLadderListBox( GameWindow *win ); - -void HandleQMLadderSelection(Int ladderID); -void HandleCustomLadderSelection(Int ladderID); - -void CustomMatchHideHostPopup(Bool hide); - -static void populateLadderComboBox( void ) -{ - // only one of these will do any work... - PopulateQMLadderComboBox(); - PopulateCustomLadderComboBox(); -} - -static void populateLadderListBox( void ) -{ - // only one of these will do any work... - PopulateQMLadderListBox(listboxLadderSelect); - PopulateCustomLadderListBox(listboxLadderSelect); - - Int selIndex, selID; - GadgetListBoxGetSelected(listboxLadderSelect, &selIndex); - if (selIndex < 0) - return; - selID = (Int)GadgetListBoxGetItemData(listboxLadderSelect, selIndex); - if (!selID) - return; - updateLadderDetails(selID, staticTextLadderName, listboxLadderDetails); -} - -static void handleLadderSelection( Int ladderID ) -{ - // only one of these will do any work... - HandleQMLadderSelection(ladderID); - HandleCustomLadderSelection(ladderID); -} - - -enum PasswordMode -{ - PASS_NONE, - PASS_ENTRY, - PASS_ERROR -}; - -static PasswordMode s_currentMode = PASS_NONE; -static void setPasswordMode(PasswordMode mode) -{ - s_currentMode = mode; - switch(mode) - { - case PASS_NONE: - if (passwordParent) - passwordParent->winHide(TRUE); - if (badPasswordParent) - badPasswordParent->winHide(TRUE); - if (buttonOk) - buttonOk->winEnable(TRUE); - if (buttonCancel) - buttonCancel->winEnable(TRUE); - if (textEntryPassword) - textEntryPassword->winEnable(FALSE); - if (listboxLadderSelect) - listboxLadderSelect->winEnable(TRUE); - TheWindowManager->winSetFocus(listboxLadderSelect); - break; - case PASS_ENTRY: - if (passwordParent) - passwordParent->winHide(FALSE); - if (badPasswordParent) - badPasswordParent->winHide(TRUE); - if (buttonOk) - buttonOk->winEnable(FALSE); - if (buttonCancel) - buttonCancel->winEnable(FALSE); - if (textEntryPassword) - { - textEntryPassword->winEnable(TRUE); - GadgetTextEntrySetText(textEntryPassword, UnicodeString::TheEmptyString); - } - if (listboxLadderSelect) - listboxLadderSelect->winEnable(FALSE); - TheWindowManager->winSetFocus(textEntryPassword); - break; - case PASS_ERROR: - if (passwordParent) - passwordParent->winHide(TRUE); - if (badPasswordParent) - badPasswordParent->winHide(FALSE); - if (buttonOk) - buttonOk->winEnable(FALSE); - if (buttonCancel) - buttonCancel->winEnable(FALSE); - if (textEntryPassword) - textEntryPassword->winEnable(FALSE); - if (listboxLadderSelect) - listboxLadderSelect->winEnable(FALSE); - TheWindowManager->winSetFocus(parent); - break; - } -} - -//----------------------------------------------------------------------------- -// PUBLIC FUNCTIONS /////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//------------------------------------------------------------------------------------------------- -/** Initialize the menu */ -//------------------------------------------------------------------------------------------------- -void PopupLadderSelectInit( WindowLayout *layout, void *userData ) -{ - parentID = NAMEKEY("PopupLadderSelect.wnd:Parent"); - parent = TheWindowManager->winGetWindowFromId(NULL, parentID); - - listboxLadderSelectID = NAMEKEY("PopupLadderSelect.wnd:ListBoxLadderSelect"); - listboxLadderSelect = TheWindowManager->winGetWindowFromId(parent, listboxLadderSelectID); - - listboxLadderDetailsID = NAMEKEY("PopupLadderSelect.wnd:ListBoxLadderDetails"); - listboxLadderDetails = TheWindowManager->winGetWindowFromId(parent, listboxLadderDetailsID); - - staticTextLadderNameID = NAMEKEY("PopupLadderSelect.wnd:StaticTextLadderName"); - staticTextLadderName = TheWindowManager->winGetWindowFromId(parent, staticTextLadderNameID); - - buttonOkID = NAMEKEY("PopupLadderSelect.wnd:ButtonOk"); - buttonCancelID = NAMEKEY("PopupLadderSelect.wnd:ButtonCancel"); - - buttonOk = TheWindowManager->winGetWindowFromId(parent, buttonOkID); - buttonCancel = TheWindowManager->winGetWindowFromId(parent, buttonCancelID); - - TheWindowManager->winSetFocus( parent ); - TheWindowManager->winSetModal( parent ); - - // password entry popup - passwordParentID = NAMEKEY("PopupLadderSelect.wnd:PasswordParent"); - passwordParent = TheWindowManager->winGetWindowFromId(parent, passwordParentID); - buttonPasswordOkID = NAMEKEY("PopupLadderSelect.wnd:ButtonPasswordOk"); - buttonPasswordCancelID = NAMEKEY("PopupLadderSelect.wnd:ButtonPasswordCancel"); - textEntryPasswordID = NAMEKEY("PopupLadderSelect.wnd:PasswordEntry"); - textEntryPassword = TheWindowManager->winGetWindowFromId(parent, textEntryPasswordID); - - // bad password popup - badPasswordParentID = NAMEKEY("PopupLadderSelect.wnd:BadPasswordParent"); - badPasswordParent = TheWindowManager->winGetWindowFromId(parent, badPasswordParentID); - buttonBadPasswordOkID = NAMEKEY("PopupLadderSelect.wnd:ButtonBadPasswordOk"); - - setPasswordMode(PASS_NONE); - - CustomMatchHideHostPopup(TRUE); - - // populate list box (based on whether we're in custom or quickmatch) - populateLadderListBox(); -} - -//------------------------------------------------------------------------------------------------- -/** Input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType PopupLadderSelectInput( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; -// if (buttonPushed) -// break; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - switch (s_currentMode) - { - case PASS_NONE: - // re-select whatever was chosen before - populateLadderComboBox(); - GameSpyCloseOverlay(GSOVERLAY_LADDERSELECT); - break; - case PASS_ENTRY: - case PASS_ERROR: - setPasswordMode(PASS_NONE); - break; - } - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; - -} - -static Int ladderIndex = 0; -void ladderSelectedCallback(void) -{ - handleLadderSelection( ladderIndex ); - - // update combo box - populateLadderComboBox(); - - // tear down overlay - GameSpyCloseOverlay( GSOVERLAY_LADDERSELECT ); -} - -//------------------------------------------------------------------------------------------------- -/** System callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType PopupLadderSelectSystem( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - // -------------------------------------------------------------------------------------------- - case GWM_CREATE: - { - break; - } // end create - //--------------------------------------------------------------------------------------------- - case GWM_DESTROY: - { - parent = NULL; - listboxLadderSelect = NULL; - listboxLadderDetails = NULL; - CustomMatchHideHostPopup(FALSE); - break; - } // end case - - //---------------------------------------------------------------------------------------------- - case GWM_INPUT_FOCUS: - { - // if we're given the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - break; - } // end input - //---------------------------------------------------------------------------------------------- - case GBM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if (controlID == buttonOkID) - { - // save selection - Int selectPos = -1; - GadgetListBoxGetSelected( listboxLadderSelect, &selectPos ); - if (selectPos < 0) - break; - - ladderIndex = (Int)GadgetListBoxGetItemData( listboxLadderSelect, selectPos, 0 ); - const LadderInfo *li = TheLadderList->findLadderByIndex( ladderIndex ); - if (li && li->cryptedPassword.isNotEmpty()) - { - // need password asking - setPasswordMode(PASS_ENTRY); - } - else - { - ladderSelectedCallback(); - } - } - else if (controlID == buttonCancelID) - { - // reset what had been - populateLadderComboBox(); - - // tear down overlay - GameSpyCloseOverlay( GSOVERLAY_LADDERSELECT ); - } - else if (controlID == buttonPasswordOkID) - { - const LadderInfo *li = TheLadderList->findLadderByIndex( ladderIndex ); - if (!li || li->cryptedPassword.isEmpty()) - { - // eh? something's not right. just pretend they typed something wrong... - setPasswordMode(PASS_ERROR); - break; - } - - AsciiString pass; - pass.translate(GadgetTextEntryGetText(textEntryPassword)); - if ( pass.isNotEmpty() ) // password ok - { - AsciiString cryptPass = EncryptString(pass.str()); - DEBUG_LOG(("pass is %s, crypted pass is %s, comparing to %s\n", - pass.str(), cryptPass.str(), li->cryptedPassword.str())); - if (cryptPass == li->cryptedPassword) - ladderSelectedCallback(); - else - setPasswordMode(PASS_ERROR); - } - else - { - setPasswordMode(PASS_ERROR); - } - } - else if (controlID == buttonPasswordCancelID) - { - setPasswordMode(PASS_NONE); - } - else if (controlID == buttonBadPasswordOkID) - { - setPasswordMode(PASS_NONE); - } - break; - } // end input - - //--------------------------------------------------------------------------------------------- - case GLM_SELECTED: - { - Int selIndex, selID; - GadgetListBoxGetSelected(listboxLadderSelect, &selIndex); - if (selIndex < 0) - break; - - selID = (Int)GadgetListBoxGetItemData(listboxLadderSelect, selIndex); - if (!selID) - break; - - updateLadderDetails(selID, staticTextLadderName, listboxLadderDetails); - break; - } // end GLM_DOUBLE_CLICKED - - //--------------------------------------------------------------------------------------------- - case GLM_DOUBLE_CLICKED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - Int selectPos = (Int)mData2; - GadgetListBoxSetSelected(control, &selectPos); - - if( controlID == listboxLadderSelectID ) - { - TheWindowManager->winSendSystemMsg( parent, GBM_SELECTED, - (WindowMsgData)buttonOk, buttonOk->winGetWindowId() ); - } - break; - } - - //--------------------------------------------------------------------------------------------- - case GEM_EDIT_DONE: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if (controlID == textEntryPasswordID) - { - TheWindowManager->winSendSystemMsg( parent, GBM_SELECTED, - (WindowMsgData)(TheWindowManager->winGetWindowFromId(passwordParent, buttonPasswordOkID)), buttonPasswordOkID ); - } - break; - } - - default: - return MSG_IGNORED; - - } // end switch - - return MSG_HANDLED; - -} - - -//----------------------------------------------------------------------------- -// PRIVATE FUNCTIONS ////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -static void updateLadderDetails( Int selID, GameWindow *staticTextLadderName, GameWindow *listboxLadderDetails ) -{ - if (!staticTextLadderName || !listboxLadderDetails) - return; - - GadgetStaticTextSetText(staticTextLadderName, UnicodeString::TheEmptyString); - GadgetListBoxReset(listboxLadderDetails); - - const LadderInfo *info = TheLadderList->findLadderByIndex(selID); - if (!info) - return; - - UnicodeString line; - Color color = GameMakeColor( 255, 255, 255, 255 ); - Color captionColor = GameMakeColor( 0, 255, 255, 255 ); - - // name - line.format(TheGameText->fetch("GUI:LadderNameAndSize"), info->name.str(), info->playersPerTeam, info->playersPerTeam); - GadgetStaticTextSetText(staticTextLadderName, line); - - // location - if (!info->location.isEmpty()) - GadgetListBoxAddEntryText(listboxLadderDetails, info->location, captionColor, -1); - - // homepage - line.format(TheGameText->fetch("GUI:LadderURL"), info->homepageURL.str()); - GadgetListBoxAddEntryText(listboxLadderDetails, line, captionColor, -1); - - // description - if (!info->description.isEmpty()) - GadgetListBoxAddEntryText(listboxLadderDetails, info->description, color, -1); - - // requires password? - if (info->cryptedPassword.isNotEmpty()) - { - GadgetListBoxAddEntryText(listboxLadderDetails, TheGameText->fetch("GUI:LadderHasPassword"), captionColor, -1); - } - - // wins limits - if (info->minWins) - { - line.format(TheGameText->fetch("GUI:LadderMinWins"), info->minWins); - GadgetListBoxAddEntryText(listboxLadderDetails, line, captionColor, -1); - } - if (info->maxWins) - { - line.format(TheGameText->fetch("GUI:LadderMaxWins"), info->maxWins); - GadgetListBoxAddEntryText(listboxLadderDetails, line, captionColor, -1); - } - - // random factions? - if (info->randomFactions) - { - GadgetListBoxAddEntryText(listboxLadderDetails, TheGameText->fetch("GUI:LadderRandomFactions"), captionColor, -1); - } - else - { - GadgetListBoxAddEntryText(listboxLadderDetails, TheGameText->fetch("GUI:LadderFactions"), captionColor, -1); - } - - // factions - AsciiStringList validFactions = info->validFactions; - for (AsciiStringListIterator it = validFactions.begin(); it != validFactions.end(); ++it) - { - AsciiString marker; - marker.format("INI:Faction%s", it->str()); - GadgetListBoxAddEntryText(listboxLadderDetails, TheGameText->fetch(marker), color, -1); - } - - // random maps? - if (info->randomMaps) - { - GadgetListBoxAddEntryText(listboxLadderDetails, TheGameText->fetch("GUI:LadderRandomMaps"), captionColor, -1); - } - else - { - GadgetListBoxAddEntryText(listboxLadderDetails, TheGameText->fetch("GUI:LadderMaps"), captionColor, -1); - } - - // maps - AsciiStringList validMaps = info->validMaps; - for (it = validMaps.begin(); it != validMaps.end(); ++it) - { - const MapMetaData *md = TheMapCache->findMap(*it); - if (md) - { - GadgetListBoxAddEntryText(listboxLadderDetails, md->m_displayName, color, -1); - } - } -} - -static void closeRightClickMenu(GameWindow *win) -{ - - if(win) - { - WindowLayout *winLay = win->winGetLayout(); - if(!winLay) - return; - winLay->destroyWindows(); - winLay->deleteInstance(); - winLay = NULL; - - } -} -void RCGameDetailsMenuInit( WindowLayout *layout, void *userData ) -{ -} - -WindowMsgHandledType RCGameDetailsMenuSystem( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 ) -{ - - static NameKeyType ladderInfoID = NAMEKEY_INVALID; - static NameKeyType buttonOkID = NAMEKEY_INVALID; - switch( msg ) - { - - case GWM_CREATE: - { - ladderInfoID = NAMEKEY("RCGameDetailsMenu.wnd:ButtonLadderDetails"); - buttonOkID = NAMEKEY("PopupLadderDetails.wnd:ButtonOk"); - break; - } // case GWM_DESTROY: - - case GGM_CLOSE: - { - closeRightClickMenu(window); - //rcMenu = NULL; - break; - } - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GBM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - Int selectedID = (Int)window->winGetUserData(); - if(!selectedID) - break; - closeRightClickMenu(window); - - if (controlID == ladderInfoID) - { - StagingRoomMap *srm = TheGameSpyInfo->getStagingRoomList(); - StagingRoomMap::iterator srmIt = srm->find(selectedID); - if (srmIt != srm->end()) - { - GameSpyStagingRoom *theRoom = srmIt->second; - if (!theRoom) - break; - const LadderInfo *linfo = TheLadderList->findLadder(theRoom->getLadderIP(), theRoom->getLadderPort()); - if (linfo) - { - WindowLayout *rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/PopupLadderDetails.wnd")); - if (!rcLayout) - break; - - GameWindow *rcMenu = rcLayout->getFirstWindow(); - rcMenu->winGetLayout()->runInit(); - rcMenu->winBringToTop(); - rcMenu->winHide(FALSE); - - rcMenu->winSetUserData((void *)selectedID); - TheWindowManager->winSetLoneWindow(rcMenu); - - GameWindow *st = TheWindowManager->winGetWindowFromId(NULL, - NAMEKEY("PopupLadderDetails.wnd:StaticTextLadderName")); - GameWindow *lb = TheWindowManager->winGetWindowFromId(NULL, - NAMEKEY("PopupLadderDetails.wnd:ListBoxLadderDetails")); - updateLadderDetails(selectedID, st, lb); - } - } - } - break; - } - default: - return MSG_IGNORED; - - }//Switch - return MSG_HANDLED; -} diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp deleted file mode 100644 index 55db148badc..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp +++ /dev/null @@ -1,1453 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLBuddyOverlay.cpp -// Author: Chris Huybregts, November 2001 -// Description: Lan Lobby Menu -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/AudioEventRTS.h" -#include "Common/PlayerList.h" -#include "Common/Player.h" -#include "GameClient/GameText.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetPushButton.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/GadgetRadioButton.h" -#include "GameClient/Display.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/BuddyDefs.h" -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/LobbyUtils.h" -#include "GameNetwork/GameSpy/PersistentStorageDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpy/ThreadUtils.h" - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentID = NAMEKEY_INVALID; -static NameKeyType buttonHideID = NAMEKEY_INVALID; -static NameKeyType buttonAddBuddyID = NAMEKEY_INVALID; -static NameKeyType buttonDeleteBuddyID = NAMEKEY_INVALID; -static NameKeyType textEntryID = NAMEKEY_INVALID; -static NameKeyType listboxBuddyID = NAMEKEY_INVALID; -static NameKeyType listboxChatID = NAMEKEY_INVALID; -static NameKeyType buttonAcceptBuddyID = NAMEKEY_INVALID; -static NameKeyType buttonDenyBuddyID = NAMEKEY_INVALID; -static NameKeyType radioButtonBuddiesID = NAMEKEY_INVALID; -static NameKeyType radioButtonIgnoreID = NAMEKEY_INVALID; -static NameKeyType parentBuddiesID = NAMEKEY_INVALID; -static NameKeyType parentIgnoreID = NAMEKEY_INVALID; -static NameKeyType listboxIgnoreID = NAMEKEY_INVALID; -static NameKeyType buttonNotificationID = NAMEKEY_INVALID; - - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parent = NULL; -static GameWindow *buttonHide = NULL; -static GameWindow *buttonAddBuddy = NULL; -static GameWindow *buttonDeleteBuddy = NULL; -static GameWindow *textEntry = NULL; -static GameWindow *listboxBuddy = NULL; -static GameWindow *listboxChat = NULL; -static GameWindow *buttonAcceptBuddy = NULL; -static GameWindow *buttonDenyBuddy = NULL; -static GameWindow *radioButtonBuddies = NULL; -static GameWindow *radioButtonIgnore = NULL; -static GameWindow *parentBuddies = NULL; -static GameWindow *parentIgnore = NULL; -static GameWindow *listboxIgnore = NULL; - -static Bool isOverlayActive = false; -void insertChat( BuddyMessage msg ); -// RightClick pointers --------------------------------------------------------------------- -static GameWindow *rcMenu = NULL; -static WindowLayout *noticeLayout = NULL; -static UnsignedInt noticeExpires = 0; -enum { NOTIFICATION_EXPIRES = 3000 }; - -void setUnignoreText( WindowLayout *layout, AsciiString nick, GPProfile id); -void refreshIgnoreList( void ); -void showNotificationBox( AsciiString nick, UnicodeString message); -void deleteNotificationBox( void ); -static Bool lastNotificationWasStatus = FALSE; -static Int numOnlineInNotification = 0; - -class BuddyControls -{ -public: - BuddyControls(void ); - GameWindow *listboxChat; - NameKeyType listboxChatID; - - GameWindow *listboxBuddies; - NameKeyType listboxBuddiesID; - - GameWindow *textEntryEdit; - NameKeyType textEntryEditID; - Bool isInit; -}; - -static BuddyControls buddyControls; -BuddyControls::BuddyControls( void ) -{ - listboxChat = NULL; - listboxChatID = NAMEKEY_INVALID; - listboxBuddies = NULL; - listboxBuddiesID = NAMEKEY_INVALID; - textEntryEdit = NULL; - textEntryEditID = NAMEKEY_INVALID; - isInit = FALSE; -} -// At this point I don't give a damn about how good this way is. I'm doing it anyway. -enum -{ - BUDDY_RESETALL_CRAP = -1, - BUDDY_WINDOW_BUDDIES = 0, - BUDDY_WINDOW_DIPLOMACY, - BUDDY_WINDOW_WELCOME_SCREEN, -}; - -void InitBuddyControls(Int type) -{ - if(!TheGameSpyInfo) - { - buddyControls.textEntryEditID = NAMEKEY_INVALID; - buddyControls.textEntryEdit = NULL; - buddyControls.listboxBuddiesID = NAMEKEY_INVALID; - buddyControls.listboxChatID = NAMEKEY_INVALID; - buddyControls.listboxBuddies = NULL; - buddyControls.listboxChat = NULL; - buddyControls.isInit = FALSE; - return; - } - switch (type) { - case BUDDY_RESETALL_CRAP: - buddyControls.textEntryEditID = NAMEKEY_INVALID; - buddyControls.textEntryEdit = NULL; - buddyControls.listboxBuddiesID = NAMEKEY_INVALID; - buddyControls.listboxChatID = NAMEKEY_INVALID; - buddyControls.listboxBuddies = NULL; - buddyControls.listboxChat = NULL; - buddyControls.isInit = FALSE; - break; - case BUDDY_WINDOW_BUDDIES: - buddyControls.textEntryEditID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:TextEntryChat" ) ); - buddyControls.textEntryEdit = TheWindowManager->winGetWindowFromId(NULL, buddyControls.textEntryEditID); - buddyControls.listboxBuddiesID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ListboxBuddies" ) ); - buddyControls.listboxChatID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ListboxBuddyChat" ) ); - buddyControls.listboxBuddies = TheWindowManager->winGetWindowFromId( NULL, buddyControls.listboxBuddiesID ); - buddyControls.listboxChat = TheWindowManager->winGetWindowFromId( NULL, buddyControls.listboxChatID); - GadgetTextEntrySetText(buddyControls.textEntryEdit, UnicodeString.TheEmptyString); - buddyControls.isInit = TRUE; - break; - case BUDDY_WINDOW_DIPLOMACY: - buddyControls.textEntryEditID = TheNameKeyGenerator->nameToKey( AsciiString( "Diplomacy.wnd:TextEntryChat" ) ); - buddyControls.textEntryEdit = TheWindowManager->winGetWindowFromId(NULL, buddyControls.textEntryEditID); - buddyControls.listboxBuddiesID = TheNameKeyGenerator->nameToKey( AsciiString( "Diplomacy.wnd:ListboxBuddies" ) ); - buddyControls.listboxChatID = TheNameKeyGenerator->nameToKey( AsciiString( "Diplomacy.wnd:ListboxBuddyChat" ) ); - buddyControls.listboxBuddies = TheWindowManager->winGetWindowFromId( NULL, buddyControls.listboxBuddiesID ); - buddyControls.listboxChat = TheWindowManager->winGetWindowFromId( NULL, buddyControls.listboxChatID); - GadgetTextEntrySetText(buddyControls.textEntryEdit, UnicodeString.TheEmptyString); - buddyControls.isInit = TRUE; - break; - case BUDDY_WINDOW_WELCOME_SCREEN: - break; - default: - DEBUG_ASSERTCRASH(FALSE, ("Well, you really shouldn't have gotten here, if you really care about GUI Bugs, search for this string, you you don't care, call chris (who probably doesn't care either")); - } - -} - -WindowMsgHandledType BuddyControlSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2) -{ - if(!TheGameSpyInfo || TheGameSpyInfo->getLocalProfileID() == 0 || !buddyControls.isInit) - { - return MSG_IGNORED; - } - - switch( msg ) - { - case GLM_RIGHT_CLICKED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if( controlID == buddyControls.listboxBuddiesID ) - { - RightClickStruct *rc = (RightClickStruct *)mData2; - WindowLayout *rcLayout; - if(rc->pos < 0) - break; - - GPProfile profileID = (GPProfile)GadgetListBoxGetItemData(control, rc->pos, 0); - RCItemType itemType = (RCItemType)(Int)GadgetListBoxGetItemData(control, rc->pos, 1); - UnicodeString nick = GadgetListBoxGetText(control, rc->pos); - - GadgetListBoxSetSelected(control, rc->pos); - if (itemType == ITEM_BUDDY) - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCBuddiesMenu.wnd")); - else if (itemType == ITEM_REQUEST) - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCBuddyRequestMenu.wnd")); - else - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCNonBuddiesMenu.wnd")); - rcMenu = rcLayout->getFirstWindow(); - rcMenu->winGetLayout()->runInit(); - rcMenu->winBringToTop(); - rcMenu->winHide(FALSE); - - - ICoord2D rcSize, rcPos; - rcMenu->winGetSize(&rcSize.x, &rcSize.y); - rcPos.x = rc->mouseX; - rcPos.y = rc->mouseY; - if(rc->mouseX + rcSize.x > TheDisplay->getWidth()) - rcPos.x = TheDisplay->getWidth() - rcSize.x; - if(rc->mouseY + rcSize.y > TheDisplay->getHeight()) - rcPos.y = TheDisplay->getHeight() - rcSize.y; - rcMenu->winSetPosition(rcPos.x, rcPos.y); - - - GameSpyRCMenuData *rcData = NEW GameSpyRCMenuData; - rcData->m_id = profileID; - rcData->m_nick.translate(nick); - rcData->m_itemType = itemType; - setUnignoreText(rcLayout, rcData->m_nick, rcData->m_id); - rcMenu->winSetUserData((void *)rcData); - TheWindowManager->winSetLoneWindow(rcMenu); - } - else - return MSG_IGNORED; - break; - } - case GEM_EDIT_DONE: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if(controlID != buddyControls.textEntryEditID) - return MSG_IGNORED; - - // see if someone's selected - Int selected = -1; - GadgetListBoxGetSelected(buddyControls.listboxBuddies, &selected); - if (selected >= 0) - { - GPProfile selectedProfile = (GPProfile)GadgetListBoxGetItemData(buddyControls.listboxBuddies, selected); - BuddyInfoMap *m = TheGameSpyInfo->getBuddyMap(); - BuddyInfoMap::iterator recipIt = m->find(selectedProfile); - if (recipIt == m->end()) - break; - - DEBUG_LOG(("Trying to send a buddy message to %d.\n", selectedProfile)); - if (TheGameSpyGame && TheGameSpyGame->isInGame() && TheGameSpyGame->isGameInProgress() && - !ThePlayerList->getLocalPlayer()->isPlayerActive()) - { - DEBUG_LOG(("I'm dead - gotta look for cheats.\n")); - for (Int i=0; igetGameSpySlot(i)->getProfileID())); - if (TheGameSpyGame->getGameSpySlot(i)->getProfileID() == selectedProfile) - { - // can't send to someone in our game if we're dead/observing. security breach and all that. no seances for you. - if (buddyControls.listboxChat) - { - GadgetListBoxAddEntryText( buddyControls.listboxChat, TheGameText->fetch("Buddy:CantTalkToIngameBuddy"), - GameSpyColor[GSCOLOR_DEFAULT], -1, -1 ); - } - return MSG_HANDLED; - } - } - } - - // read the user's input and clear the entry box - UnicodeString txtInput; - txtInput.set(GadgetTextEntryGetText( buddyControls.textEntryEdit )); - GadgetTextEntrySetText(buddyControls.textEntryEdit, UnicodeString::TheEmptyString); - txtInput.trim(); - if (!txtInput.isEmpty()) - { - // Send the message - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_MESSAGE; - wcsncpy(req.arg.message.text, txtInput.str(), MAX_BUDDY_CHAT_LEN); - req.arg.message.text[MAX_BUDDY_CHAT_LEN-1] = 0; - req.arg.message.recipient = selectedProfile; - TheGameSpyBuddyMessageQueue->addRequest(req); - - // save message for future incarnations of the buddy window - BuddyMessageList *messages = TheGameSpyInfo->getBuddyMessages(); - BuddyMessage message; - message.m_timestamp = time(NULL); - message.m_senderID = TheGameSpyInfo->getLocalProfileID(); - message.m_senderNick = TheGameSpyInfo->getLocalBaseName(); - message.m_recipientID = selectedProfile; - message.m_recipientNick = recipIt->second.m_name; - message.m_message = UnicodeString(req.arg.message.text); - messages->push_back(message); - - // put message on screen - insertChat(message); - } - } - else - { - // nobody selected. Prompt the user. - if (buddyControls.listboxChat) - { - GadgetListBoxAddEntryText( buddyControls.listboxChat, TheGameText->fetch("Buddy:SelectBuddyToChat"), - GameSpyColor[GSCOLOR_DEFAULT], -1, -1 ); - } - } - break; - } - default: - return MSG_IGNORED; - } - return MSG_HANDLED; -} - - -static void insertChat( BuddyMessage msg ) -{ - if (buddyControls.listboxChat) - { - BuddyInfoMap *m = TheGameSpyInfo->getBuddyMap(); - BuddyInfoMap::iterator senderIt = m->find(msg.m_senderID); - BuddyInfoMap::iterator recipientIt = m->find(msg.m_recipientID); - Bool localSender = (msg.m_senderID == TheGameSpyInfo->getLocalProfileID()); - UnicodeString s; - //UnicodeString timeStr = UnicodeString(_wctime( (const time_t *)&msg.m_timestamp )); - UnicodeString timeStr; - if (localSender /*&& recipientIt != m->end()*/) - { - s.format(L"[%hs -> %hs] %s", TheGameSpyInfo->getLocalBaseName().str(), msg.m_recipientNick.str(), msg.m_message.str()); - Int index = GadgetListBoxAddEntryText( buddyControls.listboxChat, s, GameSpyColor[GSCOLOR_PLAYER_SELF], -1, -1 ); - GadgetListBoxAddEntryText( buddyControls.listboxChat, timeStr, GameSpyColor[GSCOLOR_PLAYER_SELF], index, 1); - } - else if (!localSender /*&& senderIt != m->end()*/) - { - if (!msg.m_senderID) - { - s = msg.m_message; - Int index = GadgetListBoxAddEntryText( buddyControls.listboxChat, s, GameSpyColor[GSCOLOR_DEFAULT], -1, -1 ); - GadgetListBoxAddEntryText( buddyControls.listboxChat, timeStr, GameSpyColor[GSCOLOR_DEFAULT], index, 1); - } - else - { - s.format(L"[%hs] %s", msg.m_senderNick.str(), msg.m_message.str()); - Int index = GadgetListBoxAddEntryText( buddyControls.listboxChat, s, GameSpyColor[GSCOLOR_PLAYER_BUDDY], -1, -1 ); - GadgetListBoxAddEntryText( buddyControls.listboxChat, timeStr, GameSpyColor[GSCOLOR_PLAYER_BUDDY], index, 1); - } - } - } -} - -void updateBuddyInfo( void ) -{ - if (!TheGameSpyBuddyMessageQueue->isConnected()) - { - GadgetListBoxReset(buddyControls.listboxBuddies); - return; - } - - if (!buddyControls.isInit) - return; - - int selected; - GPProfile selectedProfile = 0; - int visiblePos = GadgetListBoxGetTopVisibleEntry(buddyControls.listboxBuddies); - - GadgetListBoxGetSelected(buddyControls.listboxBuddies, &selected); - if (selected >= 0) - selectedProfile = (GPProfile)GadgetListBoxGetItemData(buddyControls.listboxBuddies, selected); - - selected = -1; - GadgetListBoxReset(buddyControls.listboxBuddies); - - // Add buddies - BuddyInfoMap *buddies = TheGameSpyInfo->getBuddyMap(); - BuddyInfoMap::iterator bIt; - for (bIt = buddies->begin(); bIt != buddies->end(); ++bIt) - { - BuddyInfo info = bIt->second; - GPProfile profileID = bIt->first; - - // insert name into box - UnicodeString formatStr; - formatStr.translate(info.m_name.str());//, info.m_status, info.m_statusString.str(), info.m_locationString.str()); - Color nameColor = (TheGameSpyInfo->isSavedIgnored(profileID)) ? - GameSpyColor[GSCOLOR_PLAYER_IGNORED] : GameSpyColor[GSCOLOR_PLAYER_BUDDY]; - int index = GadgetListBoxAddEntryText(buddyControls.listboxBuddies, formatStr, nameColor, -1, -1); - - // insert status into box - AsciiString marker; - marker.format("Buddy:%ls", info.m_statusString.str()); - if (!info.m_statusString.compareNoCase(L"Offline") || - !info.m_statusString.compareNoCase(L"Online") || - !info.m_statusString.compareNoCase(L"Matching")) - { - formatStr = TheGameText->fetch(marker); - } - else if (!info.m_statusString.compareNoCase(L"Staging") || - !info.m_statusString.compareNoCase(L"Loading") || - !info.m_statusString.compareNoCase(L"Playing")) - { - formatStr.format(TheGameText->fetch(marker), info.m_locationString.str()); - } - else if (!info.m_statusString.compareNoCase(L"Chatting")) - { - UnicodeString roomName; - GroupRoomMap::iterator gIt = TheGameSpyInfo->getGroupRoomList()->find( _wtoi(info.m_locationString.str()) ); - if (gIt != TheGameSpyInfo->getGroupRoomList()->end()) - { - AsciiString s; - s.format("GUI:%s", gIt->second.m_name.str()); - roomName = TheGameText->fetch(s); - } - formatStr.format(TheGameText->fetch(marker), roomName.str()); - } - else - { - formatStr = info.m_statusString; - } - GadgetListBoxAddEntryText(buddyControls.listboxBuddies, formatStr, GameSpyColor[GSCOLOR_DEFAULT], index, 1); - GadgetListBoxSetItemData(buddyControls.listboxBuddies, (void *)(profileID), index, 0 ); - GadgetListBoxSetItemData(buddyControls.listboxBuddies, (void *)(ITEM_BUDDY), index, 1 ); - - if (profileID == selectedProfile) - selected = index; - } - - // add requests - buddies = TheGameSpyInfo->getBuddyRequestMap(); - for (bIt = buddies->begin(); bIt != buddies->end(); ++bIt) - { - BuddyInfo info = bIt->second; - GPProfile profileID = bIt->first; - - // insert name into box - UnicodeString formatStr; - formatStr.translate(info.m_name.str()); - int index = GadgetListBoxAddEntryText(buddyControls.listboxBuddies, formatStr, GameSpyColor[GSCOLOR_DEFAULT], -1, -1); - GadgetListBoxSetItemData(buddyControls.listboxBuddies, (void *)(profileID), index, 0 ); - - // insert status into box - formatStr = TheGameText->fetch("GUI:BuddyAddReq"); - GadgetListBoxAddEntryText(buddyControls.listboxBuddies, formatStr, GameSpyColor[GSCOLOR_DEFAULT], index, 1); - GadgetListBoxSetItemData(buddyControls.listboxBuddies, (void *)(ITEM_REQUEST), index, 1 ); - - if (profileID == selectedProfile) - selected = index; - } - - - // select the same guy - if (selected >= 0) - { - GadgetListBoxSetSelected(buddyControls.listboxBuddies, selected); - } - - // view the same spot - GadgetListBoxSetTopVisibleEntry(buddyControls.listboxBuddies, visiblePos); -} - -void HandleBuddyResponses( void ) -{ - if (TheGameSpyBuddyMessageQueue) - { - BuddyResponse resp; - if (TheGameSpyBuddyMessageQueue->getResponse( resp )) - { - switch (resp.buddyResponseType) - { - case BuddyResponse::BUDDYRESPONSE_LOGIN: - { - deleteNotificationBox(); - } - break; - case BuddyResponse::BUDDYRESPONSE_DISCONNECT: - { - lastNotificationWasStatus = FALSE; - numOnlineInNotification = 0; - showNotificationBox(AsciiString::TheEmptyString, TheGameText->fetch("Buddy:MessageDisconnected")); - } - break; - case BuddyResponse::BUDDYRESPONSE_MESSAGE: - { - if ( !wcscmp(resp.arg.message.text, L"I have authorized your request to add me to your list") ) - break; - - if (TheGameSpyInfo->isSavedIgnored(resp.profile)) - { - //DEBUG_CRASH(("Player is ignored!\n")); - break; // no buddy messages from ignored people - } - - // save message for future incarnations of the buddy window - BuddyMessageList *messages = TheGameSpyInfo->getBuddyMessages(); - BuddyMessage message; - message.m_timestamp = resp.arg.message.date; - message.m_senderID = resp.profile; - message.m_recipientID = TheGameSpyInfo->getLocalProfileID(); - message.m_recipientNick = TheGameSpyInfo->getLocalBaseName(); - message.m_message = resp.arg.message.text; - // insert status into box - BuddyInfoMap *m = TheGameSpyInfo->getBuddyMap(); - BuddyInfoMap::iterator senderIt = m->find(message.m_senderID); - AsciiString nick; - if (senderIt != m->end()) - nick = senderIt->second.m_name.str(); - else - nick = resp.arg.message.nick; - message.m_senderNick = nick; - messages->push_back(message); - - DEBUG_LOG(("Inserting buddy chat from '%s'/'%s'\n", nick.str(), resp.arg.message.nick)); - - // put message on screen - insertChat(message); - - // play audio notification - AudioEventRTS buddyMsgAudio("GUIMessageReceived"); - if( TheAudio ) - { - TheAudio->addAudioEvent( &buddyMsgAudio ); - } // end if - - UnicodeString snippet = message.m_message; - while (snippet.getLength() > 11) - { - snippet.removeLastChar(); - } - UnicodeString s; - s.format(TheGameText->fetch("Buddy:MessageNotification"), nick.str(), snippet.str()); - lastNotificationWasStatus = FALSE; - numOnlineInNotification = 0; - showNotificationBox(AsciiString::TheEmptyString, s); - } - break; - case BuddyResponse::BUDDYRESPONSE_REQUEST: - { - // save request for future incarnations of the buddy window - BuddyInfoMap *m = TheGameSpyInfo->getBuddyRequestMap(); - BuddyInfo info; - info.m_countryCode = resp.arg.request.countrycode; - info.m_email = resp.arg.request.email; - info.m_name = resp.arg.request.nick; - info.m_id = resp.profile; - info.m_status = (GPEnum)0; - info.m_statusString = resp.arg.request.text; - (*m)[resp.profile] = info; - - // TODO: put request on screen - updateBuddyInfo(); - // insert status into box - lastNotificationWasStatus = FALSE; - numOnlineInNotification = 0; - showNotificationBox(info.m_name, TheGameText->fetch("Buddy:AddNotification")); - } - break; - case BuddyResponse::BUDDYRESPONSE_STATUS: - { - BuddyInfoMap *m = TheGameSpyInfo->getBuddyMap(); - BuddyInfoMap::const_iterator bit = m->find(resp.profile); - Bool seenPreviously = FALSE; - GPEnum oldStatus = GP_OFFLINE; - GPEnum newStatus = resp.arg.status.status; - if (bit != m->end()) - { - seenPreviously = TRUE; - oldStatus = (*m)[resp.profile].m_status; - } - BuddyInfo info; - info.m_countryCode = resp.arg.status.countrycode; - info.m_email = resp.arg.status.email; - info.m_name = resp.arg.status.nick; - info.m_id = resp.profile; - info.m_status = newStatus; - info.m_statusString = UnicodeString(MultiByteToWideCharSingleLine(resp.arg.status.statusString).c_str()); - info.m_locationString = UnicodeString(MultiByteToWideCharSingleLine(resp.arg.status.location).c_str()); - (*m)[resp.profile] = info; - - updateBuddyInfo(); - PopulateLobbyPlayerListbox(); - RefreshGameListBoxes(); - if ( (newStatus == GP_OFFLINE && seenPreviously) || - (newStatus == GP_ONLINE && (oldStatus == GP_OFFLINE || !seenPreviously)) ) - //if (!info.m_statusString.compareNoCase(L"Offline") || - //!info.m_statusString.compareNoCase(L"Online")) - { - // insert status into box - AsciiString marker; - marker.format("Buddy:%lsNotification", info.m_statusString.str()); - - lastNotificationWasStatus = TRUE; - if (newStatus != GP_OFFLINE) - ++numOnlineInNotification; - - showNotificationBox(info.m_name, TheGameText->fetch(marker)); - } - else if( newStatus == GP_RECV_GAME_INVITE && !seenPreviously) - { - lastNotificationWasStatus = TRUE; - if (newStatus != GP_OFFLINE) - ++numOnlineInNotification; - - showNotificationBox(info.m_name, TheGameText->fetch("Buddy:OnlineNotification")); - } - } - break; - } - } - } - else - { - DEBUG_CRASH(("No buddy message queue!\n")); - } - if(noticeLayout && timeGetTime() > noticeExpires) - { - deleteNotificationBox(); - } -} - -void showNotificationBox( AsciiString nick, UnicodeString message) -{ -// if(!GameSpyIsOverlayOpen(GSOVERLAY_BUDDY)) -// return; - if( !noticeLayout ) - noticeLayout = TheWindowManager->winCreateLayout( "Menus/PopupBuddyListNotification.wnd" ); - noticeLayout->hide( FALSE ); - if (buttonNotificationID == NAMEKEY_INVALID) - { - buttonNotificationID = TheNameKeyGenerator->nameToKey("PopupBuddyListNotification.wnd:ButtonNotification"); - } - GameWindow *win = TheWindowManager->winGetWindowFromId(NULL,buttonNotificationID); - if(!win) - { - deleteNotificationBox(); - return; - } - - if (lastNotificationWasStatus && numOnlineInNotification > 1) - { - message = TheGameText->fetch("Buddy:MultipleOnlineNotification"); - } - - if (nick.isNotEmpty()) - message.format(message, nick.str()); - GadgetButtonSetText(win, message); - //GadgetStaticTextSetText(win, message); - noticeExpires = timeGetTime() + NOTIFICATION_EXPIRES; - noticeLayout->bringForward(); - - AudioEventRTS buttonClick("GUICommunicatorIncoming"); - - if( TheAudio ) - { - TheAudio->addAudioEvent( &buttonClick ); - } // end if - -} - -void deleteNotificationBox( void ) -{ - lastNotificationWasStatus = FALSE; - numOnlineInNotification = 0; - if(noticeLayout) - { - noticeLayout->destroyWindows(); - noticeLayout->deleteInstance(); - noticeLayout = NULL; - } -} - -void PopulateOldBuddyMessages(void) -{ - // show previous messages - BuddyMessageList *messages = TheGameSpyInfo->getBuddyMessages(); - for (BuddyMessageList::iterator mIt = messages->begin(); mIt != messages->end(); ++mIt) - { - BuddyMessage message = *mIt; - insertChat(message); - } -} - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Buddy Overlay */ -//------------------------------------------------------------------------------------------------- -void WOLBuddyOverlayInit( WindowLayout *layout, void *userData ) -{ - parentID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:BuddyMenuParent" ) ); - buttonHideID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ButtonHide" ) ); - buttonAddBuddyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ButtonAdd" ) ); - buttonDeleteBuddyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ButtonDelete" ) ); - //textEntryID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:TextEntryChat" ) ); - //listboxBuddyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ListboxBuddies" ) ); - //listboxChatID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ListboxBuddyChat" ) ); - buttonAcceptBuddyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ButtonYes" ) ); - buttonDenyBuddyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ButtonNo" ) ); - radioButtonBuddiesID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:RadioButtonBuddies" ) ); - radioButtonIgnoreID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:RadioButtonIgnore" ) ); - parentBuddiesID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:BuddiesParent" ) ); - parentIgnoreID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:IgnoreParent" ) ); - listboxIgnoreID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ListboxIgnore" ) ); - - - parent = TheWindowManager->winGetWindowFromId( NULL, parentID ); - buttonHide = TheWindowManager->winGetWindowFromId( parent, buttonHideID); - buttonAddBuddy = TheWindowManager->winGetWindowFromId( parent, buttonAddBuddyID); - buttonDeleteBuddy = TheWindowManager->winGetWindowFromId( parent, buttonDeleteBuddyID); - // textEntry = TheWindowManager->winGetWindowFromId( parent, textEntryID); - //listboxBuddy = TheWindowManager->winGetWindowFromId( parent, listboxBuddyID); - //listboxChat = TheWindowManager->winGetWindowFromId( parent, listboxChatID); - buttonAcceptBuddy = TheWindowManager->winGetWindowFromId( parent, buttonAcceptBuddyID); - buttonDenyBuddy = TheWindowManager->winGetWindowFromId( parent, buttonDenyBuddyID); - radioButtonBuddies = TheWindowManager->winGetWindowFromId( parent, radioButtonBuddiesID); - radioButtonIgnore = TheWindowManager->winGetWindowFromId( parent, radioButtonIgnoreID); - parentBuddies = TheWindowManager->winGetWindowFromId( parent, parentBuddiesID); - parentIgnore = TheWindowManager->winGetWindowFromId( parent, parentIgnoreID); - listboxIgnore = TheWindowManager->winGetWindowFromId( parent, listboxIgnoreID); - - InitBuddyControls(BUDDY_WINDOW_BUDDIES); - - GadgetRadioSetSelection(radioButtonBuddies,FALSE); - parentBuddies->winHide(FALSE); - parentIgnore->winHide(TRUE); - - //GadgetTextEntrySetText(textEntry, UnicodeString.TheEmptyString); - - PopulateOldBuddyMessages(); - - // Show Menu - layout->hide( FALSE ); - - // Set Keyboard to Main Parent - TheWindowManager->winSetFocus( parent ); - - isOverlayActive = true; - updateBuddyInfo(); - -} // WOLBuddyOverlayInit - -//------------------------------------------------------------------------------------------------- -/** WOL Buddy Overlay shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLBuddyOverlayShutdown( WindowLayout *layout, void *userData ) -{ - listboxIgnore = NULL; - - // hide menu - layout->hide( TRUE ); - - // our shutdown is complete - //TheShell->shutdownComplete( layout ); - - isOverlayActive = false; - - InitBuddyControls(BUDDY_RESETALL_CRAP); - -} // WOLBuddyOverlayShutdown - - -//------------------------------------------------------------------------------------------------- -/** WOL Buddy Overlay update method */ -//------------------------------------------------------------------------------------------------- -void WOLBuddyOverlayUpdate( WindowLayout * layout, void *userData) -{ - if (!TheGameSpyBuddyMessageQueue || !TheGameSpyBuddyMessageQueue->isConnected()) - GameSpyCloseOverlay(GSOVERLAY_BUDDY); -}// WOLBuddyOverlayUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Buddy Overlay input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLBuddyOverlayInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonHide, buttonHideID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// WOLBuddyOverlayInput - -//------------------------------------------------------------------------------------------------- -/** WOL Buddy Overlay window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLBuddyOverlaySystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - if(BuddyControlSystem(window, msg, mData1, mData2) == MSG_HANDLED) - { - return MSG_HANDLED; - } - switch( msg ) - { - - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - case GLM_RIGHT_CLICKED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if( controlID == listboxIgnoreID ) - { - RightClickStruct *rc = (RightClickStruct *)mData2; - WindowLayout *rcLayout; - if(rc->pos < 0) - break; - - Bool isBuddy = false, isRequest = false; - GPProfile profileID = (GPProfile)GadgetListBoxGetItemData(control, rc->pos); - UnicodeString nick = GadgetListBoxGetText(control, rc->pos); - BuddyInfoMap *buddies = TheGameSpyInfo->getBuddyMap(); - BuddyInfoMap::iterator bIt; - bIt = buddies->find(profileID); - if (bIt != buddies->end()) - { - isBuddy = true; - } - else - { - buddies = TheGameSpyInfo->getBuddyRequestMap(); - bIt = buddies->find(profileID); - if (bIt != buddies->end()) - { - isRequest = true; - } - else - { - // neither buddy nor request - //break; - } - } - - GadgetListBoxSetSelected(control, rc->pos); - if (isBuddy) - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCBuddiesMenu.wnd")); - else if (isRequest) - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCBuddyRequestMenu.wnd")); - else - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCNonBuddiesMenu.wnd")); - rcMenu = rcLayout->getFirstWindow(); - rcMenu->winGetLayout()->runInit(); - rcMenu->winBringToTop(); - rcMenu->winHide(FALSE); - - - - rcMenu->winSetPosition(rc->mouseX, rc->mouseY); - GameSpyRCMenuData *rcData = NEW GameSpyRCMenuData; - rcData->m_id = profileID; - rcData->m_nick.translate(nick); - rcData->m_itemType = (isBuddy)?ITEM_BUDDY:((isRequest)?ITEM_REQUEST:ITEM_NONBUDDY); - setUnignoreText(rcLayout, rcData->m_nick, rcData->m_id); - rcMenu->winSetUserData((void *)rcData); - TheWindowManager->winSetLoneWindow(rcMenu); - } - break; - } - case GBM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if (controlID == buttonHideID) - { - GameSpyCloseOverlay( GSOVERLAY_BUDDY ); - } - else if (controlID == radioButtonBuddiesID) - { - parentBuddies->winHide(FALSE); - parentIgnore->winHide(TRUE); - } - else if (controlID == radioButtonIgnoreID) - { - parentBuddies->winHide(TRUE); - parentIgnore->winHide(FALSE); - refreshIgnoreList(); - } - else if (controlID == buttonAddBuddyID) - { - /* - UnicodeString uName = GadgetTextEntryGetText(textEntry); - AsciiString aName; - aName.translate(uName); - if (!aName.isEmpty()) - { - TheWOLBuddyList->requestBuddyAdd(aName); - } - GadgetTextEntrySetText(textEntry, UnicodeString::TheEmptyString); - */ - } - else if (controlID == buttonDeleteBuddyID) - { - /* - int selected; - AsciiString selectedName = AsciiString::TheEmptyString; - - GadgetListBoxGetSelected(listbox, &selected); - if (selected >= 0) - selectedName = TheNameKeyGenerator->keyToName((NameKeyType)(int)GadgetListBoxGetItemData(listbox, selected)); - - if (!selectedName.isEmpty()) - { - TheWOLBuddyList->requestBuddyDelete(selectedName); - } - */ - } - break; - }// case GBM_SELECTED: - case GLM_DOUBLE_CLICKED: - { - /* - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if( controlID == listboxBuddyID ) - { - int rowSelected = mData2; - - if (rowSelected >= 0) - { - UnicodeString buddyName; - GameWindow *listboxWindow = TheWindowManager->winGetWindowFromId( parent, listboxBuddyID ); - - // get text of buddy name - buddyName = GadgetListBoxGetText( listboxWindow, rowSelected,0 ); - GPProfile buddyID = (GPProfile)GadgetListBoxGetItemData( listboxWindow, rowSelected, 0 ); - - Int index = -1; - gpGetBuddyIndex(TheGPConnection, buddyID, &index); - if (index >= 0) - { - GPBuddyStatus status; - gpGetBuddyStatus(TheGPConnection, rowSelected, &status); - - UnicodeString string; - string.format(L"To join %s in %hs:", buddyName.str(), status.locationString); - GameSpyAddText(string, GSCOLOR_DEFAULT); - - if (status.status == GP_CHATTING) - { - AsciiString location = status.locationString; - AsciiString val; - location.nextToken(&val, "/"); - location.nextToken(&val, "/"); - location.nextToken(&val, "/"); - - string.format(L" ???"); - if (!val.isEmpty()) - { - Int groupRoom = atoi(val.str()); - if (TheGameSpyChat->getCurrentGroupRoomID() == groupRoom) - { - // already there - string.format(L" nothing"); - GameSpyAddText(string, GSCOLOR_DEFAULT); - } - else - { - GroupRoomMap *rooms = TheGameSpyChat->getGroupRooms(); - if (rooms) - { - Bool needToJoin = true; - GroupRoomMap::iterator it = rooms->find(groupRoom); - if (it != rooms->end()) - { - // he's in a different room - if (TheGameSpyChat->getCurrentGroupRoomID()) - { - string.format(L" leave group room"); - GameSpyAddText(string, GSCOLOR_DEFAULT); - - TheGameSpyChat->leaveRoom(GroupRoom); - } - else if (TheGameSpyGame->isInGame()) - { - if (TheGameSpyGame->isGameInProgress()) - { - string.format(L" can't leave game in progress"); - GameSpyAddText(string, GSCOLOR_DEFAULT); - needToJoin = false; - } - else - { - string.format(L" leave game setup"); - GameSpyAddText(string, GSCOLOR_DEFAULT); - - TheGameSpyChat->leaveRoom(StagingRoom); - TheGameSpyGame->leaveGame(); - } - } - if (needToJoin) - { - string.format(L" join lobby %d", groupRoom); - TheGameSpyChat->joinGroupRoom(groupRoom); - GameSpyAddText(string, GSCOLOR_DEFAULT); - } - } - } - } - } - } - } - else - { - DEBUG_CRASH(("No buddy associated with that ProfileID")); - GameSpyUpdateBuddyOverlay(); - } - } - } - */ - break; - } - - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLBuddyOverlaySystem - -WindowMsgHandledType PopupBuddyNotificationSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - case GWM_CREATE: - { - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GBM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if (controlID == buttonNotificationID) - { - GameSpyOpenOverlay( GSOVERLAY_BUDDY ); - } - break; - } - - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// PopupBuddyNotificationSystem - -/* -static NameKeyType buttonAcceptBuddyID = NAMEKEY_INVALID; -static NameKeyType buttonDenyBuddyID = NAMEKEY_INVALID; -*/ -static NameKeyType buttonAddID = NAMEKEY_INVALID; -static NameKeyType buttonDeleteID = NAMEKEY_INVALID; -static NameKeyType buttonPlayID = NAMEKEY_INVALID; -static NameKeyType buttonIgnoreID = NAMEKEY_INVALID; -static NameKeyType buttonStatsID = NAMEKEY_INVALID; -// Window Pointers ------------------------------------------------------------------------ -//static GameWindow *rCparent = NULL; - - -//------------------------------------------------------------------------------------------------- -/** WOL Buddy Overlay Right Click menu callbacks */ -//------------------------------------------------------------------------------------------------- -void WOLBuddyOverlayRCMenuInit( WindowLayout *layout, void *userData ) -{ - AsciiString controlName; - controlName.format("%s:ButtonAdd",layout->getFilename().str()+6); - buttonAddID = TheNameKeyGenerator->nameToKey( controlName ); - controlName.format("%s:ButtonDelete",layout->getFilename().str()+6); - buttonDeleteID = TheNameKeyGenerator->nameToKey( controlName ); - controlName.format("%s:ButtonPlay",layout->getFilename().str()+6); - buttonPlayID = TheNameKeyGenerator->nameToKey( controlName ); - controlName.format("%s:ButtonIgnore",layout->getFilename().str()+6); - buttonIgnoreID = TheNameKeyGenerator->nameToKey( controlName ); - controlName.format("%s:ButtonStats",layout->getFilename().str()+6); - buttonStatsID = TheNameKeyGenerator->nameToKey( controlName ); -} -static void closeRightClickMenu(GameWindow *win) -{ - - if(win) - { - WindowLayout *winLay = win->winGetLayout(); - if(!winLay) - return; - winLay->destroyWindows(); - winLay->deleteInstance(); - winLay = NULL; - - } -} - -void RequestBuddyAdd(Int profileID, AsciiString nick) -{ - // request to add a buddy - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_ADDBUDDY; - req.arg.addbuddy.id = profileID; - UnicodeString buddyAddstr; - buddyAddstr = TheGameText->fetch("GUI:BuddyAddReq"); - wcsncpy(req.arg.addbuddy.text, buddyAddstr.str(), MAX_BUDDY_CHAT_LEN); - req.arg.addbuddy.text[MAX_BUDDY_CHAT_LEN-1] = 0; - TheGameSpyBuddyMessageQueue->addRequest(req); - - UnicodeString s; - Bool exists = TRUE; - s.format(TheGameText->fetch("Buddy:InviteSent", &exists)); - if (!exists) - { - // no string yet. don't display. - return; - } - - // save message for future incarnations of the buddy window - BuddyMessageList *messages = TheGameSpyInfo->getBuddyMessages(); - BuddyMessage message; - message.m_timestamp = time(NULL); - message.m_senderID = 0; - message.m_senderNick = ""; - message.m_recipientID = TheGameSpyInfo->getLocalProfileID(); - message.m_recipientNick = TheGameSpyInfo->getLocalBaseName(); - message.m_message.format(TheGameText->fetch("Buddy:InviteSentToPlayer"), nick.str()); - - // insert status into box - messages->push_back(message); - - DEBUG_LOG(("Inserting buddy add request\n")); - - // put message on screen - insertChat(message); - - // play audio notification - AudioEventRTS buddyMsgAudio("GUIMessageReceived"); - if( TheAudio ) - { - TheAudio->addAudioEvent( &buddyMsgAudio ); - } // end if - - lastNotificationWasStatus = FALSE; - numOnlineInNotification = 0; - showNotificationBox(AsciiString::TheEmptyString, s); -} - -WindowMsgHandledType WOLBuddyOverlayRCMenuSystem( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 ) -{ - - switch( msg ) - { - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - rcMenu = NULL; - break; - } // case GWM_DESTROY: - - case GGM_CLOSE: - { - closeRightClickMenu(window); - //rcMenu = NULL; - break; - } - - - case GBM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - GameSpyRCMenuData *rcData = (GameSpyRCMenuData*)window->winGetUserData(); - if(!rcData) - break; - DEBUG_ASSERTCRASH(rcData, ("WOLBuddyOverlayRCMenuSystem GBM_SELECTED:: we're attempting to read the GameSpyRCMenuData from the window, but the data's not there")); - GPProfile profileID = rcData->m_id; - AsciiString nick = rcData->m_nick; - - Bool isBuddy = false, isRequest = false; - Bool isGameSpyUser = profileID > 0; - if (rcData->m_itemType == ITEM_BUDDY) - isBuddy = TRUE; - else if (rcData->m_itemType == ITEM_REQUEST) - isRequest = TRUE; - - if(rcData) - { - delete rcData; - rcData = NULL; - } - window->winSetUserData(NULL); - //DEBUG_ASSERTCRASH(profileID > 0, ("Bad profile ID in user data!")); - - if( controlID == buttonAddID ) - { - if(!isGameSpyUser) - break; - DEBUG_LOG(("ButtonAdd was pushed\n")); - if (isRequest) - { - // ok the request - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_OKADD; - req.arg.profile.id = profileID; - TheGameSpyBuddyMessageQueue->addRequest(req); - - BuddyInfoMap *m = TheGameSpyInfo->getBuddyRequestMap(); - m->erase( profileID ); - - // DONT CHECK IN UNTIL MATT HAS REVIEWED - // if the profile ID is not from a buddy and we're okaying his request, then - // request to add him to our list automatically CLH 2-18-03 - if(!TheGameSpyInfo->isBuddy(profileID)) - { - RequestBuddyAdd(profileID, nick); - } - updateBuddyInfo(); - - } - else if (!isBuddy) - { - RequestBuddyAdd(profileID, nick); - } - } - else if( controlID == buttonDeleteID ) - { - if(!isGameSpyUser) - break; - if (isBuddy) - { - // delete the buddy - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_DELBUDDY; - req.arg.profile.id = profileID; - TheGameSpyBuddyMessageQueue->addRequest(req); - } - else - { - // delete the request - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_DENYADD; - req.arg.profile.id = profileID; - TheGameSpyBuddyMessageQueue->addRequest(req); - BuddyInfoMap *m = TheGameSpyInfo->getBuddyRequestMap(); - m->erase( profileID ); - } - BuddyInfoMap *buddies = (isBuddy)?TheGameSpyInfo->getBuddyMap():TheGameSpyInfo->getBuddyRequestMap(); - buddies->erase(profileID); - updateBuddyInfo(); - DEBUG_LOG(("ButtonDelete was pushed\n")); - PopulateLobbyPlayerListbox(); - } - else if( controlID == buttonPlayID ) - { - DEBUG_LOG(("buttonPlayID was pushed\n")); - } - else if( controlID == buttonIgnoreID ) - { - DEBUG_LOG(("%s is isGameSpyUser %d", nick.str(), isGameSpyUser)); - if( isGameSpyUser ) - { - if(TheGameSpyInfo->isSavedIgnored(profileID)) - { - TheGameSpyInfo->removeFromSavedIgnoreList(profileID); - } - else - { - TheGameSpyInfo->addToSavedIgnoreList(profileID, nick); - } - } - else - { - if(TheGameSpyInfo->isIgnored(nick)) - { - TheGameSpyInfo->removeFromIgnoreList(nick); - } - else - { - TheGameSpyInfo->addToIgnoreList(nick); - } - } - updateBuddyInfo(); - refreshIgnoreList(); - // repopulate our player listboxes now - PopulateLobbyPlayerListbox(); - } - else if( controlID == buttonStatsID ) - { - DEBUG_LOG(("buttonStatsID was pushed\n")); - GameSpyCloseOverlay(GSOVERLAY_PLAYERINFO); - SetLookAtPlayer(profileID,nick ); - GameSpyOpenOverlay(GSOVERLAY_PLAYERINFO); - PSRequest req; - req.requestType = PSRequest::PSREQUEST_READPLAYERSTATS; - req.player.id = profileID; - TheGameSpyPSMessageQueue->addRequest(req); - } - closeRightClickMenu(window); - break; - } - default: - return MSG_IGNORED; - - }//Switch - return MSG_HANDLED; -} - - -void setUnignoreText( WindowLayout *layout, AsciiString nick, GPProfile id) -{ - AsciiString controlName; - controlName.format("%s:ButtonIgnore",layout->getFilename().str()+6); - NameKeyType ID = TheNameKeyGenerator->nameToKey( controlName ); - GameWindow *win = TheWindowManager->winGetWindowFromId(layout->getFirstWindow(), ID); - if(win) - { - if(TheGameSpyInfo->isSavedIgnored(id) || TheGameSpyInfo->isIgnored(nick)) - GadgetButtonSetText(win, TheGameText->fetch("GUI:Unignore")); - } -} - -void refreshIgnoreList( void ) -{ - - - SavedIgnoreMap tempMap; - tempMap = TheGameSpyInfo->returnSavedIgnoreList(); - SavedIgnoreMap::iterator it = tempMap.begin(); - GadgetListBoxReset(listboxIgnore); - while(it != tempMap.end()) - { - UnicodeString name; - name.translate(it->second); - Int pos = GadgetListBoxAddEntryText(listboxIgnore, name, GameMakeColor(255,100,100,255),-1); - GadgetListBoxSetItemData(listboxIgnore, (void *)it->first,pos ); - ++it; - } - IgnoreList tempList; - tempList = TheGameSpyInfo->returnIgnoreList(); - IgnoreList::iterator iListIt = tempList.begin(); - while( iListIt != tempList.end()) - { - AsciiString aName = *iListIt; - UnicodeString name; - name.translate(aName); - Int pos = GadgetListBoxAddEntryText(listboxIgnore, name, GameMakeColor(255,100,100,255),-1); - GadgetListBoxSetItemData(listboxIgnore, 0,pos ); - ++iListIt; - } - -// -// GPProfile profileID = 0; -// PlayerInfoMap::iterator it = TheGameSpyInfo->getPlayerInfoMap()->find(aName); -// if (it != TheGameSpyInfo->getPlayerInfoMap()->end()) -// profileID = it->second.m_profileID; - -} diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLCustomScoreScreen.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLCustomScoreScreen.cpp deleted file mode 100644 index d0bfe524d77..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLCustomScoreScreen.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLCustomScoreScreen.cpp -// Author: Matt Campbell, December 2001 -// Description: Custom match score screen -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Lib/BaseType.h" -#include "Common/GameEngine.h" -#include "Common/NameKeyGenerator.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetTextEntry.h" -#include "Common/GlobalData.h" -//#include "GameNetwork/WOL.h" -//#include "GameNetwork/WOLmenus.h" - - - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentWOLCustomScoreID = NAMEKEY_INVALID; -static NameKeyType buttonDisconnectID = NAMEKEY_INVALID; -static NameKeyType buttonLobbyID = NAMEKEY_INVALID; - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentWOLCustomScore = NULL; -static GameWindow *buttonDisconnect = NULL; -static GameWindow *buttonLobby = NULL; - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Status Menu */ -//------------------------------------------------------------------------------------------------- -void WOLCustomScoreScreenInit( WindowLayout *layout, void *userData ) -{ - parentWOLCustomScoreID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLCustomScoreScreen.wnd:WOLCustomScoreScreenParent" ) ); - buttonDisconnectID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLCustomScoreScreen.wnd:ButtonDisconnect" ) ); - buttonLobbyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLCustomScoreScreen.wnd:ButtonLobby" ) ); - parentWOLCustomScore = TheWindowManager->winGetWindowFromId( NULL, parentWOLCustomScoreID ); - buttonDisconnect = TheWindowManager->winGetWindowFromId( NULL, buttonDisconnectID); - buttonLobby = TheWindowManager->winGetWindowFromId( NULL, buttonLobbyID); - - /* - if (WOL::TheWOL->getState() == WOL::WOLAPI_FATAL_ERROR) - { - // We can get to the score screen even though we've been disconnected. Just hide - // any buttons that lead back into WOL. - buttonLobby->winHide( TRUE ); - } - */ - - // Show Menu - layout->hide( FALSE ); - - // Set Keyboard to Main Parent - TheWindowManager->winSetFocus( parentWOLCustomScore ); -} // WOLCustomScoreScreenInit - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLCustomScoreScreenShutdown( WindowLayout *layout, void *userData ) -{ - // hide menu - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout ); -} // WOLCustomScoreScreenShutdown - - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLCustomScoreScreenUpdate( WindowLayout * layout, void *userData) -{ - /* - if (WOL::TheWOL) - WOL::TheWOL->update(); - */ -}// WOLCustomScoreScreenUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLCustomScoreScreenInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonDisconnect, buttonDisconnectID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// WOLCustomScoreScreenInput - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLCustomScoreScreenSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - - switch( msg ) - { - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're given the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - case GBM_SELECTED: - { - /* - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if ( controlID == buttonDisconnectID ) - { - if (WOL::TheWOL->setState( WOL::WOLAPI_FATAL_ERROR )) - { - WOL::TheWOL->addCommand( WOL::WOLCOMMAND_RESET ); // don't display an error, log out, or anything - } - - } //if ( controlID == buttonDisconnect ) - else if ( controlID == buttonLobbyID ) - { - if (WOL::TheWOL->getState() != WOL::WOLAPI_FATAL_ERROR) - { - WOL::TheWOL->setScreen(WOL::WOLAPI_MENU_CUSTOMLOBBY); - WOL::TheWOL->setGameMode(WOL::WOLTYPE_CUSTOM); - WOL::TheWOL->setState( WOL::WOLAPI_LOBBY ); - WOL::TheWOL->addCommand( WOL::WOLCOMMAND_REFRESH_CHANNELS ); - } - else - { - } - } //if ( controlID == buttonDisconnect ) - */ - break; - }// case GBM_SELECTED: - - case GEM_EDIT_DONE: - { - break; - } - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLCustomScoreScreenSystem diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp deleted file mode 100644 index 81329e4f53a..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp +++ /dev/null @@ -1,2689 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLGameSetupMenu.cpp -// Author: Matt Campbell, December 2001 -// Description: WOL Game Options Menu -/////////////////////////////////////////////////////////////////////////////////////// - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "Common/GameState.h" -#include "GameClient/GameText.h" -#include "Common/MultiplayerSettings.h" -#include "Common/PlayerTemplate.h" -#include "Common/CustomMatchPreferences.h" -#include "GameClient/AnimateWindowManager.h" -#include "GameClient/InGameUI.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Mouse.h" -#include "GameClient/Gadget.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetComboBox.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/GadgetPushButton.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/MapUtil.h" -#include "GameClient/EstablishConnectionsMenu.h" -#include "GameClient/GameWindowTransitions.h" - -#include "GameNetwork/GameSpy/BuddyDefs.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PersistentStorageDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameNetwork/NAT.h" -#include "GameNetwork/GUIUtil.h" -#include "GameNetwork/GameSpy/GSConfig.h" - -void WOLDisplaySlotList( void ); - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -extern std::list TheLobbyQueuedUTMs; -extern void MapSelectorTooltip(GameWindow *window, WinInstanceData *instData, UnsignedInt mouse); - - -#if defined(_DEBUG) || defined(_INTERNAL) -extern Bool g_debugSlots; -void slotListDebugLog(const char *fmt, ...) -{ - static char buf[1024]; - va_list va; - va_start( va, fmt ); - _vsnprintf(buf, 1024, fmt, va ); - va_end( va ); - buf[1023] = 0; - - DEBUG_LOG(("%s", buf)); - if (g_debugSlots) - { - UnicodeString msg; - msg.translate(buf); - TheGameSpyInfo->addText(msg, GameSpyColor[GSCOLOR_DEFAULT], NULL); - } -} -#define SLOTLIST_DEBUG_LOG(x) slotListDebugLog x -#else -#define SLOTLIST_DEBUG_LOG(x) DEBUG_LOG(x) -#endif - -void SendStatsToOtherPlayers(const GameInfo *game) -{ - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "STATS/"; - AsciiString fullStr; - PSPlayerStats fullStats = TheGameSpyPSMessageQueue->findPlayerStatsByID(TheGameSpyInfo->getLocalProfileID()); - PSPlayerStats subStats; - subStats.id = fullStats.id; - subStats.wins = fullStats.wins; - subStats.losses = fullStats.losses; - subStats.discons = fullStats.discons; - subStats.desyncs = fullStats.desyncs; - subStats.games = fullStats.games; - subStats.locale = fullStats.locale; - subStats.gamesAsRandom = fullStats.gamesAsRandom; - GetAdditionalDisconnectsFromUserFile(&subStats); - fullStr.format("%d %s", TheGameSpyInfo->getLocalProfileID(), TheGameSpyPSMessageQueue->formatPlayerKVPairs( subStats )); - req.options = fullStr.str(); - - Int localIndex = game->getLocalSlotNum(); - for (Int i=0; igetConstSlot(i); - if (slot->isHuman() && i != localIndex) - { - AsciiString hostName; - hostName.translate(slot->getName()); - req.nick = hostName.str(); - DEBUG_LOG(("SendStatsToOtherPlayers() - sending to '%s', data of\n\t'%s'\n", hostName.str(), req.options.c_str())); - TheGameSpyPeerMessageQueue->addRequest(req); - } - } -} - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -static Bool isShuttingDown = false; -static Bool buttonPushed = false; -static char *nextScreen = NULL; -static Bool raiseMessageBoxes = false; -static Bool launchGameNext = FALSE; - -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentWOLGameSetupID = NAMEKEY_INVALID; - -static NameKeyType comboBoxPlayerID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; - -static NameKeyType staticTextPlayerID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; - -static NameKeyType buttonAcceptID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; - -static NameKeyType comboBoxColorID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; - -static NameKeyType comboBoxPlayerTemplateID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; - -static NameKeyType comboBoxTeamID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; -//static NameKeyType buttonStartPositionID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, -// NAMEKEY_INVALID,NAMEKEY_INVALID, -// NAMEKEY_INVALID,NAMEKEY_INVALID, -// NAMEKEY_INVALID,NAMEKEY_INVALID }; - -static NameKeyType buttonMapStartPositionID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; -static NameKeyType genericPingWindowID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; - -static NameKeyType textEntryChatID = NAMEKEY_INVALID; -static NameKeyType textEntryMapDisplayID = NAMEKEY_INVALID; -static NameKeyType buttonBackID = NAMEKEY_INVALID; -static NameKeyType buttonStartID = NAMEKEY_INVALID; -static NameKeyType buttonEmoteID = NAMEKEY_INVALID; -static NameKeyType buttonSelectMapID = NAMEKEY_INVALID; -static NameKeyType windowMapID = NAMEKEY_INVALID; - -static NameKeyType windowMapSelectMapID = NAMEKEY_INVALID; -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentWOLGameSetup = NULL; -static GameWindow *buttonBack = NULL; -static GameWindow *buttonStart = NULL; -static GameWindow *buttonSelectMap = NULL; -static GameWindow *buttonEmote = NULL; -static GameWindow *textEntryChat = NULL; -static GameWindow *textEntryMapDisplay = NULL; -static GameWindow *windowMap = NULL; - -static GameWindow *comboBoxPlayer[MAX_SLOTS] = {NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL }; -static GameWindow *staticTextPlayer[MAX_SLOTS] = {NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL }; -static GameWindow *buttonAccept[MAX_SLOTS] = {NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL }; - -static GameWindow *comboBoxColor[MAX_SLOTS] = {NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL }; - -static GameWindow *comboBoxPlayerTemplate[MAX_SLOTS] = {NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL }; - -static GameWindow *comboBoxTeam[MAX_SLOTS] = {NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL }; - -//static GameWindow *buttonStartPosition[MAX_SLOTS] = {NULL,NULL,NULL,NULL, -// NULL,NULL,NULL,NULL }; -// -static GameWindow *buttonMapStartPosition[MAX_SLOTS] = {NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL }; - -static GameWindow *genericPingWindow[MAX_SLOTS] = {NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL }; - -static const Image *pingImages[3] = { NULL, NULL, NULL }; - -WindowLayout *WOLMapSelectLayout = NULL; - -void PopBackToLobby( void ) -{ - // delete TheNAT, its no good for us anymore. - delete TheNAT; - TheNAT = NULL; - - if (TheGameSpyInfo) // this can be blown away by a disconnect on the map transfer screen - { - TheGameSpyInfo->getCurrentStagingRoom()->reset(); - TheGameSpyInfo->leaveStagingRoom(); - //TheGameSpyInfo->joinBestGroupRoom(); - } - - DEBUG_LOG(("PopBackToLobby() - parentWOLGameSetup is %X\n", parentWOLGameSetup)); - if (parentWOLGameSetup) - { - nextScreen = "Menus/WOLCustomLobby.wnd"; - TheShell->pop(); - } -} - -void updateMapStartSpots( GameInfo *myGame, GameWindow *buttonMapStartPositions[], Bool onLoadScreen = FALSE ); -void positionStartSpots( GameInfo *myGame, GameWindow *buttonMapStartPositions[], GameWindow *mapWindow); -void positionStartSpots(AsciiString mapName, GameWindow *buttonMapStartPositions[], GameWindow *mapWindow); -void WOLPositionStartSpots( void ) -{ - GameWindow *win = windowMap; - - if (WOLMapSelectLayout != NULL) { - win = TheWindowManager->winGetWindowFromId(NULL, windowMapSelectMapID); - - // get the controls. - NameKeyType listboxMapID = TheNameKeyGenerator->nameToKey( AsciiString("WOLMapSelectMenu.wnd:ListboxMap") ); - GameWindow *listboxMap = TheWindowManager->winGetWindowFromId( NULL, listboxMapID ); - - if (listboxMap != NULL) { - Int selected; - UnicodeString map; - - // get the selected index - GadgetListBoxGetSelected( listboxMap, &selected ); - - if( selected != -1 ) - { - - // get text of the map to load - map = GadgetListBoxGetText( listboxMap, selected, 0 ); - - - // set the map name in the global data map name - AsciiString asciiMap; - const char *mapFname = (const char *)GadgetListBoxGetItemData( listboxMap, selected ); - DEBUG_ASSERTCRASH(mapFname, ("No map item data")); - if (mapFname) { - asciiMap = mapFname; - } else { - asciiMap.translate( map ); - } - - positionStartSpots(asciiMap, buttonMapStartPosition, win); - } - } - - } else { - DEBUG_ASSERTCRASH(win != NULL, ("no map preview window")); - positionStartSpots( TheGameSpyInfo->getCurrentStagingRoom(), buttonMapStartPosition, win); - } -} -static void savePlayerInfo( void ) -{ - if (TheGameSpyGame) - { - Int slotNum = TheGameSpyGame->getLocalSlotNum(); - if (slotNum >= 0) - { - GameSpyGameSlot *slot = TheGameSpyGame->getGameSpySlot(slotNum); - if (slot) - { - // save off some prefs - CustomMatchPreferences pref; - pref.setPreferredColor(slot->getColor()); - pref.setPreferredFaction(slot->getPlayerTemplate()); - if (TheGameSpyGame->amIHost()) - { - pref.setPreferredMap(TheGameSpyGame->getMap()); - } - pref.write(); - } - } - } -} - -// Tooltips ------------------------------------------------------------------------------- - -static void playerTooltip(GameWindow *window, - WinInstanceData *instData, - UnsignedInt mouse) -{ - Int slotIdx = -1; - for (Int i=0; isetCursorTooltip( UnicodeString::TheEmptyString, -1, NULL, 1.5f ); - return; - } - - GameSpyStagingRoom *game = TheGameSpyInfo->getCurrentStagingRoom(); - if (!game) - { - TheMouse->setCursorTooltip( UnicodeString::TheEmptyString, -1, NULL, 1.5f ); - return; - } - - GameSpyGameSlot *slot = game->getGameSpySlot(slotIdx); - if (!slot || !slot->isHuman()) - { - TheMouse->setCursorTooltip( UnicodeString::TheEmptyString, -1, NULL, 1.5f ); - return; - } - - // for tooltip, we want: - // * player name - // * ping - // * locale - // * win/loss history - // * discons/desyncs as one var - // * favorite army - // in that order. got it? good. - - UnicodeString uName = slot->getName(); - - AsciiString aName; - aName.translate(uName); - PlayerInfoMap::iterator pmIt = TheGameSpyInfo->getPlayerInfoMap()->find(aName); - if (pmIt == TheGameSpyInfo->getPlayerInfoMap()->end()) - { - TheMouse->setCursorTooltip( uName, -1, NULL, 1.5f ); - return; - } - Int profileID = pmIt->second.m_profileID; - - PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(profileID); - if (stats.id == 0) - { - TheMouse->setCursorTooltip( uName, -1, NULL, 1.5f ); - return; - } - - Bool isLocalPlayer = slot == game->getGameSpySlot(game->getLocalSlotNum()); - - AsciiString localeIdentifier; - localeIdentifier.format("WOL:Locale%2.2d", stats.locale); - UnicodeString playerInfo; - Int totalWins = 0, totalLosses = 0, totalDiscons = 0; - PerGeneralMap::iterator it; - - for (it = stats.wins.begin(); it != stats.wins.end(); ++it) - { - totalWins += it->second; - } - for (it = stats.losses.begin(); it != stats.losses.end(); ++it) - { - totalLosses += it->second; - } - for (it = stats.discons.begin(); it != stats.discons.end(); ++it) - { - totalDiscons += it->second; - } - for (it = stats.desyncs.begin(); it != stats.desyncs.end(); ++it) - { - totalDiscons += it->second; - } - UnicodeString favoriteSide; - Int numGames = 0; - Int favorite = 0; - for(it = stats.games.begin(); it != stats.games.end(); ++it) - { - if(it->second >= numGames) - { - numGames = it->second; - favorite = it->first; - } - } - if(numGames == 0) - favoriteSide = TheGameText->fetch("GUI:None"); - else if( stats.gamesAsRandom >= numGames ) - favoriteSide = TheGameText->fetch("GUI:Random"); - else - { - const PlayerTemplate *fac = ThePlayerTemplateStore->getNthPlayerTemplate(favorite); - if (fac) - { - AsciiString side; - side.format("SIDE:%s", fac->getSide().str()); - - favoriteSide = TheGameText->fetch(side); - } - } - - playerInfo.format(TheGameText->fetch("TOOLTIP:StagingPlayerInfo"), - TheGameText->fetch(localeIdentifier).str(), - slot->getPingAsInt(), - totalWins, totalLosses, totalDiscons, - favoriteSide.str()); - - UnicodeString tooltip = UnicodeString::TheEmptyString; - if (isLocalPlayer) - { - tooltip.format(TheGameText->fetch("TOOLTIP:LocalPlayer"), uName.str()); - } - else - { - // not us - if (TheGameSpyInfo->getBuddyMap()->find(profileID) != TheGameSpyInfo->getBuddyMap()->end()) - { - // buddy - tooltip.format(TheGameText->fetch("TOOLTIP:BuddyPlayer"), uName.str()); - } - else - { - if (profileID) - { - // non-buddy profiled player - tooltip.format(TheGameText->fetch("TOOLTIP:ProfiledPlayer"), uName.str()); - } - else - { - // non-profiled player - tooltip.format(TheGameText->fetch("TOOLTIP:GenericPlayer"), uName.str()); - } - } - } - - tooltip.concat(playerInfo); - - TheMouse->setCursorTooltip( tooltip, -1, NULL, 1.5f ); // the text and width are the only params used. the others are the default values. -} - -void gameAcceptTooltip(GameWindow *window, WinInstanceData *instData, UnsignedInt mouse) -{ - Int x, y; - x = LOLONGTOSHORT(mouse); - y = HILONGTOSHORT(mouse); - - Int winPosX, winPosY, winWidth, winHeight; - - window->winGetScreenPosition(&winPosX, &winPosY); - - window->winGetSize(&winWidth, &winHeight); - - if ((x > winPosX && x < (winPosX + winWidth)) && (y > winPosY && y < (winPosY + winHeight))) - { - TheMouse->setCursorTooltip(TheGameText->fetch("TOOLTIP:GameAcceptance"), -1, NULL); - } -} - -void pingTooltip(GameWindow *window, WinInstanceData *instData, UnsignedInt mouse) -{ - Int x, y; - x = LOLONGTOSHORT(mouse); - y = HILONGTOSHORT(mouse); - - - Int winPosX, winPosY, winWidth, winHeight; - - window->winGetScreenPosition(&winPosX, &winPosY); - - window->winGetSize(&winWidth, &winHeight); - - if ((x > winPosX && x < (winPosX + winWidth)) && (y > winPosY && y < (winPosY + winHeight))) - { - TheMouse->setCursorTooltip(TheGameText->fetch("TOOLTIP:ConnectionSpeed"), -1, NULL); - } -} - -//external declarations of the Gadgets the callbacks can use -GameWindow *listboxGameSetupChat = NULL; -NameKeyType listboxGameSetupChatID = NAMEKEY_INVALID; - -static void handleColorSelection(int index) -{ - GameWindow *combo = comboBoxColor[index]; - Int color, selIndex; - GadgetComboBoxGetSelectedPos(combo, &selIndex); - color = (Int)GadgetComboBoxGetItemData(combo, selIndex); - - GameInfo *myGame = TheGameSpyInfo->getCurrentStagingRoom(); - - if (myGame) - { - GameSlot * slot = myGame->getSlot(index); - if (color == slot->getColor()) - return; - - if (color >= -1 && color < TheMultiplayerSettings->getNumColors()) - { - Bool colorAvailable = TRUE; - if(color != -1 ) - { - for(Int i=0; i getSlot(i); - if(color == checkSlot->getColor() && slot != checkSlot) - { - colorAvailable = FALSE; - break; - } - } - } - if(!colorAvailable) - return; - } - - slot->setColor(color); - - if (TheGameSpyInfo->amIHost()) - { - // send around a new slotlist - TheGameSpyInfo->setGameOptions(); - WOLDisplaySlotList(); - } - else - { - // request the color from the host - if (!slot->isPlayer(TheGameSpyInfo->getLocalName())) - return; - - AsciiString options; - options.format("Color=%d", color); - AsciiString hostName; - hostName.translate(myGame->getSlot(0)->getName()); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "REQ/"; - req.nick = hostName.str(); - req.options = options.str(); - TheGameSpyPeerMessageQueue->addRequest(req); - } - } -} - -static void handlePlayerTemplateSelection(int index) -{ - GameWindow *combo = comboBoxPlayerTemplate[index]; - Int playerTemplate, selIndex; - GadgetComboBoxGetSelectedPos(combo, &selIndex); - playerTemplate = (Int)GadgetComboBoxGetItemData(combo, selIndex); - GameInfo *myGame = TheGameSpyInfo->getCurrentStagingRoom(); - - if (myGame) - { - GameSlot * slot = myGame->getSlot(index); - if (playerTemplate == slot->getPlayerTemplate()) - return; - - Int oldTemplate = slot->getPlayerTemplate(); - slot->setPlayerTemplate(playerTemplate); - - if (oldTemplate == PLAYERTEMPLATE_OBSERVER) - { - // was observer, so populate color & team with all, and enable - GadgetComboBoxSetSelectedPos(comboBoxColor[index], 0); - GadgetComboBoxSetSelectedPos(comboBoxTeam[index], 0); - slot->setStartPos(-1); - } - else if (playerTemplate == PLAYERTEMPLATE_OBSERVER) - { - // is becoming observer, so populate color & team with random only, and disable - GadgetComboBoxSetSelectedPos(comboBoxColor[index], 0); - GadgetComboBoxSetSelectedPos(comboBoxTeam[index], 0); - slot->setStartPos(-1); - } - - - if (TheGameSpyInfo->amIHost()) - { - // send around a new slotlist - myGame->resetAccepted(); - TheGameSpyInfo->setGameOptions(); - WOLDisplaySlotList(); - } - else - { - // request the playerTemplate from the host - AsciiString options; - options.format("PlayerTemplate=%d", playerTemplate); - AsciiString hostName; - hostName.translate(myGame->getSlot(0)->getName()); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "REQ/"; - req.nick = hostName.str(); - req.options = options.str(); - TheGameSpyPeerMessageQueue->addRequest(req); - } - } -} - - -static void handleStartPositionSelection(Int player, int startPos) -{ - GameSpyStagingRoom *myGame = TheGameSpyInfo->getCurrentStagingRoom(); - - if (myGame) - { - GameSpyGameSlot * slot = myGame->getGameSpySlot(player); - if (!slot) - return; - - if (startPos == slot->getStartPos()) - return; - Bool skip = FALSE; - if (startPos < 0) - { - skip = TRUE; - } - - if(!skip) - { - Bool isAvailable = TRUE; - for(Int i = 0; i < MAX_SLOTS; ++i) - { - if(i != player && myGame->getSlot(i)->getStartPos() == startPos) - { - isAvailable = FALSE; - break; - } - } - if( !isAvailable ) - return; - } - slot->setStartPos(startPos); - - if (myGame->amIHost()) - { - // send around a new slotlist - myGame->resetAccepted(); - TheGameSpyInfo->setGameOptions(); - WOLDisplaySlotList(); - } - else - { - // request the color from the host - if (AreSlotListUpdatesEnabled()) - { - // request the playerTemplate from the host - AsciiString options; - options.format("StartPos=%d", slot->getStartPos()); - AsciiString hostName; - hostName.translate(myGame->getSlot(0)->getName()); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "REQ/"; - req.nick = hostName.str(); - req.options = options.str(); - TheGameSpyPeerMessageQueue->addRequest(req); - - } - } - } -} - - - -static void handleTeamSelection(int index) -{ - GameWindow *combo = comboBoxTeam[index]; - Int team, selIndex; - GadgetComboBoxGetSelectedPos(combo, &selIndex); - team = (Int)GadgetComboBoxGetItemData(combo, selIndex); - GameInfo *myGame = TheGameSpyInfo->getCurrentStagingRoom(); - - if (myGame) - { - GameSlot * slot = myGame->getSlot(index); - if (team == slot->getTeamNumber()) - return; - - slot->setTeamNumber(team); - - if (TheGameSpyInfo->amIHost()) - { - // send around a new slotlist - myGame->resetAccepted(); - TheGameSpyInfo->setGameOptions(); - WOLDisplaySlotList(); - } - else - { - // request the team from the host - AsciiString options; - options.format("Team=%d", team); - AsciiString hostName; - hostName.translate(myGame->getSlot(0)->getName()); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "REQ/"; - req.nick = hostName.str(); - req.options = options.str(); - TheGameSpyPeerMessageQueue->addRequest(req); - } - } -} - - -static void StartPressed(void) -{ - Bool isReady = TRUE; - Bool allHaveMap = TRUE; - Int playerCount = 0; - Int humanCount = 0; - GameSpyStagingRoom *myGame = TheGameSpyInfo->getCurrentStagingRoom(); - if (!myGame) - return; - - // see if everyone's accepted and count the number of players in the game - UnicodeString mapDisplayName; - const MapMetaData *mapData = TheMapCache->findMap( myGame->getMap() ); - Bool willTransfer = TRUE; - if (mapData) - { - mapDisplayName.format(L"%ls", mapData->m_displayName.str()); - willTransfer = !mapData->m_isOfficial; - } - else - { - mapDisplayName.format(L"%hs", myGame->getMap().str()); - willTransfer = WouldMapTransfer(myGame->getMap()); - } - for( int i = 0; i < MAX_SLOTS; i++ ) - { - if ((myGame->getSlot(i)->isAccepted() == FALSE) && (myGame->getSlot(i)->isHuman() == TRUE)) - { - isReady = FALSE; - if (!myGame->getSlot(i)->hasMap() && !willTransfer) - { - UnicodeString msg; - msg.format(TheGameText->fetch("GUI:PlayerNoMap"), myGame->getSlot(i)->getName().str(), mapDisplayName.str()); - TheGameSpyInfo->addText(msg, GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - allHaveMap = FALSE; - } - } - if(myGame->getSlot(i)->isOccupied() && myGame->getSlot(i)->getPlayerTemplate() != PLAYERTEMPLATE_OBSERVER) - { - if (myGame->getSlot(i)->isHuman()) - humanCount++; - playerCount++; - } - } - - // Check for too many players - const MapMetaData *md = TheMapCache->findMap( myGame->getMap() ); - if (!md || md->m_numPlayers < playerCount) - { - if (myGame->amIHost()) - { - UnicodeString text; - text.format(TheGameText->fetch("LAN:TooManyPlayers"), (md)?md->m_numPlayers:0); - TheGameSpyInfo->addText(text, GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - } - return; - } - - // Check for observer + AI players - if (TheGlobalData->m_netMinPlayers && !humanCount) - { - if (myGame->amIHost()) - { - UnicodeString text = TheGameText->fetch("GUI:NeedHumanPlayers"); - TheGameSpyInfo->addText(text, GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - } - return; - } - - // Check for too few players - if (playerCount < TheGlobalData->m_netMinPlayers) - { - if (myGame->amIHost()) - { - UnicodeString text; - text.format(TheGameText->fetch("LAN:NeedMorePlayers"),playerCount); - TheGameSpyInfo->addText(text, GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - } - return; - } - - // Check for too few teams - int numRandom = 0; - std::set teams; - for (i=0; igetSlot(i); - if (slot && slot->isOccupied() && slot->getPlayerTemplate() != PLAYERTEMPLATE_OBSERVER) - { - if (slot->getTeamNumber() >= 0) - { - teams.insert(slot->getTeamNumber()); - } - else - { - ++numRandom; - } - } - } - if (numRandom + teams.size() < TheGlobalData->m_netMinPlayers) - { - if (myGame->amIHost()) - { - UnicodeString text; - text.format(TheGameText->fetch("LAN:NeedMoreTeams")); - TheGameSpyInfo->addText(text, GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - } - return; - } - - if (numRandom + teams.size() < 2) - { - UnicodeString text; - text.format(TheGameText->fetch("GUI:SandboxMode")); - TheGameSpyInfo->addText(text, GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - } - - if(isReady) - { - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_STARTGAME; - TheGameSpyPeerMessageQueue->addRequest(req); - - SendStatsToOtherPlayers(myGame); - - // we've started, there's no going back - // i.e. disable the back button. - buttonBack->winEnable(FALSE); - GameWindow *buttonBuddy = TheWindowManager->winGetWindowFromId(NULL, NAMEKEY("GameSpyGameOptionsMenu.wnd:ButtonCommunicator")); - if (buttonBuddy) - buttonBuddy->winEnable(FALSE); - GameSpyCloseOverlay(GSOVERLAY_BUDDY); - - *TheGameSpyGame = *myGame; - TheGameSpyGame->startGame(0); - } - else if (allHaveMap) - { - TheGameSpyInfo->addText(TheGameText->fetch("GUI:NotifiedStartIntent"), GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMROOM; - req.UTM.isStagingRoom = TRUE; - req.id = "HWS/"; - req.options = "true"; - TheGameSpyPeerMessageQueue->addRequest(req); - } - -}//void StartPressed(void) - -//------------------------------------------------------------------------------------------------- -/** Update options on screen */ -//------------------------------------------------------------------------------------------------- -void WOLDisplayGameOptions( void ) -{ - GameSpyStagingRoom *theGame = TheGameSpyInfo->getCurrentStagingRoom(); - if (!parentWOLGameSetup || !theGame) - return; - - const GameSlot *localSlot = NULL; - if (theGame->getLocalSlotNum() >= 0) - localSlot = theGame->getConstSlot(theGame->getLocalSlotNum()); - - const MapMetaData *md = TheMapCache->findMap(TheGameSpyInfo->getCurrentStagingRoom()->getMap()); - if (md && localSlot && localSlot->hasMap()) - { - GadgetStaticTextSetText(textEntryMapDisplay, md->m_displayName); - } - else - { - AsciiString s = TheGameSpyInfo->getCurrentStagingRoom()->getMap(); - if (s.reverseFind('\\')) - { - s = s.reverseFind('\\') + 1; - } - UnicodeString mapDisplay; - mapDisplay.translate(s); - GadgetStaticTextSetText(textEntryMapDisplay, mapDisplay); - } - WOLPositionStartSpots(); - updateMapStartSpots(TheGameSpyInfo->getCurrentStagingRoom(), buttonMapStartPosition); -} - -// ----------------------------------------------------------------------------------------- -// The Bad munkee slot list displaying function -//------------------------------------------------------------------------------------------------- -void WOLDisplaySlotList( void ) -{ - if (!parentWOLGameSetup || !TheGameSpyInfo->getCurrentStagingRoom()) - return; - - GameSpyStagingRoom *game = TheGameSpyInfo->getCurrentStagingRoom(); - if (!game->isInGame()) - return; - - DEBUG_ASSERTCRASH(!game->getConstSlot(0)->isOpen(), ("Open host!")); - - UpdateSlotList( game, comboBoxPlayer, comboBoxColor, - comboBoxPlayerTemplate, comboBoxTeam, buttonAccept, buttonStart, buttonMapStartPosition ); - - WOLDisplayGameOptions(); - - for (Int i=0; igetGameSpySlot(i); - if (slot && slot->isHuman()) - { - if (i == game->getLocalSlotNum()) - { - // set up my own ping... - slot->setPingString(TheGameSpyInfo->getPingString()); - } - - if (genericPingWindow[i]) - { - genericPingWindow[i]->winHide(FALSE); - Int ping = slot->getPingAsInt(); - if (ping < TheGameSpyConfig->getPingCutoffGood()) - { - genericPingWindow[i]->winSetEnabledImage(0, pingImages[0]); - } - else if (ping < TheGameSpyConfig->getPingCutoffBad()) - { - genericPingWindow[i]->winSetEnabledImage(0, pingImages[1]); - } - else - { - genericPingWindow[i]->winSetEnabledImage(0, pingImages[2]); - } - } - } - else - { - if (genericPingWindow[i]) - genericPingWindow[i]->winHide(TRUE); - } - } -} - -//------------------------------------------------------------------------------------------------- -/** Initialize the Gadgets Options Menu */ -//------------------------------------------------------------------------------------------------- -void InitWOLGameGadgets( void ) -{ - GameSpyStagingRoom *theGameInfo = TheGameSpyInfo->getCurrentStagingRoom(); - pingImages[0] = TheMappedImageCollection->findImageByName("Ping03"); - pingImages[1] = TheMappedImageCollection->findImageByName("Ping02"); - pingImages[2] = TheMappedImageCollection->findImageByName("Ping01"); - DEBUG_ASSERTCRASH(pingImages[0], ("Can't find ping image!")); - DEBUG_ASSERTCRASH(pingImages[1], ("Can't find ping image!")); - DEBUG_ASSERTCRASH(pingImages[2], ("Can't find ping image!")); - - //Initialize the gadget IDs - parentWOLGameSetupID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:GameSpyGameOptionsMenuParent" ) ); - buttonBackID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:ButtonBack" ) ); - buttonStartID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:ButtonStart" ) ); - textEntryChatID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:TextEntryChat" ) ); - textEntryMapDisplayID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:TextEntryMapDisplay" ) ); - listboxGameSetupChatID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:ListboxChatWindowGameSpyGameSetup" ) ); - buttonEmoteID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:ButtonEmote" ) ); - buttonSelectMapID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:ButtonSelectMap" ) ); - windowMapID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:MapWindow" ) ); - windowMapSelectMapID = TheNameKeyGenerator->nameToKey(AsciiString("WOLMapSelectMenu.wnd:WinMapPreview")); - - NameKeyType staticTextTitleID = NAMEKEY("GameSpyGameOptionsMenu.wnd:StaticTextGameName"); - - // Initialize the pointers to our gadgets - parentWOLGameSetup = TheWindowManager->winGetWindowFromId( NULL, parentWOLGameSetupID ); - buttonEmote = TheWindowManager->winGetWindowFromId( parentWOLGameSetup,buttonEmoteID ); - buttonSelectMap = TheWindowManager->winGetWindowFromId( parentWOLGameSetup,buttonSelectMapID ); - buttonStart = TheWindowManager->winGetWindowFromId( parentWOLGameSetup,buttonStartID ); - buttonBack = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, buttonBackID); - listboxGameSetupChat = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, listboxGameSetupChatID ); - textEntryChat = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, textEntryChatID ); - textEntryMapDisplay = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, textEntryMapDisplayID ); - windowMap = TheWindowManager->winGetWindowFromId( parentWOLGameSetup,windowMapID ); - DEBUG_ASSERTCRASH(windowMap, ("Could not find the parentWOLGameSetup.wnd:MapWindow" )); - - //Added By Sadullah Nader - //Tooltip Function set - windowMap->winSetTooltipFunc(MapSelectorTooltip); - // - - GameWindow *staticTextTitle = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, staticTextTitleID ); - if (staticTextTitle) - { - GadgetStaticTextSetText(staticTextTitle, TheGameSpyGame->getGameName()); - } - - if (!theGameInfo) - { - DEBUG_CRASH(("No staging room!")); - return; - } - - for (Int i = 0; i < MAX_SLOTS; i++) - { - AsciiString tmpString; - tmpString.format("GameSpyGameOptionsMenu.wnd:ComboBoxPlayer%d", i); - comboBoxPlayerID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - comboBoxPlayer[i] = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, comboBoxPlayerID[i] ); - GadgetComboBoxReset(comboBoxPlayer[i]); - comboBoxPlayer[i]->winSetTooltipFunc(playerTooltip); - - tmpString.format("GameSpyGameOptionsMenu.wnd:StaticTextPlayer%d", i); - staticTextPlayerID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - staticTextPlayer[i] = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, staticTextPlayerID[i] ); - staticTextPlayer[i]->winSetTooltipFunc(playerTooltip); - if (TheGameSpyInfo->amIHost()) - staticTextPlayer[i]->winHide(TRUE); - - if(i==0 && TheGameSpyInfo->amIHost()) - { - UnicodeString uName; - uName.translate(TheGameSpyInfo->getLocalName()); - GadgetComboBoxAddEntry(comboBoxPlayer[i],uName,GameSpyColor[GSCOLOR_PLAYER_OWNER]); - GadgetComboBoxSetSelectedPos(comboBoxPlayer[0],0); - } - else - { - GadgetComboBoxAddEntry(comboBoxPlayer[i],TheGameText->fetch("GUI:Open"),GameSpyColor[GSCOLOR_PLAYER_NORMAL]); - GadgetComboBoxAddEntry(comboBoxPlayer[i],TheGameText->fetch("GUI:Closed"),GameSpyColor[GSCOLOR_PLAYER_NORMAL]); - GadgetComboBoxAddEntry(comboBoxPlayer[i],TheGameText->fetch("GUI:EasyAI"),GameSpyColor[GSCOLOR_PLAYER_NORMAL]); - GadgetComboBoxAddEntry(comboBoxPlayer[i],TheGameText->fetch("GUI:MediumAI"),GameSpyColor[GSCOLOR_PLAYER_NORMAL]); - GadgetComboBoxAddEntry(comboBoxPlayer[i],TheGameText->fetch("GUI:HardAI"),GameSpyColor[GSCOLOR_PLAYER_NORMAL]); - GadgetComboBoxSetSelectedPos(comboBoxPlayer[i],0); - } - - tmpString.format("GameSpyGameOptionsMenu.wnd:ComboBoxColor%d", i); - comboBoxColorID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - comboBoxColor[i] = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, comboBoxColorID[i] ); - DEBUG_ASSERTCRASH(comboBoxColor[i], ("Could not find the comboBoxColor[%d]",i )); - PopulateColorComboBox(i, comboBoxColor, theGameInfo); - GadgetComboBoxSetSelectedPos(comboBoxColor[i], 0); - - tmpString.format("GameSpyGameOptionsMenu.wnd:ComboBoxPlayerTemplate%d", i); - comboBoxPlayerTemplateID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - comboBoxPlayerTemplate[i] = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, comboBoxPlayerTemplateID[i] ); - DEBUG_ASSERTCRASH(comboBoxPlayerTemplate[i], ("Could not find the comboBoxPlayerTemplate[%d]",i )); - PopulatePlayerTemplateComboBox(i, comboBoxPlayerTemplate, theGameInfo, theGameInfo->getAllowObservers()); - - tmpString.format("GameSpyGameOptionsMenu.wnd:ComboBoxTeam%d", i); - comboBoxTeamID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - comboBoxTeam[i] = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, comboBoxTeamID[i] ); - DEBUG_ASSERTCRASH(comboBoxTeam[i], ("Could not find the comboBoxTeam[%d]",i )); - PopulateTeamComboBox(i, comboBoxTeam, theGameInfo); - - tmpString.format("GameSpyGameOptionsMenu.wnd:ButtonAccept%d", i); - buttonAcceptID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - buttonAccept[i] = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, buttonAcceptID[i] ); - DEBUG_ASSERTCRASH(buttonAccept[i], ("Could not find the buttonAccept[%d]",i )); - buttonAccept[i]->winSetTooltipFunc(gameAcceptTooltip); - - tmpString.format("GameSpyGameOptionsMenu.wnd:GenericPing%d", i); - genericPingWindowID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - genericPingWindow[i] = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, genericPingWindowID[i] ); - DEBUG_ASSERTCRASH(genericPingWindow[i], ("Could not find the genericPingWindow[%d]",i )); - genericPingWindow[i]->winSetTooltipFunc(pingTooltip); - -// tmpString.format("GameSpyGameOptionsMenu.wnd:ButtonStartPosition%d", i); -// buttonStartPositionID[i] = TheNameKeyGenerator->nameToKey( tmpString ); -// buttonStartPosition[i] = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, buttonStartPositionID[i] ); -// DEBUG_ASSERTCRASH(buttonStartPosition[i], ("Could not find the ButtonStartPosition[%d]",i )); - - tmpString.format("GameSpyGameOptionsMenu.wnd:ButtonMapStartPosition%d", i); - buttonMapStartPositionID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - buttonMapStartPosition[i] = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, buttonMapStartPositionID[i] ); - DEBUG_ASSERTCRASH(buttonMapStartPosition[i], ("Could not find the ButtonMapStartPosition[%d]",i )); - -// if (buttonStartPosition[i]) -// buttonStartPosition[i]->winHide(TRUE); - - if(i !=0 && buttonAccept[i]) - buttonAccept[i]->winHide(TRUE); - } - - if( buttonAccept[0] ) - buttonAccept[0]->winEnable(TRUE); - - if (buttonBack != NULL) - { - buttonBack->winEnable(TRUE); - } - //GadgetButtonSetEnabledColor(buttonAccept[0], GameSpyColor[GSCOLOR_ACCEPT_TRUE]); -} - -void DeinitWOLGameGadgets( void ) -{ - parentWOLGameSetup = NULL; - buttonEmote = NULL; - buttonSelectMap = NULL; - buttonStart = NULL; - buttonBack = NULL; - listboxGameSetupChat = NULL; - textEntryChat = NULL; - textEntryMapDisplay = NULL; - windowMap = NULL; -// GameWindow *staticTextTitle = NULL; - for (Int i = 0; i < MAX_SLOTS; i++) - { - comboBoxPlayer[i] = NULL; - staticTextPlayer[i] = NULL; - comboBoxColor[i] = NULL; - comboBoxPlayerTemplate[i] = NULL; - comboBoxTeam[i] = NULL; - buttonAccept[i] = NULL; -// buttonStartPosition[i] = NULL; - buttonMapStartPosition[i] = NULL; - genericPingWindow[i] = NULL; - } -} - -static Bool initDone = false; -UnsignedInt lastSlotlistTime = 0; -UnsignedInt enterTime = 0; -Bool initialAcceptEnable = FALSE; -//------------------------------------------------------------------------------------------------- -/** Initialize the Lan Game Options Menu */ -//------------------------------------------------------------------------------------------------- -void WOLGameSetupMenuInit( WindowLayout *layout, void *userData ) -{ - if (TheGameSpyGame && TheGameSpyGame->isGameInProgress()) - { - TheGameSpyGame->setGameInProgress(FALSE); - - // check if we were disconnected - Int disconReason; - if (TheGameSpyInfo->isDisconnectedAfterGameStart(&disconReason)) - { - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", disconReason); - UnicodeString title, body; - title = TheGameText->fetch( "GUI:GSErrorTitle" ); - body = TheGameText->fetch( disconMunkee ); - GameSpyCloseAllOverlays(); - GSMessageBoxOk( title, body ); - TheGameSpyInfo->reset(); - DEBUG_LOG(("WOLGameSetupMenuInit() - game was in progress, and we were disconnected, so pop immediate back to main menu\n")); - TheShell->popImmediate(); - return; - } - - // If we init while the game is in progress, we are really returning to the menu - // after the game. So, we pop the menu and go back to the lobby. Whee! - DEBUG_LOG(("WOLGameSetupMenuInit() - game was in progress, so pop immediate back to lobby\n")); - TheShell->popImmediate(); - if (TheGameSpyPeerMessageQueue && TheGameSpyPeerMessageQueue->isConnected()) - { - DEBUG_LOG(("We're still connected, so pushing back on the lobby\n")); - TheShell->push("Menus/WOLCustomLobby.wnd", TRUE); - } - return; - } - TheGameSpyInfo->setCurrentGroupRoom(0); - - if (TheNAT != NULL) { - delete TheNAT; - TheNAT = NULL; - } - - nextScreen = NULL; - buttonPushed = false; - isShuttingDown = false; - launchGameNext = FALSE; - - //initialize the gadgets - EnableSlotListUpdates(FALSE); - InitWOLGameGadgets(); - EnableSlotListUpdates(TRUE); - TheGameSpyInfo->registerTextWindow(listboxGameSetupChat); - - //The dialog needs to react differently depending on whether it's the host or not. - TheMapCache->updateCache(); - GameSpyStagingRoom *game = TheGameSpyInfo->getCurrentStagingRoom(); - GameSpyGameSlot *hostSlot = game->getGameSpySlot(0); - hostSlot->setAccept(); - if (TheGameSpyInfo->amIHost()) - { - OptionPreferences natPref; - CustomMatchPreferences customPref; - hostSlot->setColor( customPref.getPreferredColor() ); - hostSlot->setPlayerTemplate( customPref.getPreferredFaction() ); - hostSlot->setNATBehavior((FirewallHelperClass::FirewallBehaviorType)natPref.getFirewallBehavior()); - hostSlot->setPingString(TheGameSpyInfo->getPingString()); - game->setMap(customPref.getPreferredMap()); - - for (Int i=1; igetGameSpySlot(i); - slot->setState( SLOT_OPEN ); - } - - AsciiString lowerMap = customPref.getPreferredMap(); - lowerMap.toLower(); - std::map::iterator it = TheMapCache->find(lowerMap); - if (it != TheMapCache->end()) - { - hostSlot->setMapAvailability(TRUE); - game->setMapCRC( it->second.m_CRC ); - game->setMapSize( it->second.m_filesize ); - - game->adjustSlotsForMap(); // BGC- adjust the slots for the new map. - } - - - WOLDisplaySlotList(); - WOLDisplayGameOptions(); - } - else - { - OptionPreferences natPref; - CustomMatchPreferences customPref; - AsciiString options; - PeerRequest req; - UnicodeString uName = hostSlot->getName(); - AsciiString aName; - aName.translate(uName); - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "REQ/"; - req.nick = aName.str(); - options.format("PlayerTemplate=%d", customPref.getPreferredFaction()); - req.options = options.str(); - TheGameSpyPeerMessageQueue->addRequest(req); - options.format("Color=%d", customPref.getPreferredColor()); - req.options = options.str(); - TheGameSpyPeerMessageQueue->addRequest(req); - options.format("NAT=%d", natPref.getFirewallBehavior()); - req.options = options.str(); - TheGameSpyPeerMessageQueue->addRequest(req); - options.format("Ping=%s", TheGameSpyInfo->getPingString().str()); - req.options = options.str(); - TheGameSpyPeerMessageQueue->addRequest(req); - - game->setMapCRC( game->getMapCRC() ); // force a recheck - game->setMapSize( game->getMapSize() ); // of if we have the map - - for (Int i = 0; i < MAX_SLOTS; ++i) - { - //I'm a client, disable the controls I can't touch. - comboBoxPlayer[i]->winEnable(FALSE); - - comboBoxColor[i]->winEnable(FALSE); - comboBoxPlayerTemplate[i]->winEnable(FALSE); - comboBoxTeam[i]->winEnable(FALSE); -// buttonStartPosition[i]->winEnable(FALSE); - buttonMapStartPosition[i]->winEnable(FALSE); - - } - buttonStart->winSetText(TheGameText->fetch("GUI:Accept")); - buttonStart->winEnable( FALSE ); - buttonSelectMap->winEnable( FALSE ); - initialAcceptEnable = FALSE; - } - - // Show the Menu - layout->hide( FALSE ); - - // Make sure the text fields are clear - GadgetListBoxReset( listboxGameSetupChat ); - GadgetTextEntrySetText(textEntryChat, UnicodeString::TheEmptyString); - - initDone = true; - TheGameSpyInfo->setGameOptions(); - //TheShell->registerWithAnimateManager(parentWOLGameSetup, WIN_ANIMATION_SLIDE_TOP, TRUE); - WOLPositionStartSpots(); - - lastSlotlistTime = 0; - enterTime = timeGetTime(); - - // Set Keyboard to chat entry - TheWindowManager->winSetFocus( textEntryChat ); - raiseMessageBoxes = true; - TheTransitionHandler->setGroup("GameSpyGameOptionsMenuFade"); -}// void WOLGameSetupMenuInit( WindowLayout *layout, void *userData ) - -//------------------------------------------------------------------------------------------------- -/** This is called when a shutdown is complete for this menu */ -//------------------------------------------------------------------------------------------------- -static void shutdownComplete( WindowLayout *layout ) -{ - - isShuttingDown = false; - - // hide the layout - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout, (nextScreen != NULL) ); - - if (nextScreen != NULL) - { - if (!TheGameSpyPeerMessageQueue || !TheGameSpyPeerMessageQueue->isConnected()) - { - DEBUG_LOG(("GameSetup shutdownComplete() - skipping push because we're disconnected\n")); - } - else - { - TheShell->push(nextScreen); - } - } - - /* - if (launchGameNext) - { - TheGameSpyGame->launchGame(); - TheGameSpyInfo->leaveStagingRoom(); - } - */ - - nextScreen = NULL; - -} // end if - -//------------------------------------------------------------------------------------------------- -/** GameSpy Game Options menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLGameSetupMenuShutdown( WindowLayout *layout, void *userData ) -{ - TheGameSpyInfo->unregisterTextWindow(listboxGameSetupChat); - - if( WOLMapSelectLayout ) - { - WOLMapSelectLayout->destroyWindows(); - WOLMapSelectLayout->deleteInstance(); - WOLMapSelectLayout = NULL; - } - parentWOLGameSetup = NULL; - EnableSlotListUpdates(FALSE); - DeinitWOLGameGadgets(); - if (TheEstablishConnectionsMenu != NULL) - { - TheEstablishConnectionsMenu->endMenu(); - } - initDone = false; - - isShuttingDown = true; - - // if we are shutting down for an immediate pop, skip the animations - Bool popImmediate = *(Bool *)userData; - if( popImmediate ) - { - - shutdownComplete( layout ); - return; - - } //end if - - TheShell->reverseAnimatewindow(); - - RaiseGSMessageBox(); - TheTransitionHandler->reverse("GameSpyGameOptionsMenuFade"); -} // void WOLGameSetupMenuShutdown( WindowLayout *layout, void *userData ) - -static void fillPlayerInfo(const PeerResponse *resp, PlayerInfo *info) -{ - info->m_name = resp->nick.c_str(); - info->m_profileID = resp->player.profileID; - info->m_flags = resp->player.flags; - info->m_wins = resp->player.wins; - info->m_losses = resp->player.losses; - info->m_locale = resp->locale.c_str(); - info->m_rankPoints= resp->player.rankPoints; - info->m_side = resp->player.side; - info->m_preorder = resp->player.preorder; -} - -//------------------------------------------------------------------------------------------------- -/** Lan Game Options menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLGameSetupMenuUpdate( WindowLayout * layout, void *userData) -{ - // We'll only be successful if we've requested to - if(isShuttingDown && TheShell->isAnimFinished() && TheTransitionHandler->isFinished()) - { - shutdownComplete(layout); - return; - } - - if (raiseMessageBoxes) - { - RaiseGSMessageBox(); - raiseMessageBoxes = false; - } - - if (TheShell->isAnimFinished() && !buttonPushed && TheGameSpyPeerMessageQueue) - { - HandleBuddyResponses(); - HandlePersistentStorageResponses(); - - if (TheGameSpyGame && TheGameSpyGame->isGameInProgress()) - { - if (TheGameSpyInfo->isDisconnectedAfterGameStart(NULL)) - { - return; // already been disconnected, so don't worry. - } - - Int allowedMessages = TheGameSpyInfo->getMaxMessagesPerUpdate(); - Bool sawImportantMessage = FALSE; - PeerResponse resp; - while (allowedMessages-- && !sawImportantMessage && TheGameSpyPeerMessageQueue->getResponse( resp )) - { - switch (resp.peerResponseType) - { - case PeerResponse::PEERRESPONSE_DISCONNECT: - { - sawImportantMessage = TRUE; - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", resp.discon.reason); - - // check for scorescreen - NameKeyType listboxChatWindowScoreScreenID = NAMEKEY("ScoreScreen.wnd:ListboxChatWindowScoreScreen"); - GameWindow *listboxChatWindowScoreScreen = TheWindowManager->winGetWindowFromId( NULL, listboxChatWindowScoreScreenID ); - if (listboxChatWindowScoreScreen) - { - GadgetListBoxAddEntryText(listboxChatWindowScoreScreen, TheGameText->fetch(disconMunkee), - GameSpyColor[GSCOLOR_DEFAULT], -1); - } - else - { - // still ingame - TheInGameUI->message(disconMunkee); - } - TheGameSpyInfo->markAsDisconnectedAfterGameStart(resp.discon.reason); - } - } - } - - return; // if we're in game, all we care about is if we've been disconnected from the chat server - } - - Bool isHosting = TheGameSpyInfo->amIHost(); // only while in game setup screen - isHosting = isHosting || (TheGameSpyGame && TheGameSpyGame->isInGame() && TheGameSpyGame->amIHost()); // while in game - if (!isHosting && !lastSlotlistTime && timeGetTime() > enterTime + 10000) - { - // don't do this if we're disconnected - if (TheGameSpyPeerMessageQueue->isConnected()) - { - // haven't seen ourselves - buttonPushed = true; - DEBUG_LOG(("Haven't seen ourselves in slotlist\n")); - if (TheGameSpyGame) - TheGameSpyGame->reset(); - TheGameSpyInfo->leaveStagingRoom(); - //TheGameSpyInfo->joinBestGroupRoom(); - GSMessageBoxOk(TheGameText->fetch("GUI:HostLeftTitle"), TheGameText->fetch("GUI:HostLeft")); - nextScreen = "Menus/WOLCustomLobby.wnd"; - TheShell->pop(); - } - return; - } - - if (TheNAT != NULL) { - NATStateType NATState = TheNAT->update(); - if (NATState == NATSTATE_DONE) - { - //launchGameNext = TRUE; - //TheShell->pop(); - TheGameSpyGame->launchGame(); - if (TheGameSpyInfo) // this can be blown away by a disconnect on the map transfer screen - TheGameSpyInfo->leaveStagingRoom(); - return; - } - else if (NATState == NATSTATE_FAILED) - { - // Just back out. This cleans up some slot list problems - buttonPushed = true; - - // delete TheNAT, its no good for us anymore. - delete TheNAT; - TheNAT = NULL; - - TheGameSpyInfo->getCurrentStagingRoom()->reset(); - TheGameSpyInfo->leaveStagingRoom(); - //TheGameSpyInfo->joinBestGroupRoom(); - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:NATNegotiationFailed")); - nextScreen = "Menus/WOLCustomLobby.wnd"; - TheShell->pop(); - return; - } - } - - PeerResponse resp; - - Int allowedMessages = TheGameSpyInfo->getMaxMessagesPerUpdate(); - Bool sawImportantMessage = FALSE; - while (allowedMessages-- && !sawImportantMessage) - { - - if (!TheLobbyQueuedUTMs.empty()) - { - DEBUG_LOG(("Got response from queued lobby UTM list\n")); - resp = TheLobbyQueuedUTMs.front(); - TheLobbyQueuedUTMs.pop_front(); - } - else if (TheGameSpyPeerMessageQueue->getResponse( resp )) - { - DEBUG_LOG(("Got response from message queue\n")); - } - else - { - break; - } - - switch (resp.peerResponseType) - { - case PeerResponse::PEERRESPONSE_FAILEDTOHOST: - { - // oops - we've not heard from the qr server. bail. - TheGameSpyInfo->addText(TheGameText->fetch("GUI:GSFailedToHost"), GameSpyColor[GSCOLOR_DEFAULT], NULL); - } - break; - case PeerResponse::PEERRESPONSE_GAMESTART: - { - sawImportantMessage = TRUE; - GameSpyStagingRoom *myGame = TheGameSpyInfo->getCurrentStagingRoom(); - if (!myGame || !myGame->isInGame()) - break; - - if (!TheGameSpyGame) - break; - - SendStatsToOtherPlayers(TheGameSpyGame); - - // we've started, there's no going back - // i.e. disable the back button. - buttonBack->winEnable(FALSE); - GameWindow *buttonBuddy = TheWindowManager->winGetWindowFromId(NULL, NAMEKEY("GameSpyGameOptionsMenu.wnd:ButtonCommunicator")); - if (buttonBuddy) - buttonBuddy->winEnable(FALSE); - GameSpyCloseOverlay(GSOVERLAY_BUDDY); - - *TheGameSpyGame = *myGame; - TheGameSpyGame->startGame(0); - } - break; - case PeerResponse::PEERRESPONSE_PLAYERCHANGEDFLAGS: - { - PlayerInfo p; - fillPlayerInfo(&resp, &p); - TheGameSpyInfo->updatePlayerInfo(p); - WOLDisplaySlotList(); - } - break; - case PeerResponse::PEERRESPONSE_PLAYERINFO: - { - PlayerInfo p; - fillPlayerInfo(&resp, &p); - TheGameSpyInfo->updatePlayerInfo(p); - WOLDisplaySlotList(); - // send out new slotlist if I'm host - TheGameSpyInfo->setGameOptions(); - } - break; - case PeerResponse::PEERRESPONSE_PLAYERJOIN: - { - if (resp.player.roomType != StagingRoom) - { - break; - } - sawImportantMessage = TRUE; - PlayerInfo p; - fillPlayerInfo(&resp, &p); - TheGameSpyInfo->updatePlayerInfo(p); - - if (p.m_profileID) - { - if (TheGameSpyPSMessageQueue->findPlayerStatsByID(p.m_profileID).id == 0) - { - PSRequest req; - req.requestType = PSRequest::PSREQUEST_READPLAYERSTATS; - req.player.id = p.m_profileID; - TheGameSpyPSMessageQueue->addRequest(req); - } - } - - // check if we have room for the dude - GameInfo *game = TheGameSpyInfo->getCurrentStagingRoom(); - if (TheGameSpyInfo->amIHost() && game) - { - if (TheNAT) - { - // ditch him - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "KICK/"; - req.nick = p.m_name.str(); - req.options = "GameStarted"; - TheGameSpyPeerMessageQueue->addRequest(req); - } - else - { - // look for room for him - // See if there's room - // First get the number of players currently in the room. - Int numPlayers = 0; - for (Int player = 0; player < MAX_SLOTS; ++player) - { - if (game->getSlot(player)->isOccupied() && - game->getSlot(player)->getPlayerTemplate() != PLAYERTEMPLATE_OBSERVER) - { - ++numPlayers; - } - } - - // now get the number of starting spots on the map. - Int numStartingSpots = MAX_SLOTS; - const MapMetaData *md = TheMapCache->findMap(game->getMap()); - if (md != NULL) - { - numStartingSpots = md->m_numPlayers; - } - - Int openSlotIndex = -1; - for (Int i=0; igetConstSlot(i); - if (slot && slot->isOpen()) - { - openSlotIndex = i; - break; - } - } - - if (openSlotIndex >= 0) - { - // add him - GameSlot newSlot; - UnicodeString uName; - uName.translate(p.m_name); - newSlot.setState(SLOT_PLAYER, uName); - newSlot.setIP(ntohl(resp.player.IP)); - game->setSlot( openSlotIndex, newSlot ); - game->resetAccepted(); // BGC - need to unaccept everyone if someone joins the game. - } - else - { - // ditch him - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "KICK/"; - req.nick = p.m_name.str(); - req.options = "GameFull"; - TheGameSpyPeerMessageQueue->addRequest(req); - } - - // send out new slotlist if I'm host - TheGameSpyInfo->setGameOptions(); - } - } - WOLDisplaySlotList(); - } - break; - - case PeerResponse::PEERRESPONSE_PLAYERLEFT: - { - sawImportantMessage = TRUE; - PlayerInfo p; - fillPlayerInfo(&resp, &p); - TheGameSpyInfo->playerLeftGroupRoom(resp.nick.c_str()); - - if (TheGameSpyGame && TheGameSpyGame->isGameInProgress()) - { - break; - } - - if (TheNAT == NULL) // don't update slot list if we're trying to start a game - { - - GameInfo *game = TheGameSpyInfo->getCurrentStagingRoom(); - if (game && TheGameSpyInfo->amIHost()) - { - Int idx = game->getSlotNum(resp.nick.c_str()); - if (idx >= 0) - { - game->getSlot(idx)->setState(SLOT_OPEN); - game->resetAccepted(); // BGC - need to unaccept everyone if someone leaves the game. - } - } - - // send out new slotlist if I'm host - TheGameSpyInfo->setGameOptions(); - WOLDisplaySlotList(); - - if (game && !TheGameSpyInfo->amIHost()) - { - Int idx = game->getSlotNum(resp.nick.c_str()); - if (idx == 0) - { - // host left - buttonPushed = true; - TheGameSpyInfo->getCurrentStagingRoom()->reset(); - TheGameSpyInfo->leaveStagingRoom(); - //TheGameSpyInfo->joinBestGroupRoom(); - GSMessageBoxOk(TheGameText->fetch("GUI:HostLeftTitle"), TheGameText->fetch("GUI:HostLeft")); - nextScreen = "Menus/WOLCustomLobby.wnd"; - TheShell->pop(); - } - } - - } - } - break; - - case PeerResponse::PEERRESPONSE_MESSAGE: - { - TheGameSpyInfo->addChat(resp.nick.c_str(), resp.message.profileID, - UnicodeString(resp.text.c_str()), !resp.message.isPrivate, resp.message.isAction, listboxGameSetupChat); - } - break; - - case PeerResponse::PEERRESPONSE_DISCONNECT: - { - sawImportantMessage = TRUE; - UnicodeString title, body; - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", resp.discon.reason); - title = TheGameText->fetch( "GUI:GSErrorTitle" ); - body = TheGameText->fetch( disconMunkee ); - GameSpyCloseAllOverlays(); - GSMessageBoxOk( title, body ); - TheGameSpyInfo->reset(); - TheShell->pop(); - } - - case PeerResponse::PEERRESPONSE_ROOMUTM: - { - sawImportantMessage = TRUE; -#if defined(_DEBUG) || defined(_INTERNAL) - if (g_debugSlots) - { - DEBUG_LOG(("About to process a room UTM. Command is '%s', command options is '%s'\n", - resp.command.c_str(), resp.commandOptions.c_str())); - } -#endif - if (!strcmp(resp.command.c_str(), "SL")) - { - // slotlist - GameSpyStagingRoom *game = TheGameSpyInfo->getCurrentStagingRoom(); - Bool isValidSlotList = game && game->getSlot(0) && game->getSlot(0)->isPlayer( resp.nick.c_str() ) && !TheGameSpyInfo->amIHost(); - if (!isValidSlotList) - { - SLOTLIST_DEBUG_LOG(("Not a valid slotlist\n")); - if (!game) - { - SLOTLIST_DEBUG_LOG(("No game!\n")); - } - else - { - if (!game->getSlot(0)) - { - SLOTLIST_DEBUG_LOG(("No slot 0!\n")); - } - else - { - if (TheGameSpyInfo->amIHost()) - { - SLOTLIST_DEBUG_LOG(("I'm the host!\n")); - } - else - { - SLOTLIST_DEBUG_LOG(("Not from the host! isHuman:%d, name:'%ls', sender:'%s'\n", - game->getSlot(0)->isHuman(), game->getSlot(0)->getName().str(), - resp.nick.c_str())); - } - } - } - } - else // isValidSlotList - { - Int oldLocalSlotNum = (game->isInGame()) ? game->getLocalSlotNum() : -1; - Bool wasInGame = oldLocalSlotNum >= 0; - AsciiString oldMap = game->getMap(); - UnsignedInt oldMapCRC, newMapCRC; - oldMapCRC = game->getMapCRC(); - - AsciiString options = resp.commandOptions.c_str(); - options.trim(); - UnsignedShort ports[MAX_SLOTS]; - UnsignedInt ips[MAX_SLOTS]; - Int i; - for (i=0; igetConstSlot(i)) - { - ips[i] = game->getConstSlot(i)->getIP(); - ports[i] = game->getConstSlot(i)->getPort(); - } - else - { - ips[i] = 0; - ports[i] = 0; - } - } - Bool optionsOK = ParseAsciiStringToGameInfo(game, options.str()); - if (TheNAT) - { - for (i=0; igetSlot(i)) - { -#ifdef DEBUG_LOGGING - UnsignedShort newPort = game->getConstSlot(i)->getPort(); - UnsignedInt newIP = game->getConstSlot(i)->getIP(); - DEBUG_ASSERTLOG(newIP == ips[i], ("IP was different for player %d (%X --> %X)\n", - i, ips[i], newIP)); - DEBUG_ASSERTLOG(newPort == ports[i], ("Port was different for player %d (%d --> %d)\n", - i, ports[i], newPort)); -#endif - game->getSlot(i)->setPort(ports[i]); - game->getSlot(i)->setIP(ips[i]); - } - } - } - Int newLocalSlotNum = (game->isInGame()) ? game->getLocalSlotNum() : -1; - Bool isInGame = newLocalSlotNum >= 0; - if (!optionsOK) - { - SLOTLIST_DEBUG_LOG(("Options are bad! bailing!\n")); - break; - } - else - { - SLOTLIST_DEBUG_LOG(("Options are good, local slot is %d\n", newLocalSlotNum)); - if (!isInGame) - { - SLOTLIST_DEBUG_LOG(("Not in game; players are:\n")); - for (Int i=0; igetGameSpySlot(i); - if (slot && slot->isHuman()) - { - UnicodeString munkee; - munkee.format(L"\t%d: %ls", i, slot->getName().str()); - SLOTLIST_DEBUG_LOG(("%ls\n", munkee.str())); - } - } - } - } - WOLDisplaySlotList(); - - // if I changed map availability, send it across - newMapCRC = game->getMapCRC(); - if (isInGame) - { - lastSlotlistTime = timeGetTime(); - if ( (oldMapCRC ^ newMapCRC) || (!wasInGame && isInGame) ) - { - // it changed. send it - UnicodeString hostName = TheGameSpyInfo->getCurrentStagingRoom()->getSlot(0)->getName(); - AsciiString asciiName; - asciiName.translate(hostName); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "MAP"; - req.nick = asciiName.str(); - req.options = (game->getSlot(newLocalSlotNum)->hasMap())?"1":"0"; - TheGameSpyPeerMessageQueue->addRequest(req); - if (!game->getSlot(newLocalSlotNum)->hasMap()) - { - UnicodeString text; - UnicodeString mapDisplayName; - const MapMetaData *mapData = TheMapCache->findMap( game->getMap() ); - Bool willTransfer = TRUE; - if (mapData) - { - mapDisplayName.format(L"%ls", mapData->m_displayName.str()); - willTransfer = !mapData->m_isOfficial; - } - else - { - mapDisplayName.format(L"%hs", TheGameState->getMapLeafName(game->getMap()).str()); - willTransfer = WouldMapTransfer(game->getMap()); - } - if (willTransfer) - text.format(TheGameText->fetch("GUI:LocalPlayerNoMapWillTransfer"), mapDisplayName.str()); - else - text.format(TheGameText->fetch("GUI:LocalPlayerNoMap"), mapDisplayName.str()); - TheGameSpyInfo->addText(text, GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - } - } - if (!initialAcceptEnable) - { - buttonStart->winEnable( TRUE ); - initialAcceptEnable = TRUE; - } - } - else - { - if (lastSlotlistTime) - { - // can't see ourselves - buttonPushed = true; - DEBUG_LOG(("Can't see ourselves in slotlist %s\n", options.str())); - TheGameSpyInfo->getCurrentStagingRoom()->reset(); - TheGameSpyInfo->leaveStagingRoom(); - //TheGameSpyInfo->joinBestGroupRoom(); - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSKicked")); - nextScreen = "Menus/WOLCustomLobby.wnd"; - TheShell->pop(); - } - } - } - } - else if (!strcmp(resp.command.c_str(), "HWS")) - { - // host wants to start - GameInfo *game = TheGameSpyInfo->getCurrentStagingRoom(); - if (game && game->isInGame() && game->getSlot(0) && game->getSlot(0)->isPlayer( resp.nick.c_str() )) - { - Int slotNum = game->getLocalSlotNum(); - GameSlot *slot = game->getSlot(slotNum); - if (slot && (slot->isAccepted() == false)) - { - TheGameSpyInfo->addText(TheGameText->fetch("GUI:HostWantsToStart"), GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - } - } - } - else if (!stricmp(resp.command.c_str(), "NAT")) - { - if (TheNAT != NULL) { - TheNAT->processGlobalMessage(-1, resp.commandOptions.c_str()); - } - } - else if (!stricmp(resp.command.c_str(), "Pings")) - { - if (!TheGameSpyInfo->amIHost()) - { - AsciiString pings = resp.commandOptions.c_str(); - AsciiString token; - for (Int i=0; igetCurrentStagingRoom()->getGameSpySlot(i); - if (pings.nextToken(&token, ",")) - { - token.trim(); - slot->setPingString(token); - } - else - { - slot->setPingString(""); - } - } - } - } - } - break; - - case PeerResponse::PEERRESPONSE_PLAYERUTM: - { - sawImportantMessage = TRUE; - if (!strcmp(resp.command.c_str(), "STATS")) - { - PSPlayerStats stats = TheGameSpyPSMessageQueue->parsePlayerKVPairs(resp.commandOptions.c_str()); - if (stats.id && (TheGameSpyPSMessageQueue->findPlayerStatsByID(stats.id).id == 0)) - TheGameSpyPSMessageQueue->trackPlayerStats(stats); - break; - } - GameSpyStagingRoom *game = TheGameSpyInfo->getCurrentStagingRoom(); - if (game) - { - Int slotNum = game->getSlotNum(resp.nick.c_str()); - if ((slotNum >= 0) && (slotNum < MAX_SLOTS) && (!stricmp(resp.command.c_str(), "NAT"))) { - // this is a command for NAT negotiations, pass if off to TheNAT - if (TheNAT != NULL) { - TheNAT->processGlobalMessage(slotNum, resp.commandOptions.c_str()); - } - } - if (slotNum == 0 && !TheGameSpyInfo->amIHost()) - { - if (!strcmp(resp.command.c_str(), "KICK")) - { - // oops - we've been kicked. bail. - buttonPushed = true; - TheGameSpyInfo->getCurrentStagingRoom()->reset(); - TheGameSpyInfo->leaveStagingRoom(); - //TheGameSpyInfo->joinBestGroupRoom(); - UnicodeString message = TheGameText->fetch("GUI:GSKicked"); - AsciiString commandMessage = resp.commandOptions.c_str(); - commandMessage.trim(); - DEBUG_LOG(("We were kicked: reason was '%s'\n", resp.commandOptions.c_str())); - if (commandMessage == "GameStarted") - { - message = TheGameText->fetch("GUI:GSKickedGameStarted"); - } - else if (commandMessage == "GameFull") - { - message = TheGameText->fetch("GUI:GSKickedGameFull"); - } - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), message); - nextScreen = "Menus/WOLCustomLobby.wnd"; - TheShell->pop(); - } - } - else if (slotNum > 0 && TheGameSpyInfo->amIHost()) - { - if (!strcmp(resp.command.c_str(), "accept")) - { - game->getSlot(slotNum)->setAccept(); - TheGameSpyInfo->setGameOptions(); - WOLDisplaySlotList(); - } - else if (!strcmp(resp.command.c_str(), "MAP")) - { - Bool hasMap = atoi(resp.commandOptions.c_str()); - game->getSlot(slotNum)->setMapAvailability(hasMap); - if (!hasMap) - { - // tell the host the user doesn't have the map - UnicodeString mapDisplayName; - const MapMetaData *mapData = TheMapCache->findMap( game->getMap() ); - Bool willTransfer = TRUE; - if (mapData) - { - mapDisplayName.format(L"%ls", mapData->m_displayName.str()); - willTransfer = !mapData->m_isOfficial; - } - else - { - mapDisplayName.format(L"%hs", game->getMap().str()); - willTransfer = WouldMapTransfer(game->getMap()); - } - UnicodeString text; - if (willTransfer) - text.format(TheGameText->fetch("GUI:PlayerNoMapWillTransfer"), game->getSlot(slotNum)->getName().str(), mapDisplayName.str()); - else - text.format(TheGameText->fetch("GUI:PlayerNoMap"), game->getSlot(slotNum)->getName().str(), mapDisplayName.str()); - TheGameSpyInfo->addText(text, GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - } - WOLDisplaySlotList(); - } - else if (!strcmp(resp.command.c_str(), "REQ")) - { - AsciiString options = resp.commandOptions.c_str(); - options.trim(); - - Bool change = false; - Bool shouldUnaccept = false; - AsciiString key; - options.nextToken(&key, "="); - Int val = atoi(options.str()+1); - UnsignedInt uVal = atoi(options.str()+1); - DEBUG_LOG(("GameOpt request: key=%s, val=%s from player %d\n", key.str(), options.str()+1, slotNum)); - - GameSpyGameSlot *slot = game->getGameSpySlot(slotNum); - if (!slot) - break; - - if (key == "Color") - { - if (val >= -1 && val < TheMultiplayerSettings->getNumColors() && val != slot->getColor() && slot->getPlayerTemplate() != PLAYERTEMPLATE_OBSERVER) - { - Bool colorAvailable = TRUE; - if(val != -1 ) - { - for(Int i=0; i getSlot(i); - if(val == checkSlot->getColor() && slot != checkSlot) - { - colorAvailable = FALSE; - break; - } - } - } - if(colorAvailable) - slot->setColor(val); - change = true; - } - else - { - DEBUG_LOG(("Rejecting invalid color %d\n", val)); - } - } - else if (key == "PlayerTemplate") - { - if (val >= PLAYERTEMPLATE_MIN && val < ThePlayerTemplateStore->getPlayerTemplateCount() && val != slot->getPlayerTemplate()) - { - slot->setPlayerTemplate(val); - if (val == PLAYERTEMPLATE_OBSERVER) - { - slot->setColor(-1); - slot->setStartPos(-1); - slot->setTeamNumber(-1); - } - change = true; - shouldUnaccept = true; - } - else - { - DEBUG_LOG(("Rejecting invalid PlayerTemplate %d\n", val)); - } - } - else if (key == "StartPos") - { - if (val >= -1 && val < MAX_SLOTS && val != slot->getStartPos() && slot->getPlayerTemplate() != PLAYERTEMPLATE_OBSERVER) - { - Bool startPosAvailable = TRUE; - if(val != -1) - { - for(Int i=0; i getSlot(i); - if(val == checkSlot->getStartPos() && slot != checkSlot) - { - startPosAvailable = FALSE; - break; - } - } - } - if(startPosAvailable) - slot->setStartPos(val); - change = true; - shouldUnaccept = true; - } - else - { - DEBUG_LOG(("Rejecting invalid startPos %d\n", val)); - } - } - else if (key == "Team") - { - if (val >= -1 && val < MAX_SLOTS/2 && val != slot->getTeamNumber() && slot->getPlayerTemplate() != PLAYERTEMPLATE_OBSERVER) - { - slot->setTeamNumber(val); - change = true; - shouldUnaccept = true; - } - else - { - DEBUG_LOG(("Rejecting invalid team %d\n", val)); - } - } - else if (key == "IP") - { - if (uVal != slot->getIP()) - { - DEBUG_LOG(("setting IP of player %ls from 0x%08x to be 0x%08x", slot->getName().str(), slot->getIP(), uVal)); - slot->setIP(uVal); - change = true; - shouldUnaccept = true; - } - else - { - DEBUG_LOG(("Rejecting invalid IP %d\n", uVal)); - } - } - else if (key == "NAT") - { - if ((val >= FirewallHelperClass::FIREWALL_MIN) && - (val <= FirewallHelperClass::FIREWALL_MAX)) - { - slot->setNATBehavior((FirewallHelperClass::FirewallBehaviorType)val); - DEBUG_LOG(("Setting NAT behavior to %d for player %d\n", val, slotNum)); - change = true; - } - else - { - DEBUG_LOG(("Rejecting invalid NAT behavior %d from player %d\n", val, slotNum)); - } - } - else if (key == "Ping") - { - slot->setPingString(options.str()+1); - TheGameSpyInfo->setGameOptions(); - DEBUG_LOG(("Setting ping string to %s for player %d\n", options.str()+1, slotNum)); - } - - if (change) - { - if (shouldUnaccept) - game->resetAccepted(); - - TheGameSpyInfo->setGameOptions(); - - WOLDisplaySlotList(); - DEBUG_LOG(("Slot value is color=%d, PlayerTemplate=%d, startPos=%d, team=%d, IP=0x%8.8X\n", - slot->getColor(), slot->getPlayerTemplate(), slot->getStartPos(), slot->getTeamNumber(), slot->getIP())); - DEBUG_LOG(("Slot list updated to %s\n", GameInfoToAsciiString(game).str())); - } - } - } - } - } - break; - - } - } - - - } -}// void WOLGameSetupMenuUpdate( WindowLayout * layout, void *userData) - -//------------------------------------------------------------------------------------------------- -/** Lan Game Options menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLGameSetupMenuInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - /* - switch( msg ) - { - - //------------------------------------------------------------------------------------------------- - case GWM_RIGHT_UP: - { - if (buttonPushed) - break; - - GameWindow *control = (GameWindow *)mData1; - NameKeyType controlID = (NameKeyType)control->winGetWindowId(); - DEBUG_LOG(("GWM_RIGHT_UP for control %d(%s)\n", controlID, TheNameKeyGenerator->keyToName(controlID).str())); - break; - } - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - if (buttonPushed) - break; - - switch( key ) - { - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonBack, buttonBackID ); - } // end if - // don't let key fall through anywhere else - return MSG_HANDLED; - } // end escape - } // end switch( key ) - } // end char - } // end switch( msg ) - */ - return MSG_IGNORED; -}//WindowMsgHandledType WOLGameSetupMenuInput( GameWindow *window, UnsignedInt msg, - - -// Slash commands ------------------------------------------------------------------------- -//extern "C" { -//int getQR2HostingStatus(void); -//} -extern int isThreadHosting; - -Bool handleGameSetupSlashCommands(UnicodeString uText) -{ - AsciiString message; - message.translate(uText); - - if (message.getCharAt(0) != '/') - { - return FALSE; // not a slash command - } - - AsciiString remainder = message.str() + 1; - AsciiString token; - remainder.nextToken(&token); - token.toLower(); - - if (token == "host") - { - UnicodeString s; - s.format(L"Hosting qr2:%d thread:%d", 0, isThreadHosting); - TheGameSpyInfo->addText(s, GameSpyColor[GSCOLOR_DEFAULT], NULL); - return TRUE; // was a slash command - } - else if (token == "me" && uText.getLength()>4) - { - TheGameSpyInfo->sendChat(UnicodeString(uText.str()+4), TRUE, NULL); - return TRUE; // was a slash command - } -#if defined(_DEBUG) || defined(_INTERNAL) - else if (token == "slots") - { - g_debugSlots = !g_debugSlots; - TheGameSpyInfo->addText(UnicodeString(L"Toggled SlotList debug"), GameSpyColor[GSCOLOR_DEFAULT], NULL); - return TRUE; // was a slash command - } - else if (token == "discon") - { - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_LOGOUT; - TheGameSpyPeerMessageQueue->addRequest( req ); - return TRUE; - } -#endif // defined(_DEBUG) || defined(_INTERNAL) - - return FALSE; // not a slash command -} - -static Int getNextSelectablePlayer(Int start) -{ - GameSpyStagingRoom *game = TheGameSpyInfo->getCurrentStagingRoom(); - if (!game->amIHost()) - return -1; - for (Int j=start; jgetGameSpySlot(j); - if (slot && slot->getStartPos() == -1 && - ( (j==game->getLocalSlotNum() && game->getConstSlot(j)->getPlayerTemplate()!=PLAYERTEMPLATE_OBSERVER) - || slot->isAI())) - { - return j; - } - } - return -1; -} - -static Int getFirstSelectablePlayer(const GameInfo *game) -{ - const GameSlot *slot = game->getConstSlot(game->getLocalSlotNum()); - if (!game->amIHost() || slot && slot->getPlayerTemplate() != PLAYERTEMPLATE_OBSERVER) - return game->getLocalSlotNum(); - - for (Int i=0; igetConstSlot(i); - if (slot && slot->isAI()) - return i; - } - - return game->getLocalSlotNum(); -} - -//------------------------------------------------------------------------------------------------- -/** WOL Game Options menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLGameSetupMenuSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - static buttonCommunicatorID = NAMEKEY_INVALID; - switch( msg ) - { - //------------------------------------------------------------------------------------------------- - case GWM_CREATE: - { - buttonCommunicatorID = NAMEKEY("GameSpyGameOptionsMenu.wnd:ButtonCommunicator"); - break; - } // case GWM_DESTROY: - //------------------------------------------------------------------------------------------------- - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - //------------------------------------------------------------------------------------------------- - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - //------------------------------------------------------------------------------------------------- - case GCM_SELECTED: - { - if (!initDone) - break; - if (buttonPushed) - break; - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - GameSpyStagingRoom *myGame = TheGameSpyInfo->getCurrentStagingRoom(); - for (Int i = 0; i < MAX_SLOTS; i++) - { - if (controlID == comboBoxColorID[i]) - { - handleColorSelection(i); - } - else if (controlID == comboBoxPlayerTemplateID[i]) - { - handlePlayerTemplateSelection(i); - } - else if (controlID == comboBoxTeamID[i]) - { - handleTeamSelection(i); - } - else if( controlID == comboBoxPlayerID[i] && TheGameSpyInfo->amIHost() ) - { - // We don't have anything that'll happen if we click on ourselves - if(i == myGame->getLocalSlotNum()) - break; - // Get - Int pos = -1; - GadgetComboBoxGetSelectedPos(comboBoxPlayer[i], &pos); - if( pos != SLOT_PLAYER && pos >= 0) - { - if( myGame->getSlot(i)->getState() == SLOT_PLAYER ) - { - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - AsciiString aName; - aName.translate(myGame->getSlot(i)->getName()); - req.nick = aName.str(); - req.id = "KICK/"; - req.options = "true"; - TheGameSpyPeerMessageQueue->addRequest(req); - - UnicodeString name = myGame->getSlot(i)->getName(); - myGame->getSlot(i)->setState(SlotState(pos)); - myGame->resetAccepted(); - TheGameSpyInfo->setGameOptions(); - WOLDisplaySlotList(); - //TheLAN->OnPlayerLeave(name); - } - else if( myGame->getSlot(i)->getState() != pos ) - { - Bool wasAI = (myGame->getSlot(i)->isAI()); - myGame->getSlot(i)->setState(SlotState(pos)); - Bool isAI = (myGame->getSlot(i)->isAI()); - myGame->resetAccepted(); - if (wasAI ^ isAI) - PopulatePlayerTemplateComboBox(i, comboBoxPlayerTemplate, myGame, wasAI && myGame->getAllowObservers()); - TheGameSpyInfo->setGameOptions(); - WOLDisplaySlotList(); - } - } - break; - } - } - }// case GCM_SELECTED: - //------------------------------------------------------------------------------------------------- - case GBM_SELECTED: - { - if (buttonPushed) - break; - - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - static buttonCommunicatorID = NAMEKEY("GameSpyGameOptionsMenu.wnd:ButtonCommunicator"); - - if ( controlID == buttonBackID ) - { - savePlayerInfo(); - if( WOLMapSelectLayout ) - { - WOLMapSelectLayout->destroyWindows(); - WOLMapSelectLayout->deleteInstance(); - WOLMapSelectLayout = NULL; - } - - TheGameSpyInfo->getCurrentStagingRoom()->reset(); - //peerLeaveRoom(TheGameSpyChat->getPeer(), StagingRoom, NULL); - TheGameSpyInfo->leaveStagingRoom(); - buttonPushed = true; - nextScreen = "Menus/WOLCustomLobby.wnd"; - TheShell->pop(); - - } //if ( controlID == buttonBack ) - else if ( controlID == buttonCommunicatorID ) - { - GameSpyToggleOverlay( GSOVERLAY_BUDDY ); - - } - else if ( controlID == buttonEmoteID ) - { - // read the user's input - txtInput.set(GadgetTextEntryGetText( textEntryChat )); - // Clear the text entry line - GadgetTextEntrySetText(textEntryChat, UnicodeString::TheEmptyString); - // Clean up the text (remove leading/trailing chars, etc) - txtInput.trim(); - // Echo the user's input to the chat window - if (!txtInput.isEmpty()) - TheGameSpyInfo->sendChat(txtInput, FALSE, NULL); // 'emote' button is now carriage-return - } //if ( controlID == buttonEmote ) - else if ( controlID == buttonSelectMapID ) - { - WOLMapSelectLayout = TheWindowManager->winCreateLayout( "Menus/WOLMapSelectMenu.wnd" ); - WOLMapSelectLayout->runInit(); - WOLMapSelectLayout->hide( FALSE ); - WOLMapSelectLayout->bringForward(); - } - else if ( controlID == buttonStartID ) - { - savePlayerInfo(); - if (TheGameSpyInfo->amIHost()) - { - StartPressed(); - } - else - { - //I'm the Client... send an accept message to the host. - GameSlot *localSlot = TheGameSpyInfo->getCurrentStagingRoom()->getSlot(TheGameSpyInfo->getCurrentStagingRoom()->getLocalSlotNum()); - if (localSlot) - { - localSlot->setAccept(); - } - UnicodeString hostName = TheGameSpyInfo->getCurrentStagingRoom()->getSlot(0)->getName(); - AsciiString asciiName; - asciiName.translate(hostName); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "accept"; - req.nick = asciiName.str(); - req.options = "true"; - TheGameSpyPeerMessageQueue->addRequest(req); - //peerSetReady( PEER, PEERTrue ); - WOLDisplaySlotList(); - } - } - else - { - for (Int i = 0; i < MAX_SLOTS; i++) - { - if (controlID == buttonMapStartPositionID[i]) - { - GameSpyStagingRoom *game = TheGameSpyInfo->getCurrentStagingRoom(); - Int playerIdxInPos = -1; - for (Int j=0; jgetGameSpySlot(j); - if (slot && slot->getStartPos() == i) - { - playerIdxInPos = j; - break; - } - } - if (playerIdxInPos >= 0) - { - GameSpyGameSlot *slot = game->getGameSpySlot(playerIdxInPos); - if (playerIdxInPos == game->getLocalSlotNum() || (game->amIHost() && slot && slot->isAI())) - { - // it's one of my type. Try to change it. - Int nextPlayer = getNextSelectablePlayer(playerIdxInPos+1); - handleStartPositionSelection(playerIdxInPos, -1); - if (nextPlayer >= 0) - { - handleStartPositionSelection(nextPlayer, i); - } - } - } - else - { - // nobody in the slot - put us in - Int nextPlayer = getNextSelectablePlayer(0); - if (nextPlayer < 0) - nextPlayer = getFirstSelectablePlayer(game); - handleStartPositionSelection(nextPlayer, i); - } - } - } - } - - - break; - }// case GBM_SELECTED: - //------------------------------------------------------------------------------------------------- - case GBM_SELECTED_RIGHT: - { - if (buttonPushed) - break; - - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - for (Int i = 0; i < MAX_SLOTS; i++) - { - if (controlID == buttonMapStartPositionID[i]) - { - GameSpyStagingRoom *game = TheGameSpyInfo->getCurrentStagingRoom(); - Int playerIdxInPos = -1; - for (Int j=0; jgetGameSpySlot(j); - if (slot && slot->getStartPos() == i) - { - playerIdxInPos = j; - break; - } - } - if (playerIdxInPos >= 0) - { - GameSpyGameSlot *slot = game->getGameSpySlot(playerIdxInPos); - if (playerIdxInPos == game->getLocalSlotNum() || (game->amIHost() && slot && slot->isAI())) - { - // it's one of my type. Remove it. - handleStartPositionSelection(playerIdxInPos, -1); - } - } - } - } - break; - } - - //------------------------------------------------------------------------------------------------- - case GEM_EDIT_DONE: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - // Take the user's input and echo it into the chat window as well as - // send it to the other clients on the lan - if ( controlID == textEntryChatID ) - { - - // read the user's input - txtInput.set(GadgetTextEntryGetText( textEntryChat )); - // Clear the text entry line - GadgetTextEntrySetText(textEntryChat, UnicodeString::TheEmptyString); - // Clean up the text (remove leading/trailing chars, etc) - txtInput.trim(); - // Echo the user's input to the chat window - if (!txtInput.isEmpty()) - { - if (!handleGameSetupSlashCommands(txtInput)) - { - TheGameSpyInfo->sendChat(txtInput, false, NULL); - } - } - - }// if ( controlID == textEntryChatID ) - break; - } - //------------------------------------------------------------------------------------------------- - default: - return MSG_IGNORED; - }//Switch - return MSG_HANDLED; -}//WindowMsgHandledType WOLGameSetupMenuSystem( GameWindow *window, UnsignedInt msg, - - diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLadderScreen.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLadderScreen.cpp deleted file mode 100644 index ae044416076..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLadderScreen.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ReplayMenu.cpp ///////////////////////////////////////////////////////////////////// -// Author: Chris The masta Huybregts, December 2001 -// Description: Replay Menus -/////////////////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/MessageBox.h" - -// window ids ------------------------------------------------------------------------------------- -static NameKeyType parentWindowID = NAMEKEY_INVALID; -static NameKeyType buttonBackID = NAMEKEY_INVALID; -static NameKeyType windowLadderID = NAMEKEY_INVALID; - - -// window pointers -------------------------------------------------------------------------------- -static GameWindow *parentWindow = NULL; -static GameWindow *buttonBack = NULL; -static GameWindow *windowLadder = NULL; - - -//------------------------------------------------------------------------------------------------- -/** Initialize the single player menu */ -//------------------------------------------------------------------------------------------------- -void WOLLadderScreenInit( WindowLayout *layout, void *userData ) -{ - TheShell->showShellMap(TRUE); - - // get ids for our children controls - parentWindowID = TheNameKeyGenerator->nameToKey( AsciiString("WOLLadderScreen.wnd:LadderParent") ); - buttonBackID = TheNameKeyGenerator->nameToKey( AsciiString("WOLLadderScreen.wnd:ButtonBack") ); - windowLadderID = TheNameKeyGenerator->nameToKey( AsciiString("WOLLadderScreen.wnd:WindowLadder") ); - - parentWindow = TheWindowManager->winGetWindowFromId( NULL, parentWindowID ); - buttonBack = TheWindowManager->winGetWindowFromId( parentWindow, buttonBackID ); - windowLadder = TheWindowManager->winGetWindowFromId( parentWindow, windowLadderID ); - - //Load the listbox shiznit -// PopulateReplayFileListbox(listboxReplayFiles); - - // show menu - layout->hide( FALSE ); - - // set keyboard focus to main parent - TheWindowManager->winSetFocus( parentWindow ); - -} // end ReplayMenuInit - -//------------------------------------------------------------------------------------------------- -/** single player menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLLadderScreenShutdown( WindowLayout *layout, void *userData ) -{ - - // hide menu - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout ); - -} // end ReplayMenuShutdown - -//------------------------------------------------------------------------------------------------- -/** single player menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLLadderScreenUpdate( WindowLayout *layout, void *userData ) -{ - -} // end ReplayMenuUpdate - -//------------------------------------------------------------------------------------------------- -/** Replay menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLLadderScreenInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonBack, buttonBackID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; - -} // end ReplayMenuInput - -//------------------------------------------------------------------------------------------------- -/** single player menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLLadderScreenSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CREATE: - { - - - break; - - } // end create - - //--------------------------------------------------------------------------------------------- - case GWM_DESTROY: - { - - break; - - } // end case - - // -------------------------------------------------------------------------------------------- - case GWM_INPUT_FOCUS: - { - - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - - } // end input - //--------------------------------------------------------------------------------------------- - case GBM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if( controlID == buttonBackID ) - { - - // thou art directed to return to thy known solar system immediately! - TheShell->pop(); - - } // end else if - - break; - - } // end selected - - default: - return MSG_IGNORED; - } // end switch - - return MSG_HANDLED; -} // end ReplayMenuSystem - diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLobbyMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLobbyMenu.cpp deleted file mode 100644 index 63d64aa6780..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLobbyMenu.cpp +++ /dev/null @@ -1,1857 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLLobbyMenu.cpp -// Author: Chris Huybregts, November 2001 -// Description: WOL Lobby Menu -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "Common/GameState.h" -#include "Common/MiniLog.h" -#include "Common/MultiplayerSettings.h" -#include "Common/PlayerTemplate.h" -#include "Common/CustomMatchPreferences.h" -#include "Common/Version.h" -#include "GameClient/AnimateWindowManager.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/GameClient.h" -#include "GameClient/Shell.h" -#include "GameClient/ShellHooks.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetComboBox.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetSlider.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/GameText.h" -#include "GameClient/MessageBox.h" -#include "GameClient/Mouse.h" -#include "GameClient/Display.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameClient/GameWindowTransitions.h" - -#include "GameLogic/GameLogic.h" - -#include "GameClient/LanguageFilter.h" -#include "GameNetwork/GameSpy/BuddyDefs.h" -#include "GameNetwork/GameSpy/GSConfig.h" -#include "GameNetwork/GameSpy/LadderDefs.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PersistentStorageDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpy/LobbyUtils.h" -#include "GameNetwork/RankPointValue.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif -void refreshGameList( Bool forceRefresh = FALSE ); -void refreshPlayerList( Bool forceRefresh = FALSE ); - -#ifdef DEBUG_LOGGING -#define PERF_TEST -static LogClass s_perfLog("Perf.txt"); -#define PERF_LOG(x) s_perfLog.log x -#else // DEBUG_LOGGING -#define PERF_LOG(x) {} -#endif // DEBUG_LOGGING - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -static Bool isShuttingDown = false; -static Bool buttonPushed = false; -static char *nextScreen = NULL; -static Bool raiseMessageBoxes = false; -static time_t gameListRefreshTime = 0; -static const time_t gameListRefreshInterval = 10000; -static time_t playerListRefreshTime = 0; -static const time_t playerListRefreshInterval = 5000; - -void setUnignoreText( WindowLayout *layout, AsciiString nick, GPProfile id); -static void doSliderTrack(GameWindow *control, Int val); -Bool DontShowMainMenu = FALSE; -enum { COLUMN_PLAYERNAME = 2 }; - -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentWOLLobbyID = NAMEKEY_INVALID; -static NameKeyType buttonBackID = NAMEKEY_INVALID; -static NameKeyType buttonHostID = NAMEKEY_INVALID; -static NameKeyType buttonRefreshID = NAMEKEY_INVALID; -static NameKeyType buttonJoinID = NAMEKEY_INVALID; -static NameKeyType buttonBuddyID = NAMEKEY_INVALID; -static NameKeyType buttonEmoteID = NAMEKEY_INVALID; -static NameKeyType textEntryChatID = NAMEKEY_INVALID; -static NameKeyType listboxLobbyPlayersID = NAMEKEY_INVALID; -static NameKeyType listboxLobbyChatID = NAMEKEY_INVALID; -static NameKeyType comboLobbyGroupRoomsID = NAMEKEY_INVALID; -//static NameKeyType // sliderChatAdjustID = NAMEKEY_INVALID; - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentWOLLobby = NULL; -static GameWindow *buttonBack = NULL; -static GameWindow *buttonHost = NULL; -static GameWindow *buttonRefresh = NULL; -static GameWindow *buttonJoin = NULL; -static GameWindow *buttonBuddy = NULL; -static GameWindow *buttonEmote = NULL; -static GameWindow *textEntryChat = NULL; -static GameWindow *listboxLobbyPlayers = NULL; -static GameWindow *listboxLobbyChat = NULL; -static GameWindow *comboLobbyGroupRooms = NULL; -static GameWindow *parent = NULL; - -static Int groupRoomToJoin = 0; -static Int initialGadgetDelay = 2; -static Bool justEntered = FALSE; - -#if defined(_INTERNAL) || defined(_DEBUG) -Bool g_fakeCRC = FALSE; -Bool g_debugSlots = FALSE; -#endif - -std::list TheLobbyQueuedUTMs; - -// Slash commands ------------------------------------------------------------------------- -//extern "C" { -//int getQR2HostingStatus(void); -//} -extern int isThreadHosting; - -Bool handleLobbySlashCommands(UnicodeString uText) -{ - AsciiString message; - message.translate(uText); - - if (message.getCharAt(0) != '/') - { - return FALSE; // not a slash command - } - - AsciiString remainder = message.str() + 1; - AsciiString token; - remainder.nextToken(&token); - token.toLower(); - - if (token == "host") - { - UnicodeString s; - s.format(L"Hosting qr2:%d thread:%d", 0, isThreadHosting); - TheGameSpyInfo->addText(s, GameSpyColor[GSCOLOR_DEFAULT], NULL); - return TRUE; // was a slash command - } - else if (token == "me" && uText.getLength()>4) - { - TheGameSpyInfo->sendChat(UnicodeString(uText.str()+4), TRUE, listboxLobbyPlayers); - return TRUE; // was a slash command - } - else if (token == "refresh") - { - // Added 2/19/03 added the game refresh - refreshGameList(TRUE); - refreshPlayerList(TRUE); - return TRUE; // was a slash command - } - /* - if (token == "togglegamelist") - { - NameKeyType buttonID = NAMEKEY("WOLCustomLobby.wnd:ButtonGameListToggle"); - GameWindow *button = TheWindowManager->winGetWindowFromId(parent, buttonID); - if (button) - { - button->winHide(!button->winIsHidden()); - } - return TRUE; // was a slash command - } - else if (token == "adjustchat") - { - NameKeyType sliderID = NAMEKEY("WOLCustomLobby.wnd:SliderChatAdjust"); - GameWindow *slider = TheWindowManager->winGetWindowFromId(parent, sliderID); - if (slider) - { - slider->winHide(!slider->winIsHidden()); - } - return TRUE; // was a slash command - } - */ -#if defined(_INTERNAL) || defined(_DEBUG) - else if (token == "fakecrc") - { - g_fakeCRC = !g_fakeCRC; - TheGameSpyInfo->addText(UnicodeString(L"Toggled CRC fakery"), GameSpyColor[GSCOLOR_DEFAULT], NULL); - return TRUE; // was a slash command - } - else if (token == "slots") - { - g_debugSlots = !g_debugSlots; - TheGameSpyInfo->addText(UnicodeString(L"Toggled SlotList debug"), GameSpyColor[GSCOLOR_DEFAULT], NULL); - return TRUE; // was a slash command - } -#endif - - return FALSE; // not a slash command -} - -static Bool s_tryingToHostOrJoin = FALSE; -void SetLobbyAttemptHostJoin(Bool start) -{ - s_tryingToHostOrJoin = start; -} - -// Tooltips ------------------------------------------------------------------------------- - -static void playerTooltip(GameWindow *window, - WinInstanceData *instData, - UnsignedInt mouse) -{ - Int x, y, row, col; - x = LOLONGTOSHORT(mouse); - y = HILONGTOSHORT(mouse); - - GadgetListBoxGetEntryBasedOnXY(window, x, y, row, col); - - if (row == -1 || col == -1) - { - TheMouse->setCursorTooltip( UnicodeString::TheEmptyString);//TheGameText->fetch("TOOLTIP:PlayersInLobby") ); - return; - } - - UnicodeString uName = GadgetListBoxGetText(window, row, 2); - AsciiString aName; - aName.translate(uName); - - PlayerInfoMap::iterator it = TheGameSpyInfo->getPlayerInfoMap()->find(aName); - PlayerInfo *info = &(it->second); - Bool isLocalPlayer = (TheGameSpyInfo->getLocalName().compareNoCase(info->m_name) == 0); - - if (col == 0) - { - if (info->m_preorder) - { - TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:LobbyOfficersClub") ); - } - else - { - TheMouse->setCursorTooltip( UnicodeString::TheEmptyString); - } - return; - } - - AsciiString playerLocale = info->m_locale; - AsciiString localeIdentifier; - localeIdentifier.format("WOL:Locale%2.2d", atoi(playerLocale.str())); - Int playerWins = info->m_wins; - Int playerLosses = info->m_losses; - UnicodeString playerInfo; - playerInfo.format(TheGameText->fetch("TOOLTIP:PlayerInfo"), TheGameText->fetch(localeIdentifier).str(), playerWins, playerLosses); - - UnicodeString tooltip = UnicodeString::TheEmptyString;//TheGameText->fetch("TOOLTIP:PlayersInLobby"); - if (isLocalPlayer) - { - tooltip.format(TheGameText->fetch("TOOLTIP:LocalPlayer"), uName.str()); - } - else - { - // not us - if (TheGameSpyInfo->getBuddyMap()->find(info->m_profileID) != TheGameSpyInfo->getBuddyMap()->end()) - { - // buddy - tooltip.format(TheGameText->fetch("TOOLTIP:BuddyPlayer"), uName.str()); - } - else - { - if (info->m_profileID) - { - // non-buddy profiled player - tooltip.format(TheGameText->fetch("TOOLTIP:ProfiledPlayer"), uName.str()); - } - else - { - // non-profiled player - tooltip.format(TheGameText->fetch("TOOLTIP:GenericPlayer"), uName.str()); - } - } - } - - if (info->isIgnored()) - { - tooltip.concat(TheGameText->fetch("TOOLTIP:IgnoredModifier")); - } - - if (info->m_profileID) - { - tooltip.concat(playerInfo); - } - - Int rank = 0; - Int i = 0; - while( info->m_rankPoints >= TheRankPointValues->m_ranks[i + 1]) - ++i; - rank = i; - AsciiString sideName = "GUI:RandomSide"; - if (info->m_side > 0) - { - const PlayerTemplate *fac = ThePlayerTemplateStore->getNthPlayerTemplate(info->m_side); - if (fac) - { - sideName.format("SIDE:%s", fac->getSide().str()); - } - } - AsciiString rankName; - rankName.format("GUI:GSRank%d", rank); - UnicodeString tmp; - tmp.format(L"\n%ls %ls", TheGameText->fetch(sideName).str(), TheGameText->fetch(rankName).str()); - tooltip.concat(tmp); - - TheMouse->setCursorTooltip( tooltip, -1, NULL, 1.5f ); // the text and width are the only params used. the others are the default values. -} - -static void populateGroupRoomListbox(GameWindow *lb) -{ - if (!lb) - return; - - GadgetComboBoxReset(lb); - Int indexToSelect = -1; - GroupRoomMap::iterator iter; - - // now populate the combo box - for (iter = TheGameSpyInfo->getGroupRoomList()->begin(); iter != TheGameSpyInfo->getGroupRoomList()->end(); ++iter) - { - GameSpyGroupRoom room = iter->second; - if (room.m_groupID != TheGameSpyConfig->getQMChannel()) - { - DEBUG_LOG(("populateGroupRoomListbox(): groupID %d\n", room.m_groupID)); - if (room.m_groupID == TheGameSpyInfo->getCurrentGroupRoom()) - { - Int selected = GadgetComboBoxAddEntry(lb, room.m_translatedName, GameSpyColor[GSCOLOR_CURRENTROOM]); - GadgetComboBoxSetItemData(lb, selected, (void *)(room.m_groupID)); - indexToSelect = selected; - } - else - { - Int selected = GadgetComboBoxAddEntry(lb, room.m_translatedName, GameSpyColor[GSCOLOR_ROOM]); - GadgetComboBoxSetItemData(lb, selected, (void *)(room.m_groupID)); - } - } - else - { - DEBUG_LOG(("populateGroupRoomListbox(): skipping QM groupID %d\n", room.m_groupID)); - } - } - - GadgetComboBoxSetSelectedPos(lb, indexToSelect); -} - -static const char *rankNames[] = { - "Private", - "Corporal", - "Sergeant", - "Lieutenant", - "Captain", - "Major", - "Colonel", - "General", - "Brigadier", - "Commander", -}; - -const Image* LookupSmallRankImage(Int side, Int rankPoints) -{ - if (rankPoints == 0) - return NULL; - - Int rank = 0; - Int i = 0; - while( rankPoints >= TheRankPointValues->m_ranks[i + 1]) - ++i; - rank = i; - - if (rank < 0 || rank >= 10) - return NULL; - - AsciiString sideStr = "N"; - switch(side) - { - case 2: - sideStr = "USA"; - break; - case 3: - sideStr = "CHA"; - break; - case 4: - sideStr = "GLA"; - break; - } - - AsciiString fullImageName; - fullImageName.format("%s-%s", rankNames[rank], sideStr.str()); - const Image *img = TheMappedImageCollection->findImageByName(fullImageName); - DEBUG_ASSERTLOG(img, ("*** Could not load small rank image '%s' from TheMappedImageCollection!\n", fullImageName.str())); - return img; -} - -static Int insertPlayerInListbox(const PlayerInfo& info, Color color) -{ - UnicodeString uStr; - uStr.translate(info.m_name); - - Int currentRank = info.m_rankPoints; - Int currentSide = info.m_side; - /* since PersistentStorage updates now update PlayerInfo, we don't need this. - if (info.m_profileID) - { - PSPlayerStats psStats = TheGameSpyPSMessageQueue->findPlayerStatsByID(info.m_profileID); - if (psStats.id) - { - currentRank = CalculateRank(psStats); - - PerGeneralMap::iterator it; - Int numGames = 0; - for(it = psStats.games.begin(); it != psStats.games.end(); ++it) - { - if(it->second >= numGames) - { - numGames = it->second; - currentSide = it->first; - } - } - if(numGames == 0 || psStats.gamesAsRandom >= numGames ) - { - currentSide = 0; - } - } - } - */ - - Bool isPreorder = TheGameSpyInfo->didPlayerPreorder(info.m_profileID); - - const Image *preorderImg = TheMappedImageCollection->findImageByName("OfficersClubsmall"); - Int w = (preorderImg)?preorderImg->getImageWidth():10; - //Int h = (preorderImg)?preorderImg->getImageHeight():10; - w = min(GadgetListBoxGetColumnWidth(listboxLobbyPlayers, 0), w); - Int h = w; - if (!isPreorder) - preorderImg = NULL; - - const Image *rankImg = LookupSmallRankImage(currentSide, currentRank); - - Int index = GadgetListBoxAddEntryImage(listboxLobbyPlayers, preorderImg, -1, 0, w, h); - GadgetListBoxAddEntryImage(listboxLobbyPlayers, rankImg, index, 1, w, h); - GadgetListBoxAddEntryText(listboxLobbyPlayers, uStr, color, index, 2); - - return index; -} - -void PopulateLobbyPlayerListbox(void) -{ - if (!listboxLobbyPlayers) - return; - - // Display players - PlayerInfoMap *players = TheGameSpyInfo->getPlayerInfoMap(); - PlayerInfoMap::iterator it; - BuddyInfoMap *buddies = TheGameSpyInfo->getBuddyMap(); - BuddyInfoMap::iterator bIt; - if (listboxLobbyPlayers) - { - // save off old selection - Int maxSelectedItems = GadgetListBoxGetNumEntries(listboxLobbyPlayers); - Int *selectedIndices; - GadgetListBoxGetSelected(listboxLobbyPlayers, (Int *)(&selectedIndices)); - std::set selectedNames; - std::set::const_iterator selIt; - std::set indicesToSelect; - UnicodeString uStr; - Int numSelected = 0; - for (Int i=0; ibegin(); it != players->end(); ++it) - { - PlayerInfo info = it->second; - if (info.m_flags & PEER_FLAG_OP || TheGameSpyConfig->isPlayerVIP(info.m_profileID)) - { - Int index = insertPlayerInListbox(info, info.isIgnored()?GameSpyColor[GSCOLOR_PLAYER_IGNORED]:GameSpyColor[GSCOLOR_PLAYER_OWNER]); - - selIt = selectedNames.find(info.m_name); - if (selIt != selectedNames.end()) - { - DEBUG_LOG(("Marking index %d (%s) to re-select\n", index, info.m_name.str())); - indicesToSelect.insert(index); - } - } - } - - // Buddies - for (it = players->begin(); it != players->end(); ++it) - { - PlayerInfo info = it->second; - bIt = buddies->find(info.m_profileID); - if ( !(info.m_flags & PEER_FLAG_OP || TheGameSpyConfig->isPlayerVIP(info.m_profileID)) && bIt != buddies->end() ) - { - Int index = insertPlayerInListbox(info, info.isIgnored()?GameSpyColor[GSCOLOR_PLAYER_IGNORED]:GameSpyColor[GSCOLOR_PLAYER_BUDDY]); - - selIt = selectedNames.find(info.m_name); - if (selIt != selectedNames.end()) - { - DEBUG_LOG(("Marking index %d (%s) to re-select\n", index, info.m_name.str())); - indicesToSelect.insert(index); - } - } - } - - // Everyone else - for (it = players->begin(); it != players->end(); ++it) - { - PlayerInfo info = it->second; - bIt = buddies->find(info.m_profileID); - if ( !(info.m_flags & PEER_FLAG_OP || TheGameSpyConfig->isPlayerVIP(info.m_profileID)) && bIt == buddies->end() ) - { - Int index = insertPlayerInListbox(info, info.isIgnored()?GameSpyColor[GSCOLOR_PLAYER_IGNORED]:GameSpyColor[GSCOLOR_PLAYER_NORMAL]); - - selIt = selectedNames.find(info.m_name); - if (selIt != selectedNames.end()) - { - DEBUG_LOG(("Marking index %d (%s) to re-select\n", index, info.m_name.str())); - indicesToSelect.insert(index); - } - } - } - - // restore selection - if (indicesToSelect.size()) - { - std::set::const_iterator indexIt; - Int *newIndices = NEW Int[indicesToSelect.size()]; - for (i=0, indexIt = indicesToSelect.begin(); indexIt != indicesToSelect.end(); ++i, ++indexIt) - { - newIndices[i] = *indexIt; - DEBUG_LOG(("Queueing up index %d to re-select\n", *indexIt)); - } - GadgetListBoxSetSelected(listboxLobbyPlayers, newIndices, indicesToSelect.size()); - delete[] newIndices; - } - - if (indicesToSelect.size() != numSelected) - { - TheWindowManager->winSetLoneWindow(NULL); - } - - // restore top visible entry - GadgetListBoxSetTopVisibleEntry(listboxLobbyPlayers, previousTopIndex); - } - -} - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Lobby Menu */ -//------------------------------------------------------------------------------------------------- -void WOLLobbyMenuInit( WindowLayout *layout, void *userData ) -{ - nextScreen = NULL; - buttonPushed = false; - isShuttingDown = false; - - SetLobbyAttemptHostJoin(FALSE); // not trying to host or join - - gameListRefreshTime = 0; - playerListRefreshTime = 0; - - parentWOLLobbyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLCustomLobby.wnd:WOLLobbyMenuParent" ) ); - parent = TheWindowManager->winGetWindowFromId(NULL, parentWOLLobbyID); - - buttonBackID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:ButtonBack")); - buttonBack = TheWindowManager->winGetWindowFromId(parent, buttonBackID); - - buttonHostID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:ButtonHost")); - buttonHost = TheWindowManager->winGetWindowFromId(parent, buttonHostID); - - buttonRefreshID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:ButtonRefresh")); - buttonRefresh = TheWindowManager->winGetWindowFromId(parent, buttonRefreshID); - - buttonJoinID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:ButtonJoin")); - buttonJoin = TheWindowManager->winGetWindowFromId(parent, buttonJoinID); - buttonJoin->winEnable(FALSE); - - buttonBuddyID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:ButtonBuddy")); - buttonBuddy = TheWindowManager->winGetWindowFromId(parent, buttonBuddyID); - - buttonEmoteID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:ButtonEmote")); - buttonEmote = TheWindowManager->winGetWindowFromId(parent, buttonEmoteID); - - textEntryChatID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:TextEntryChat")); - textEntryChat = TheWindowManager->winGetWindowFromId(parent, textEntryChatID); - - listboxLobbyPlayersID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:ListboxPlayers")); - listboxLobbyPlayers = TheWindowManager->winGetWindowFromId(parent, listboxLobbyPlayersID); - listboxLobbyPlayers->winSetTooltipFunc(playerTooltip); - - listboxLobbyChatID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:ListboxChat")); - listboxLobbyChat = TheWindowManager->winGetWindowFromId(parent, listboxLobbyChatID); - TheGameSpyInfo->registerTextWindow(listboxLobbyChat); - - comboLobbyGroupRoomsID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:ComboBoxGroupRooms")); - comboLobbyGroupRooms = TheWindowManager->winGetWindowFromId(parent, comboLobbyGroupRoomsID); - - GadgetTextEntrySetText(textEntryChat, UnicodeString.TheEmptyString); - - populateGroupRoomListbox(comboLobbyGroupRooms); - - // Show Menu - layout->hide( FALSE ); - - // if we're not in a room, this will join the best available one - if (!TheGameSpyInfo->getCurrentGroupRoom()) - { - if (groupRoomToJoin) - { - DEBUG_LOG(("WOLLobbyMenuInit() - rejoining group room %d\n", groupRoomToJoin)); - TheGameSpyInfo->joinGroupRoom(groupRoomToJoin); - groupRoomToJoin = 0; - } - else - { - DEBUG_LOG(("WOLLobbyMenuInit() - joining best group room\n")); - TheGameSpyInfo->joinBestGroupRoom(); - } - } - else - { - DEBUG_LOG(("WOLLobbyMenuInit() - not joining group room because we're already in one\n")); - } - - GrabWindowInfo(); - - TheGameSpyInfo->clearStagingRoomList(); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_STARTGAMELIST; - req.gameList.restrictGameList = TheGameSpyConfig->restrictGamesToLobby(); - TheGameSpyPeerMessageQueue->addRequest(req); - - // animate controls -// TheShell->registerWithAnimateManager(parent, WIN_ANIMATION_SLIDE_TOP, TRUE); - TheShell->showShellMap(TRUE); - TheGameSpyGame->reset(); - - CustomMatchPreferences pref; -// GameWindow *slider = TheWindowManager->winGetWindowFromId(parent, sliderChatAdjustID); -// if (slider) -// { -// GadgetSliderSetPosition(slider, pref.getChatSizeSlider()); -// doSliderTrack(slider, pref.getChatSizeSlider()); -// } -// - if (pref.usesLongGameList()) - { - ToggleGameListType(); - } - - // Set Keyboard to chat window - TheWindowManager->winSetFocus( textEntryChat ); - raiseMessageBoxes = true; - - TheLobbyQueuedUTMs.clear(); - justEntered = TRUE; - initialGadgetDelay = 2; - GameWindow *win = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("WOLCustomLobby.wnd:GadgetParent")); - if(win) - win->winHide(TRUE); - DontShowMainMenu = TRUE; -} // WOLLobbyMenuInit - -//------------------------------------------------------------------------------------------------- -/** This is called when a shutdown is complete for this menu */ -//------------------------------------------------------------------------------------------------- -static void shutdownComplete( WindowLayout *layout ) -{ - - isShuttingDown = false; - - // hide the layout - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout, (nextScreen != NULL) ); - - if (nextScreen != NULL) - { - TheShell->push(nextScreen); - } - - nextScreen = NULL; - -} // end if - -//------------------------------------------------------------------------------------------------- -/** WOL Lobby Menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLLobbyMenuShutdown( WindowLayout *layout, void *userData ) -{ - CustomMatchPreferences pref; -// GameWindow *slider = TheWindowManager->winGetWindowFromId(parent, sliderChatAdjustID); -// if (slider) -// { -// pref.setChatSizeSlider(GadgetSliderGetPosition(slider)); -// } - if (GetGameInfoListBox()) - { - pref.setUsesLongGameList(FALSE); - } - else - { - pref.setUsesLongGameList(TRUE); - } - pref.write(); - - ReleaseWindowInfo(); - - TheGameSpyInfo->unregisterTextWindow(listboxLobbyChat); - - //TheGameSpyChat->stopListingGames(); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_STOPGAMELIST; - TheGameSpyPeerMessageQueue->addRequest(req); - - listboxLobbyChat = NULL; - listboxLobbyPlayers = NULL; - - isShuttingDown = true; - - // if we are shutting down for an immediate pop, skip the animations - Bool popImmediate = *(Bool *)userData; - if( popImmediate ) - { - - shutdownComplete( layout ); - return; - - } //end if - - TheShell->reverseAnimatewindow(); - DontShowMainMenu = FALSE; - - RaiseGSMessageBox(); - TheTransitionHandler->reverse("WOLCustomLobbyFade"); - -} // WOLLobbyMenuShutdown - -static void fillPlayerInfo(const PeerResponse *resp, PlayerInfo *info) -{ - info->m_name = resp->nick.c_str(); - info->m_profileID = resp->player.profileID; - info->m_flags = resp->player.flags; - info->m_wins = resp->player.wins; - info->m_losses = resp->player.losses; - info->m_locale = resp->locale.c_str(); - info->m_rankPoints= resp->player.rankPoints; - info->m_side = resp->player.side; - info->m_preorder = resp->player.preorder; -} - -#ifdef PERF_TEST -static const char* getMessageString(Int t) -{ - switch(t) - { - case PeerResponse::PEERRESPONSE_LOGIN: - return "login"; - case PeerResponse::PEERRESPONSE_DISCONNECT: - return "disconnect"; - case PeerResponse::PEERRESPONSE_MESSAGE: - return "message"; - case PeerResponse::PEERRESPONSE_GROUPROOM: - return "group room"; - case PeerResponse::PEERRESPONSE_STAGINGROOM: - return "staging room"; - case PeerResponse::PEERRESPONSE_STAGINGROOMPLAYERINFO: - return "staging room player info"; - case PeerResponse::PEERRESPONSE_JOINGROUPROOM: - return "group room join"; - case PeerResponse::PEERRESPONSE_CREATESTAGINGROOM: - return "staging room create"; - case PeerResponse::PEERRESPONSE_JOINSTAGINGROOM: - return "staging room join"; - case PeerResponse::PEERRESPONSE_PLAYERJOIN: - return "player join"; - case PeerResponse::PEERRESPONSE_PLAYERLEFT: - return "player part"; - case PeerResponse::PEERRESPONSE_PLAYERCHANGEDNICK: - return "player nick"; - case PeerResponse::PEERRESPONSE_PLAYERINFO: - return "player info"; - case PeerResponse::PEERRESPONSE_PLAYERCHANGEDFLAGS: - return "player flags"; - case PeerResponse::PEERRESPONSE_ROOMUTM: - return "room UTM"; - case PeerResponse::PEERRESPONSE_PLAYERUTM: - return "player UTM"; - case PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS: - return "QM status"; - case PeerResponse::PEERRESPONSE_GAMESTART: - return "game start"; - case PeerResponse::PEERRESPONSE_FAILEDTOHOST: - return "host failure"; - } - return "unknown"; -} -#endif // PERF_TEST - -//------------------------------------------------------------------------------------------------- -/** refreshGameList - The Bool is used to force refresh if the refresh button was hit.*/ -//------------------------------------------------------------------------------------------------- -static void refreshGameList( Bool forceRefresh ) -{ - Int refreshInterval = gameListRefreshInterval; - - if (forceRefresh || ((gameListRefreshTime == 0) || ((gameListRefreshTime + refreshInterval) <= timeGetTime()))) - { - if (TheGameSpyInfo->hasStagingRoomListChanged()) - { - //DEBUG_LOG(("################### refreshing game list\n")); - //DEBUG_LOG(("gameRefreshTime=%d, refreshInterval=%d, now=%d\n", gameListRefreshTime, refreshInterval, timeGetTime())); - RefreshGameListBoxes(); - gameListRefreshTime = timeGetTime(); - } else { - //DEBUG_LOG(("-")); - } - } else { - //DEBUG_LOG(("gameListRefreshTime: %d refreshInterval: %d\n")); - } -} -//------------------------------------------------------------------------------------------------- -/** refreshPlayerList - The Bool is used to force refresh if the refresh button was hit.*/ -//------------------------------------------------------------------------------------------------- -static void refreshPlayerList( Bool forceRefresh ) -{ - Int refreshInterval = playerListRefreshInterval; - - if (forceRefresh ||((playerListRefreshTime == 0) || ((playerListRefreshTime + refreshInterval) <= timeGetTime()))) - { - PopulateLobbyPlayerListbox(); - playerListRefreshTime = timeGetTime(); - } -} -//------------------------------------------------------------------------------------------------- -/** WOL Lobby Menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLLobbyMenuUpdate( WindowLayout * layout, void *userData) -{ - if(justEntered) - { - if(initialGadgetDelay == 1) - { - TheTransitionHandler->remove("MainMenuDefaultMenuLogoFade"); - TheTransitionHandler->setGroup("WOLCustomLobbyFade"); - initialGadgetDelay = 2; - justEntered = FALSE; - } - else - initialGadgetDelay--; - } - if (TheGameLogic->isInShellGame() && TheGameLogic->getFrame() == 1) - { - SignalUIInteraction(SHELL_SCRIPT_HOOK_GENERALS_ONLINE_ENTERED_FROM_GAME); - } - - - // We'll only be successful if we've requested to - if(isShuttingDown && TheShell->isAnimFinished() && TheTransitionHandler->isFinished()) - shutdownComplete(layout); - - if (raiseMessageBoxes) - { - RaiseGSMessageBox(); - raiseMessageBoxes = false; - } - - if (TheShell->isAnimFinished() && TheTransitionHandler->isFinished() && !buttonPushed && TheGameSpyPeerMessageQueue) - { - HandleBuddyResponses(); - HandlePersistentStorageResponses(); - -#ifdef PERF_TEST - UnsignedInt start = timeGetTime(); - UnsignedInt end = timeGetTime(); - std::list responses; - Int numMessages = 0; -#endif // PERF_TEST - - Int allowedMessages = TheGameSpyInfo->getMaxMessagesPerUpdate(); - Bool sawImportantMessage = FALSE; - Bool shouldRepopulatePlayers = FALSE; - PeerResponse resp; - while (allowedMessages-- && !sawImportantMessage && TheGameSpyPeerMessageQueue->getResponse( resp )) - { -#ifdef PERF_TEST - ++numMessages; - responses.push_back(resp.peerResponseType); -#endif // PERF_TEST - switch (resp.peerResponseType) - { - case PeerResponse::PEERRESPONSE_JOINGROUPROOM: - sawImportantMessage = TRUE; - if (resp.joinGroupRoom.ok) - { - //buttonPushed = true; - TheGameSpyInfo->setCurrentGroupRoom(resp.joinGroupRoom.id); - TheGameSpyInfo->getPlayerInfoMap()->clear(); - GroupRoomMap::iterator iter = TheGameSpyInfo->getGroupRoomList()->find(resp.joinGroupRoom.id); - if (iter != TheGameSpyInfo->getGroupRoomList()->end()) - { - GameSpyGroupRoom room = iter->second; - UnicodeString msg; - msg.format(TheGameText->fetch("GUI:LobbyJoined"), room.m_translatedName.str()); - TheGameSpyInfo->addText(msg, GameSpyColor[GSCOLOR_DEFAULT], NULL); - } - } - else - { - DEBUG_LOG(("WOLLobbyMenuUpdate() - joining best group room\n")); - TheGameSpyInfo->joinBestGroupRoom(); - } - populateGroupRoomListbox(comboLobbyGroupRooms); - shouldRepopulatePlayers = TRUE; - break; - case PeerResponse::PEERRESPONSE_PLAYERCHANGEDFLAGS: - { - PlayerInfo p; - fillPlayerInfo(&resp, &p); - TheGameSpyInfo->updatePlayerInfo(p); - shouldRepopulatePlayers = TRUE; - } - break; - case PeerResponse::PEERRESPONSE_PLAYERCHANGEDNICK: - { - PlayerInfo p; - fillPlayerInfo(&resp, &p); - TheGameSpyInfo->updatePlayerInfo(p); - shouldRepopulatePlayers = TRUE; - } - break; - case PeerResponse::PEERRESPONSE_PLAYERINFO: - { - PlayerInfo p; - fillPlayerInfo(&resp, &p); - TheGameSpyInfo->updatePlayerInfo(p); - shouldRepopulatePlayers = TRUE; - } - break; - case PeerResponse::PEERRESPONSE_PLAYERJOIN: - { - if (resp.player.roomType == GroupRoom) - { - PlayerInfo p; - fillPlayerInfo(&resp, &p); - TheGameSpyInfo->updatePlayerInfo(p); - shouldRepopulatePlayers = TRUE; - } - } - break; - case PeerResponse::PEERRESPONSE_PLAYERUTM: - case PeerResponse::PEERRESPONSE_ROOMUTM: - { - DEBUG_LOG(("Putting off a UTM in the lobby\n")); - TheLobbyQueuedUTMs.push_back(resp); - } - break; - case PeerResponse::PEERRESPONSE_PLAYERLEFT: - { - PlayerInfo p; - fillPlayerInfo(&resp, &p); - TheGameSpyInfo->playerLeftGroupRoom(resp.nick.c_str()); - shouldRepopulatePlayers = TRUE; - } - break; - case PeerResponse::PEERRESPONSE_MESSAGE: - { - TheGameSpyInfo->addChat(resp.nick.c_str(), resp.message.profileID, - UnicodeString(resp.text.c_str()), !resp.message.isPrivate, resp.message.isAction, listboxLobbyChat); - } - break; - case PeerResponse::PEERRESPONSE_DISCONNECT: - { - sawImportantMessage = TRUE; - UnicodeString title, body; - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", resp.discon.reason); - title = TheGameText->fetch( "GUI:GSErrorTitle" ); - body = TheGameText->fetch( disconMunkee ); - GameSpyCloseAllOverlays(); - GSMessageBoxOk( title, body ); - TheGameSpyInfo->reset(); - TheShell->pop(); - } - case PeerResponse::PEERRESPONSE_CREATESTAGINGROOM: - { - sawImportantMessage = TRUE; - SetLobbyAttemptHostJoin(FALSE); - if (resp.createStagingRoom.result == PEERJoinSuccess) - { - // Woohoo! On to our next screen! - buttonPushed = true; - nextScreen = "Menus/GameSpyGameOptionsMenu.wnd"; - TheShell->pop(); - TheGameSpyInfo->markAsStagingRoomHost(); - TheGameSpyInfo->setGameOptions(); - } - } - break; - case PeerResponse::PEERRESPONSE_JOINSTAGINGROOM: - { - sawImportantMessage = TRUE; - SetLobbyAttemptHostJoin(FALSE); - Bool isHostPresent = TRUE; - if (resp.joinStagingRoom.ok == PEERTrue) - { - GameSpyStagingRoom *room = TheGameSpyInfo->getCurrentStagingRoom(); - if (!room) - { - isHostPresent = FALSE; - } - else - { - isHostPresent = FALSE; - for (Int i=0; igetConstSlot(0)->getName()); - const char *firstPlayer = resp.stagingRoomPlayerNames[i].c_str(); - if (!strcmp(hostName.str(), firstPlayer)) - { - DEBUG_LOG(("Saw host %s == %s in slot %d\n", hostName.str(), firstPlayer, i)); - isHostPresent = TRUE; - } - } - } - } - if (resp.joinStagingRoom.ok == PEERTrue && isHostPresent) - { - // Woohoo! On to our next screen! - buttonPushed = true; - nextScreen = "Menus/GameSpyGameOptionsMenu.wnd"; - TheShell->pop(); - } - else - { - UnicodeString s; - - switch(resp.joinStagingRoom.result) - { - case PEERFullRoom: // The room is full. - s = TheGameText->fetch("GUI:JoinFailedRoomFull"); - break; - case PEERInviteOnlyRoom: // The room is invite only. - s = TheGameText->fetch("GUI:JoinFailedInviteOnly"); - break; - case PEERBannedFromRoom: // The local user is banned from the room. - s = TheGameText->fetch("GUI:JoinFailedBannedFromRoom"); - break; - case PEERBadPassword: // An incorrect password (or none) was given for a passworded room. - s = TheGameText->fetch("GUI:JoinFailedBadPassword"); - break; - case PEERAlreadyInRoom: // The local user is already in or entering a room of the same type. - s = TheGameText->fetch("GUI:JoinFailedAlreadyInRoom"); - break; - case PEERNoConnection: // Can't join a room if there's no chat connection. - s = TheGameText->fetch("GUI:JoinFailedNoConnection"); - break; - default: - s = TheGameText->fetch("GUI:JoinFailedDefault"); - break; - } - GSMessageBoxOk(TheGameText->fetch("GUI:JoinFailedDefault"), s); - if (groupRoomToJoin) - { - DEBUG_LOG(("WOLLobbyMenuUpdate() - rejoining group room %d\n", groupRoomToJoin)); - TheGameSpyInfo->joinGroupRoom(groupRoomToJoin); - groupRoomToJoin = 0; - } - else - { - DEBUG_LOG(("WOLLobbyMenuUpdate() - joining best group room\n")); - TheGameSpyInfo->joinBestGroupRoom(); - } - } - } - break; - case PeerResponse::PEERRESPONSE_STAGINGROOMLISTCOMPLETE: - TheGameSpyInfo->sawFullGameList(); - break; - case PeerResponse::PEERRESPONSE_STAGINGROOM: - { - GameSpyStagingRoom room; - switch(resp.stagingRoom.action) - { - case PEER_CLEAR: - TheGameSpyInfo->clearStagingRoomList(); - //TheGameSpyInfo->addText( UnicodeString(L"gameList: PEER_CLEAR"), GameSpyColor[GSCOLOR_DEFAULT], listboxLobbyChat ); - break; - case PEER_ADD: - case PEER_UPDATE: - { - if (resp.stagingRoom.percentComplete == 100) - { - TheGameSpyInfo->sawFullGameList(); - } - - //if (ParseAsciiStringToGameInfo(&room, resp.stagingRoomMapName.c_str())) - //if (ParseAsciiStringToGameInfo(&room, resp.stagingServerGameOptions.c_str())) - Bool serverOk = TRUE; - if (!resp.stagingRoomMapName.length()) - { - serverOk = FALSE; - } - // fix for ghost game problem - need to iterate over all resp.stagingRoomPlayerNames[i] - Bool sawSelf = FALSE; - //for (Int i=0; igetLocalName() == resp.stagingRoomPlayerNames[0].c_str()) - { - sawSelf = TRUE; // don't show ghost games for myself - } - //} - if (sawSelf) - serverOk = FALSE; - - if (serverOk) - { - room.setGameName(UnicodeString(resp.stagingServerName.c_str())); - room.setID(resp.stagingRoom.id); - room.setHasPassword(resp.stagingRoom.requiresPassword); - room.setVersion(resp.stagingRoom.version); - room.setExeCRC(resp.stagingRoom.exeCRC); - room.setIniCRC(resp.stagingRoom.iniCRC); - room.setAllowObservers(resp.stagingRoom.allowObservers); - room.setPingString(resp.stagingServerPingString.c_str()); - room.setLadderIP(resp.stagingServerLadderIP.c_str()); - room.setLadderPort(resp.stagingRoom.ladderPort); - room.setReportedNumPlayers(resp.stagingRoom.numPlayers); - room.setReportedMaxPlayers(resp.stagingRoom.maxPlayers); - room.setReportedNumObservers(resp.stagingRoom.numObservers); - - Int i; - AsciiString gsMapName = resp.stagingRoomMapName.c_str(); - AsciiString mapName = ""; - for (i=0; iportableMapPathToRealMapPath(mapName)); - - Int numPlayers = 0; - for (i=0; isetWins( resp.stagingRoom.wins[i] ); - slot->setLosses( resp.stagingRoom.losses[i] ); - slot->setProfileID( resp.stagingRoom.profileID[i] ); - slot->setPlayerTemplate( resp.stagingRoom.faction[i] ); - slot->setColor( resp.stagingRoom.color[i] ); - if (resp.stagingRoom.profileID[i] == SLOT_EASY_AI) - { - slot->setState(SLOT_EASY_AI); - ++numPlayers; - } - else if (resp.stagingRoom.profileID[i] == SLOT_MED_AI) - { - slot->setState(SLOT_MED_AI); - ++numPlayers; - } - else if (resp.stagingRoom.profileID[i] == SLOT_BRUTAL_AI) - { - slot->setState(SLOT_BRUTAL_AI); - ++numPlayers; - } - else if (resp.stagingRoomPlayerNames[i].length()) - { - UnicodeString nameUStr; - nameUStr.translate(resp.stagingRoomPlayerNames[i].c_str()); - slot->setState(SLOT_PLAYER, nameUStr); - ++numPlayers; - } - else - { - slot->setState(SLOT_OPEN); - } - } - } - DEBUG_ASSERTCRASH(numPlayers, ("Game had no players!\n")); - //DEBUG_LOG(("Saw room: hasPass=%d, allowsObservers=%d\n", room.getHasPassword(), room.getAllowObservers())); - if (resp.stagingRoom.action == PEER_ADD) - { - TheGameSpyInfo->addStagingRoom(room); - //TheGameSpyInfo->addText( UnicodeString(L"gameList: PEER_ADD"), GameSpyColor[GSCOLOR_DEFAULT], listboxLobbyChat ); - } - else - { - TheGameSpyInfo->updateStagingRoom(room); - //TheGameSpyInfo->addText( UnicodeString(L"gameList: PEER_UPDATE"), GameSpyColor[GSCOLOR_DEFAULT], listboxLobbyChat ); - } - } - else - { - room.setID(resp.stagingRoom.id); - TheGameSpyInfo->removeStagingRoom(room); - //TheGameSpyInfo->addText( UnicodeString(L"gameList: PEER_UPDATE FAILED"), GameSpyColor[GSCOLOR_DEFAULT], listboxLobbyChat ); - } - break; - } - case PEER_REMOVE: - room.setID(resp.stagingRoom.id); - TheGameSpyInfo->removeStagingRoom(room); - //TheGameSpyInfo->addText( UnicodeString(L"gameList: PEER_REMOVE"), GameSpyColor[GSCOLOR_DEFAULT], listboxLobbyChat ); - break; - default: - //TheGameSpyInfo->addText( UnicodeString(L"gameList: Unknown"), GameSpyColor[GSCOLOR_DEFAULT], listboxLobbyChat ); - break; - } - } - break; - } - } -#if 0 - if (shouldRepopulatePlayers) - { - PopulateLobbyPlayerListbox(); - } -#else - refreshPlayerList(); -#endif - -#ifdef PERF_TEST - // check performance - end = timeGetTime(); - PERF_LOG(("Frame time was %d ms\n", end-start)); - std::list::const_iterator it; - for (it = responses.begin(); it != responses.end(); ++it) - { - PERF_LOG((" %s\n", getMessageString(*it))); - } - PERF_LOG(("\n")); -#endif // PERF_TEST - -#if 0 -// Removed 2-17-03 to pull out into a function so we can do the same checks - Int refreshInterval = gameListRefreshInterval; - - if ((gameListRefreshTime == 0) || ((gameListRefreshTime + refreshInterval) <= timeGetTime())) - { - if (TheGameSpyInfo->hasStagingRoomListChanged()) - { - //DEBUG_LOG(("################### refreshing game list\n")); - //DEBUG_LOG(("gameRefreshTime=%d, refreshInterval=%d, now=%d\n", gameListRefreshTime, refreshInterval, timeGetTime())); - RefreshGameListBoxes(); - gameListRefreshTime = timeGetTime(); - } else { - //DEBUG_LOG(("-")); - } - } else { - //DEBUG_LOG(("gameListRefreshTime: %d refreshInterval: %d\n")); - } -#else - refreshGameList(); -#endif - } -}// WOLLobbyMenuUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Lobby Menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLLobbyMenuInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - if (buttonPushed) - break; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonBack, buttonBackID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// WOLLobbyMenuInput - -//static void doSliderTrack(GameWindow *control, Int val) -//{ -// Int sliderW, sliderH, sliderX, sliderY; -// control->winGetPosition(&sliderX, &sliderY); -// control->winGetSize(&sliderW, &sliderH); -// Real cursorY = sliderY + (100-val)*0.01f*sliderH; -// -// extern GameWindow *listboxLobbyGamesSmall; -// extern GameWindow *listboxLobbyGamesLarge; -// extern GameWindow *listboxLobbyGameInfo; -// -// static Int gwsX = 0, gwsY = 0, gwsW = 0, gwsH = 0; -// static Int gwlX = 0, gwlY = 0, gwlW = 0, gwlH = 0; -// static Int gwiX = 0, gwiY = 0, gwiW = 0, gwiH = 0; -// static Int pwX = 0, pwY = 0, pwW = 0, pwH = 0; -// static Int chatPosX = 0, chatPosY = 0, chatW = 0, chatH = 0; -// static Int spacing = 0; -// if (chatPosX == 0) -// { -// listboxLobbyChat->winGetPosition(&chatPosX, &chatPosY); -// listboxLobbyChat->winGetSize(&chatW, &chatH); -// -//// listboxLobbyGamesSmall->winGetPosition(&gwsX, &gwsY); -//// listboxLobbyGamesSmall->winGetSize(&gwsW, &gwsH); -// -// listboxLobbyGamesLarge->winGetPosition(&gwlX, &gwlY); -// listboxLobbyGamesLarge->winGetSize(&gwlW, &gwlH); -// -//// listboxLobbyGameInfo->winGetPosition(&gwiX, &gwiY); -//// listboxLobbyGameInfo->winGetSize(&gwiW, &gwiH); -//// -// listboxLobbyPlayers->winGetPosition(&pwX, &pwY); -// listboxLobbyPlayers->winGetSize(&pwW, &pwH); -// -// spacing = chatPosY - pwY - pwH; -// } -// -// Int newChatY = cursorY; -// Int newChatH = chatH + chatPosY - newChatY; -// listboxLobbyChat->winSetPosition(chatPosX, newChatY); -// listboxLobbyChat->winSetSize(chatW, newChatH); -// -// Int newH = cursorY - pwY - spacing; -// listboxLobbyPlayers->winSetSize(pwW, newH); -//// listboxLobbyGamesSmall->winSetSize(gwsW, newH); -// listboxLobbyGamesLarge->winSetSize(gwlW, newH); -//// listboxLobbyGameInfo->winSetSize(gwiW, newH); - - -//------------------------------------------------------------------------------------------------- -/** WOL Lobby Menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLLobbyMenuSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - static NameKeyType buttonGameListTypeToggleID = NAMEKEY_INVALID; - - switch( msg ) - { - - - //--------------------------------------------------------------------------------------------- - case GWM_CREATE: - { - buttonGameListTypeToggleID = NAMEKEY("WOLCustomLobby.wnd:ButtonGameListToggle"); -// sliderChatAdjustID = NAMEKEY("WOLCustomLobby.wnd:SliderChatAdjust"); - - break; - } // case GWM_DESTROY: - - //--------------------------------------------------------------------------------------------- - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - //--------------------------------------------------------------------------------------------- - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - //--------------------------------------------------------------------------------------------- - case GLM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if ( controlID == GetGameListBoxID() ) - { - int rowSelected = mData2; - if( rowSelected >= 0 ) - { - buttonJoin->winEnable(TRUE); - static UnsignedInt lastFrame = 0; - static Int lastID = -1; - UnsignedInt now = TheGameClient->getFrame(); - - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_GETEXTENDEDSTAGINGROOMINFO; - req.stagingRoom.id = (Int)GadgetListBoxGetItemData(control, rowSelected, 0); - - if (lastID != req.stagingRoom.id || now > lastFrame + 60) - { - TheGameSpyPeerMessageQueue->addRequest(req); - } - - lastID = req.stagingRoom.id; - lastFrame = now; - } - else - { - buttonJoin->winEnable(FALSE); - } - if (GetGameInfoListBox()) - { - RefreshGameInfoListBox(GetGameListBox(), GetGameInfoListBox()); - } - } //if ( controlID == GetGameListBoxID() ) - - break; - } - - //--------------------------------------------------------------------------------------------- - case GBM_SELECTED: - { - if (buttonPushed) - break; - - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if (HandleSortButton((NameKeyType)controlID)) - break; - - // If we back out, just bail - we haven't gotten far enough to need to log out - if ( controlID == buttonBackID ) - { - if (s_tryingToHostOrJoin) - break; - - // Leave any group room, then pop off the screen - TheGameSpyInfo->leaveGroupRoom(); - - SetLobbyAttemptHostJoin( TRUE ); // pretend, since we don't want to queue up another action - buttonPushed = true; - nextScreen = "Menus/WOLWelcomeMenu.wnd"; - TheShell->pop(); - - } //if ( controlID == buttonBack ) - else if ( controlID == buttonRefreshID ) - { - // Added 2/17/03 added the game refresh button - refreshGameList(TRUE); - refreshPlayerList(TRUE); - } - else if ( controlID == buttonHostID ) - { - if (s_tryingToHostOrJoin) - break; - - SetLobbyAttemptHostJoin( TRUE ); - TheLobbyQueuedUTMs.clear(); - groupRoomToJoin = TheGameSpyInfo->getCurrentGroupRoom(); - GameSpyOpenOverlay(GSOVERLAY_GAMEOPTIONS); - } - else if ( controlID == buttonJoinID ) - { - if (s_tryingToHostOrJoin) - break; - - TheLobbyQueuedUTMs.clear(); - // Look for a game to join - groupRoomToJoin = TheGameSpyInfo->getCurrentGroupRoom(); - Int selected; - GadgetListBoxGetSelected(GetGameListBox(), &selected); - if (selected >= 0) - { - Int selectedID = (Int)GadgetListBoxGetItemData(GetGameListBox(), selected); - if (selectedID > 0) - { - StagingRoomMap *srm = TheGameSpyInfo->getStagingRoomList(); - StagingRoomMap::iterator srmIt = srm->find(selectedID); - if (srmIt != srm->end()) - { - GameSpyStagingRoom *roomToJoin = srmIt->second; - if (!roomToJoin || roomToJoin->getExeCRC() != TheGlobalData->m_exeCRC || roomToJoin->getIniCRC() != TheGlobalData->m_iniCRC) - { - // bad crc. don't go. - DEBUG_LOG(("WOLLobbyMenuSystem - CRC mismatch with the game I'm trying to join. My CRC's - EXE:0x%08X INI:0x%08X Their CRC's - EXE:0x%08x INI:0x%08x\n", TheGlobalData->m_exeCRC, TheGlobalData->m_iniCRC, roomToJoin->getExeCRC(), roomToJoin->getIniCRC())); -#if defined(_DEBUG) || defined(_INTERNAL) - if (TheGlobalData->m_netMinPlayers) - { - GSMessageBoxOk(TheGameText->fetch("GUI:JoinFailedDefault"), TheGameText->fetch("GUI:JoinFailedCRCMismatch")); - break; - } - else if (g_fakeCRC) - { - TheWritableGlobalData->m_exeCRC = roomToJoin->getExeCRC(); - TheWritableGlobalData->m_iniCRC = roomToJoin->getIniCRC(); - } -#else - GSMessageBoxOk(TheGameText->fetch("GUI:JoinFailedDefault"), TheGameText->fetch("GUI:JoinFailedCRCMismatch")); - break; -#endif - } - Bool unknownLadder = (roomToJoin->getLadderPort() && TheLadderList->findLadder(roomToJoin->getLadderIP(), roomToJoin->getLadderPort()) == NULL); - if (unknownLadder) - { - GSMessageBoxOk(TheGameText->fetch("GUI:JoinFailedDefault"), TheGameText->fetch("GUI:JoinFailedUnknownLadder")); - break; - } - if (roomToJoin->getNumPlayers() == MAX_SLOTS) - { - GSMessageBoxOk(TheGameText->fetch("GUI:JoinFailedDefault"), TheGameText->fetch("GUI:JoinFailedRoomFull")); - break; - } - TheGameSpyInfo->markAsStagingRoomJoiner(selectedID); - TheGameSpyGame->setGameName(roomToJoin->getGameName()); - TheGameSpyGame->setLadderIP(roomToJoin->getLadderIP()); - TheGameSpyGame->setLadderPort(roomToJoin->getLadderPort()); - SetLobbyAttemptHostJoin( TRUE ); - if (roomToJoin->getHasPassword()) - { - GameSpyOpenOverlay(GSOVERLAY_GAMEPASSWORD); - } - else - { - // no password - just join it - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_JOINSTAGINGROOM; - req.text = srmIt->second->getGameName().str(); - req.stagingRoom.id = selectedID; - req.password = ""; - TheGameSpyPeerMessageQueue->addRequest(req); - } - } - } - else - { - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:NoGameInfo"), NULL); - } - } - else - { - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:NoGameSelected"), NULL); - } - } - else if ( controlID == buttonBuddyID ) - { - GameSpyToggleOverlay( GSOVERLAY_BUDDY ); - } - else if ( controlID == buttonGameListTypeToggleID ) - { - ToggleGameListType(); - } - else if ( controlID == buttonEmoteID ) - { - // read the user's input and clear the entry box - UnicodeString txtInput; - txtInput.set(GadgetTextEntryGetText( textEntryChat )); - GadgetTextEntrySetText(textEntryChat, UnicodeString::TheEmptyString); - txtInput.trim(); - if (!txtInput.isEmpty()) - { - // Send the message - TheGameSpyInfo->sendChat( txtInput, FALSE, listboxLobbyPlayers ); // 'emote' button now just sends text - } - } - - break; - }// case GBM_SELECTED: - - //--------------------------------------------------------------------------------------------- - case GCM_SELECTED: - { - if (s_tryingToHostOrJoin) - break; - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if( controlID == comboLobbyGroupRoomsID ) - { - int rowSelected = -1; - GadgetComboBoxGetSelectedPos(control, &rowSelected); - - DEBUG_LOG(("Row selected = %d\n", rowSelected)); - if (rowSelected >= 0) - { - Int groupID; - groupID = (Int)GadgetComboBoxGetItemData(comboLobbyGroupRooms, rowSelected); - DEBUG_LOG(("ItemData was %d, current Group Room is %d\n", groupID, TheGameSpyInfo->getCurrentGroupRoom())); - if (groupID && groupID != TheGameSpyInfo->getCurrentGroupRoom()) - { - TheGameSpyInfo->leaveGroupRoom(); - TheGameSpyInfo->joinGroupRoom(groupID); - - if (TheGameSpyConfig->restrictGamesToLobby()) - { - TheGameSpyInfo->clearStagingRoomList(); - RefreshGameListBoxes(); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_STARTGAMELIST; - req.gameList.restrictGameList = TRUE; - TheGameSpyPeerMessageQueue->addRequest(req); - } - } - } - } - } // case GCM_SELECTED - break; - - //--------------------------------------------------------------------------------------------- - case GLM_DOUBLE_CLICKED: - { - if (buttonPushed) - break; - - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if (controlID == GetGameListBoxID()) - { - int rowSelected = mData2; - - if (rowSelected >= 0) - { - GadgetListBoxSetSelected( control, rowSelected ); - GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonJoinID ); - - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)button, buttonJoinID ); - } - } - break; - }// case GLM_DOUBLE_CLICKED: - - //--------------------------------------------------------------------------------------------- - case GLM_RIGHT_CLICKED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if( controlID == listboxLobbyPlayersID ) - { - RightClickStruct *rc = (RightClickStruct *)mData2; - WindowLayout *rcLayout = NULL; - GameWindow *rcMenu; - if(rc->pos < 0) - { - GadgetListBoxSetSelected(control, -1); - break; - } - - GPProfile profileID = 0; - AsciiString aName; - aName.translate(GadgetListBoxGetText(control, rc->pos, COLUMN_PLAYERNAME)); - PlayerInfoMap::iterator it = TheGameSpyInfo->getPlayerInfoMap()->find(aName); - if (it != TheGameSpyInfo->getPlayerInfoMap()->end()) - profileID = it->second.m_profileID; - - Bool isBuddy = FALSE; - if (profileID <= 0) - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCNoProfileMenu.wnd")); - else - { - if (profileID == TheGameSpyInfo->getLocalProfileID()) - { - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCLocalPlayerMenu.wnd")); - } - else if(TheGameSpyInfo->isBuddy(profileID)) - { - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCBuddiesMenu.wnd")); - isBuddy = TRUE; - } - else - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCNonBuddiesMenu.wnd")); - } - if(!rcLayout) - break; - - GadgetListBoxSetSelected(control, rc->pos); - - rcMenu = rcLayout->getFirstWindow(); - rcMenu->winGetLayout()->runInit(); - rcMenu->winBringToTop(); - rcMenu->winHide(FALSE); - setUnignoreText( rcLayout, aName, profileID); - ICoord2D rcSize, rcPos; - rcMenu->winGetSize(&rcSize.x, &rcSize.y); - rcPos.x = rc->mouseX; - rcPos.y = rc->mouseY; - if(rc->mouseX + rcSize.x > TheDisplay->getWidth()) - rcPos.x = TheDisplay->getWidth() - rcSize.x; - if(rc->mouseY + rcSize.y > TheDisplay->getHeight()) - rcPos.y = TheDisplay->getHeight() - rcSize.y; - rcMenu->winSetPosition(rcPos.x, rcPos.y); - - GameSpyRCMenuData *rcData = NEW GameSpyRCMenuData; - rcData->m_id = profileID; - rcData->m_nick = aName; - rcData->m_itemType = (isBuddy)?ITEM_BUDDY:ITEM_NONBUDDY; - rcMenu->winSetUserData((void *)rcData); - TheWindowManager->winSetLoneWindow(rcMenu); - } - else if( controlID == GetGameListBoxID() ) - { - RightClickStruct *rc = (RightClickStruct *)mData2; - WindowLayout *rcLayout = NULL; - GameWindow *rcMenu; - if(rc->pos < 0) - { - GadgetListBoxSetSelected(control, -1); - break; - } - - Int selectedID = (Int)GadgetListBoxGetItemData(control, rc->pos); - if (selectedID > 0) - { - StagingRoomMap *srm = TheGameSpyInfo->getStagingRoomList(); - StagingRoomMap::iterator srmIt = srm->find(selectedID); - if (srmIt != srm->end()) - { - GameSpyStagingRoom *theRoom = srmIt->second; - if (!theRoom) - break; - const LadderInfo *linfo = TheLadderList->findLadder(theRoom->getLadderIP(), theRoom->getLadderPort()); - if (linfo) - { - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCGameDetailsMenu.wnd")); - if (!rcLayout) - break; - - GadgetListBoxSetSelected(control, rc->pos); - - rcMenu = rcLayout->getFirstWindow(); - rcMenu->winGetLayout()->runInit(); - rcMenu->winBringToTop(); - rcMenu->winHide(FALSE); - rcMenu->winSetPosition(rc->mouseX, rc->mouseY); - - rcMenu->winSetUserData((void *)selectedID); - TheWindowManager->winSetLoneWindow(rcMenu); - } - } - } - } - break; - } - -// //--------------------------------------------------------------------------------------------- -// case GSM_SLIDER_TRACK: -// { -// if (buttonPushed) -// break; -// -// GameWindow *control = (GameWindow *)mData1; -// Int val = (Int)mData2; -// Int controlID = control->winGetWindowId(); -// if (controlID == sliderChatAdjustID) -// { -// doSliderTrack(control, val); -// } -// break; -// } - - //--------------------------------------------------------------------------------------------- - case GEM_EDIT_DONE: - { - if (buttonPushed) - break; - - // read the user's input and clear the entry box - UnicodeString txtInput; - txtInput.set(GadgetTextEntryGetText( textEntryChat )); - GadgetTextEntrySetText(textEntryChat, UnicodeString::TheEmptyString); - txtInput.trim(); - if (!txtInput.isEmpty()) - { - // Send the message - if (!handleLobbySlashCommands(txtInput)) - { - TheGameSpyInfo->sendChat( txtInput, false, listboxLobbyPlayers ); - } - } - break; - } - - //--------------------------------------------------------------------------------------------- - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLLobbyMenuSystem diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLocaleSelectPopup.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLocaleSelectPopup.cpp deleted file mode 100644 index 6d088b5c00b..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLocaleSelectPopup.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLLocaleSelectPopup.cpp -// Author: Matt Campbell, December 2001 -// Description: WOL locale select popup -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "GameClient/GameText.h" -#include "Common/CustomMatchPreferences.h" -#include "Common/GameEngine.h" -#include "Common/GameSpyMiscPreferences.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetListBox.h" -#include "Common/GlobalData.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PersistentStorageDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentLocaleSelectID = NAMEKEY_INVALID; -static NameKeyType buttonOkID = NAMEKEY_INVALID; -static NameKeyType listboxLocaleID = NAMEKEY_INVALID; - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentLocaleSelect = NULL; -static GameWindow *buttonOk = NULL; -static GameWindow *listboxLocale = NULL; - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Status Menu */ -//------------------------------------------------------------------------------------------------- -void WOLLocaleSelectInit( WindowLayout *layout, void *userData ) -{ - parentLocaleSelectID = TheNameKeyGenerator->nameToKey( AsciiString( "PopupLocaleSelect.wnd:ParentLocaleSelect" ) ); - buttonOkID = TheNameKeyGenerator->nameToKey( AsciiString( "PopupLocaleSelect.wnd:ButtonOk" ) ); - listboxLocaleID = TheNameKeyGenerator->nameToKey( AsciiString( "PopupLocaleSelect.wnd:ListBoxLocaleSelect" ) ); - parentLocaleSelect = TheWindowManager->winGetWindowFromId( NULL, parentLocaleSelectID ); - buttonOk = TheWindowManager->winGetWindowFromId( NULL, buttonOkID); - listboxLocale = TheWindowManager->winGetWindowFromId( NULL, listboxLocaleID); - - for (int i=LOC_MIN; i<=LOC_MAX; ++i) - { - AsciiString id; - id.format("WOL:Locale%2.2d", i); - GadgetListBoxAddEntryText(listboxLocale, TheGameText->fetch(id.str()), GameSpyColor[GSCOLOR_DEFAULT], -1, -1); - } - GadgetListBoxSetSelected(listboxLocale, 0); - - // Show Menu - layout->hide( FALSE ); - - // Set Keyboard to Main Parent - TheWindowManager->winSetFocus( parentLocaleSelect ); - TheWindowManager->winSetModal( parentLocaleSelect ); -} // WOLLocaleSelectInit - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLLocaleSelectShutdown( WindowLayout *layout, void *userData ) -{ - - // hide menu - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout ); - -} // WOLLocaleSelectShutdown - - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLLocaleSelectUpdate( WindowLayout * layout, void *userData) -{ - -}// WOLLocaleSelectUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLLocaleSelectInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { -// UnsignedByte key = mData1; -// UnsignedByte state = mData2; - - // ---------------------------------------------------------------------------------------- - // don't let key fall through anywhere else - return MSG_HANDLED; - } // end char - } // end switch( msg ) - return MSG_IGNORED; -}// WOLLocaleSelectInput - -//Int getRegistryNicknameOffset(AsciiString nick); /// @todo: mdc remove this once we can save ini pref files -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLLocaleSelectSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - - switch( msg ) - { - - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - case GBM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if ( controlID == buttonOkID ) - { - int selected; - GadgetListBoxGetSelected(listboxLocale, &selected); - if (selected < 0) - return MSG_HANDLED; // can't select nothing! - PSRequest psReq; - psReq.requestType = PSRequest::PSREQUEST_UPDATEPLAYERLOCALE; - psReq.player.locale = selected + LOC_MIN; - psReq.email = TheGameSpyInfo->getLocalEmail().str(); - psReq.nick = TheGameSpyInfo->getLocalBaseName().str(); - psReq.password = TheGameSpyInfo->getLocalPassword().str(); - psReq.player.id = TheGameSpyInfo->getLocalProfileID(); - - TheGameSpyPSMessageQueue->addRequest(psReq); - GameSpyCloseOverlay(GSOVERLAY_LOCALESELECT); - - GameSpyMiscPreferences cPref; - cPref.setLocale(psReq.player.locale); - cPref.write(); - - PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(TheGameSpyInfo->getLocalProfileID()); - stats.locale = psReq.player.locale; - if (stats.id == TheGameSpyInfo->getLocalProfileID()) - TheGameSpyPSMessageQueue->trackPlayerStats(stats); - - if(stats.id == 0) - { - stats = TheGameSpyInfo->getCachedLocalPlayerStats(); - stats.locale = psReq.player.locale; - TheGameSpyInfo->setCachedLocalPlayerStats(stats); - } - else - { - // force an update of our shtuff - PSResponse newResp; - newResp.responseType = PSResponse::PSRESPONSE_PLAYERSTATS; - newResp.player = TheGameSpyPSMessageQueue->findPlayerStatsByID(TheGameSpyInfo->getLocalProfileID()); - TheGameSpyPSMessageQueue->addResponse(newResp); - } - CheckReOpenPlayerInfo(); - } //if ( controlID == buttonDisconnect ) - break; - }// case GBM_SELECTED: - - case GEM_EDIT_DONE: - { - break; - } - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLLocaleSelectSystem diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp deleted file mode 100644 index f60e693e50e..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp +++ /dev/null @@ -1,1511 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLLoginMenu.cpp -// Author: Chris Huybregts, November 2001 -// Description: Lan Lobby Menu -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/STLTypedefs.h" - -#include "Common/File.h" -#include "Common/FileSystem.h" -#include "Common/GameEngine.h" -#include "Common/GameSpyMiscPreferences.h" -#include "Common/QuotedPrintable.h" -#include "Common/Registry.h" -#include "Common/UserPreferences.h" -#include "GameClient/AnimateWindowManager.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/GameText.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetComboBox.h" -#include "GameClient/GadgetCheckBox.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/MessageBox.h" -#include "GameClient/ShellHooks.h" -#include "GameClient/GameWindowTransitions.h" - -#include "GameNetwork/GameSpy/GSConfig.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PingThread.h" -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/ThreadUtils.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" - -#include "GameNetwork/GameSpyOverlay.h" - - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -#ifdef ALLOW_NON_PROFILED_LOGIN -Bool GameSpyUseProfiles = false; -#endif // ALLOW_NON_PROFILED_LOGIN - - -static Bool isShuttingDown = false; -static Bool buttonPushed = false; -static char *nextScreen = NULL; - -static const UnsignedInt loginTimeoutInMS = 10000; -static UnsignedInt loginAttemptTime = 0; - -class GameSpyLoginPreferences : public UserPreferences -{ -public: - GameSpyLoginPreferences() { m_emailPasswordMap.clear(); m_emailNickMap.clear(); } - virtual ~GameSpyLoginPreferences() { m_emailPasswordMap.clear(); m_emailNickMap.clear(); } - - virtual Bool load(AsciiString fname); - virtual Bool write(void); - - AsciiString getPasswordForEmail( AsciiString email ); - AsciiString getDateForEmail( AsciiString email, AsciiString &month, AsciiString &date, AsciiString &year ); - AsciiStringList getNicksForEmail( AsciiString email ); - void addLogin( AsciiString email, AsciiString nick, AsciiString password, AsciiString date ); - void forgetLogin( AsciiString email ); - AsciiStringList getEmails( void ); - -private: - typedef std::map PassMap; - typedef std::map DateMap; - typedef std::map NickMap; - PassMap m_emailPasswordMap; - NickMap m_emailNickMap; - DateMap m_emailDateMap; -}; - -static AsciiString obfuscate( AsciiString in ) -{ - char *buf = NEW char[in.getLength() + 1]; - strcpy(buf, in.str()); - static const char *xor = "1337Munkee"; - char *c = buf; - const char *c2 = xor; - while (*c) - { - if (!*c2) - c2 = xor; - if (*c != *c2) - *c = *c++ ^ *c2++; - else - c++, c2++; - } - AsciiString out = buf; - delete buf; - return out; -} - -Bool GameSpyLoginPreferences::load( AsciiString fname ) -{ - if (!UserPreferences::load(fname)) - return false; - - UserPreferences::iterator upIt = begin(); - while (upIt != end()) - { - AsciiString key = upIt->first; - if (key.startsWith("pass_")) - { - AsciiString email, pass; - email = key.str() + 5; - pass = upIt->second; - - AsciiString quoPass = QuotedPrintableToAsciiString(pass); - pass = obfuscate(quoPass); - - m_emailPasswordMap[email] = pass; - } - if (key.startsWith("date_")) - { - AsciiString email, date; - email = key.str() + 5; - date = upIt->second; - - date = QuotedPrintableToAsciiString(date); - - m_emailDateMap[email] = date; - } - else if (key.startsWith("nick_")) - { - AsciiString email, nick, nicks; - email = key.str() + 5; - nicks = upIt->second; - while (nicks.nextToken(&nick, ",")) - { - m_emailNickMap[email].push_back(nick); - } - } - ++upIt; - } - - return true; -} - -Bool GameSpyLoginPreferences::write( void ) -{ - if (m_filename.isEmpty()) - return false; - - FILE *fp = fopen(m_filename.str(), "w"); - if (fp) - { - fprintf(fp, "lastEmail = %s\n", ((*this)["lastEmail"].str())); - fprintf(fp, "lastName = %s\n", ((*this)["lastName"].str())); - fprintf(fp, "useProfiles = %s\n", ((*this)["useProfiles"].str())); - PassMap::iterator passIt = m_emailPasswordMap.begin(); - while (passIt != m_emailPasswordMap.end()) - { - AsciiString pass = obfuscate(passIt->second); - AsciiString quoPass = AsciiStringToQuotedPrintable(pass); - - fprintf(fp, "pass_%s = %s\n", passIt->first.str(), quoPass.str()); - ++passIt; - } - - PassMap::iterator dateIt = m_emailDateMap.begin(); - while (dateIt != m_emailDateMap.end()) - { - AsciiString date = AsciiStringToQuotedPrintable(dateIt->second); - - fprintf(fp, "date_%s = %s\n", dateIt->first.str(), date.str()); - ++dateIt; - } - - NickMap::iterator nickIt = m_emailNickMap.begin(); - while (nickIt != m_emailNickMap.end()) - { - AsciiString nicks; - AsciiStringListIterator listIt = nickIt->second.begin(); - while (listIt != nickIt->second.end()) - { - nicks.concat(*listIt); - nicks.concat(','); - ++listIt; - } - fprintf(fp, "nick_%s = %s\n", nickIt->first.str(), nicks.str()); - ++nickIt; - } - - fclose(fp); - return true; - } - return false; -} -AsciiString GameSpyLoginPreferences::getDateForEmail( AsciiString email, AsciiString &month, AsciiString &date, AsciiString &year ) -{ - if ( m_emailDateMap.find(email) == m_emailDateMap.end() ) - return AsciiString::TheEmptyString; - AsciiString fullDate = m_emailDateMap[email]; - if(fullDate.getLength() != 8) - return AsciiString::TheEmptyString; - month.format("%c%c", fullDate.getCharAt(0), fullDate.getCharAt(1)); - date.format("%c%c", fullDate.getCharAt(2), fullDate.getCharAt(3)); - year.format("%c%c%c%c", fullDate.getCharAt(4), fullDate.getCharAt(5), fullDate.getCharAt(6), fullDate.getCharAt(7)); - return m_emailDateMap[email]; -} - -AsciiString GameSpyLoginPreferences::getPasswordForEmail( AsciiString email ) -{ - if ( m_emailPasswordMap.find(email) == m_emailPasswordMap.end() ) - return AsciiString::TheEmptyString; - return m_emailPasswordMap[email]; -} - -AsciiStringList GameSpyLoginPreferences::getNicksForEmail( AsciiString email ) -{ - if ( m_emailNickMap.find(email) == m_emailNickMap.end() ) - { - AsciiStringList empty; - return empty; - } - return m_emailNickMap[email]; -} - -void GameSpyLoginPreferences::addLogin( AsciiString email, AsciiString nick, AsciiString password, AsciiString date ) -{ - if ( std::find(m_emailNickMap[email].begin(), m_emailNickMap[email].end(), nick) == m_emailNickMap[email].end() ) - m_emailNickMap[email].push_back(nick); - m_emailPasswordMap[email] = password; - m_emailDateMap[email] = date; -} - -void GameSpyLoginPreferences::forgetLogin( AsciiString email ) -{ - m_emailNickMap.erase(email); - m_emailPasswordMap.erase(email); - m_emailDateMap.erase(email); - -} - -AsciiStringList GameSpyLoginPreferences::getEmails( void ) -{ - AsciiStringList theList; - NickMap::iterator it = m_emailNickMap.begin(); - while (it != m_emailNickMap.end()) - { - theList.push_back(it->first); - ++it; - } - return theList; -} - -static const char *PREF_FILENAME = "GameSpyLogin.ini"; -static GameSpyLoginPreferences *loginPref = NULL; - -static void startPings( void ) -{ - std::list pingServers = TheGameSpyConfig->getPingServers(); - Int timeout = TheGameSpyConfig->getPingTimeoutInMs(); - Int reps = TheGameSpyConfig->getNumPingRepetitions(); - - for (std::list::const_iterator it = pingServers.begin(); it != pingServers.end(); ++it) - { - AsciiString pingServer = *it; - PingRequest req; - req.hostname = pingServer.str(); - req.repetitions = reps; - req.timeout = timeout; - ThePinger->addRequest(req); - } -} - -//------------------------------------------------------------------------------------------------- -/** This is called when a shutdown is complete for this menu */ -//------------------------------------------------------------------------------------------------- -static void shutdownComplete( WindowLayout *layout ) -{ - - isShuttingDown = false; - - // hide the layout - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout, (nextScreen != NULL) ); - - if (nextScreen != NULL) - { - if (loginPref) - { - loginPref->write(); - delete loginPref; - loginPref = NULL; - } - TheShell->push(nextScreen); - } - else - { - DEBUG_ASSERTCRASH(loginPref != NULL, ("loginPref == NULL")); - if (loginPref) - { - loginPref->write(); - delete loginPref; - loginPref = NULL; - } - } - - nextScreen = NULL; - -} // end if - - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentWOLLoginID = NAMEKEY_INVALID; -static NameKeyType buttonBackID = NAMEKEY_INVALID; // profile, quick -static NameKeyType buttonLoginID = NAMEKEY_INVALID; // profile, quick -static NameKeyType buttonCreateAccountID = NAMEKEY_INVALID; // profile, quick -static NameKeyType buttonUseAccountID = NAMEKEY_INVALID; // quick -static NameKeyType buttonDontUseAccountID = NAMEKEY_INVALID; // profile -static NameKeyType buttonTOSID = NAMEKEY_INVALID; // TOS -static NameKeyType parentTOSID = NAMEKEY_INVALID; // TOS Parent -static NameKeyType buttonTOSOKID = NAMEKEY_INVALID; // TOS -static NameKeyType listboxTOSID = NAMEKEY_INVALID; // TOS -static NameKeyType comboBoxEmailID = NAMEKEY_INVALID; // profile -static NameKeyType comboBoxLoginNameID = NAMEKEY_INVALID; // profile -static NameKeyType textEntryLoginNameID = NAMEKEY_INVALID; // quick -static NameKeyType textEntryPasswordID = NAMEKEY_INVALID; // profile -static NameKeyType checkBoxRememberPasswordID = NAMEKEY_INVALID; // checkbox to remember information or not -static NameKeyType textEntryMonthID = NAMEKEY_INVALID; // profile -static NameKeyType textEntryDayID = NAMEKEY_INVALID; // profile -static NameKeyType textEntryYearID = NAMEKEY_INVALID; // profile - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentWOLLogin = NULL; -static GameWindow *buttonBack = NULL; -static GameWindow *buttonLogin = NULL; -static GameWindow *buttonCreateAccount = NULL; -static GameWindow *buttonUseAccount = NULL; -static GameWindow *buttonDontUseAccount = NULL; -static GameWindow *buttonTOS = NULL; -static GameWindow *parentTOS = NULL; -static GameWindow *buttonTOSOK = NULL; -static GameWindow *listboxTOS = NULL; -static GameWindow *comboBoxEmail = NULL; -static GameWindow *comboBoxLoginName = NULL; -static GameWindow *textEntryLoginName = NULL; -static GameWindow *textEntryPassword = NULL; -static GameWindow *checkBoxRememberPassword = NULL; -static GameWindow *textEntryMonth = NULL; -static GameWindow *textEntryDay = NULL; -static GameWindow *textEntryYear = NULL; - -void EnableLoginControls( Bool state ) -{ - if (buttonLogin) - buttonLogin->winEnable(state); - if (buttonCreateAccount) - buttonCreateAccount->winEnable(state); - if (buttonUseAccount) - buttonUseAccount->winEnable(state); - if (buttonDontUseAccount) - buttonDontUseAccount->winEnable(state); - if (comboBoxEmail) - comboBoxEmail->winEnable(state); - if (comboBoxLoginName) - comboBoxLoginName->winEnable(state); - if (textEntryLoginName) - textEntryLoginName->winEnable(state); - if (textEntryPassword) - textEntryPassword->winEnable(state); - if (checkBoxRememberPassword) - checkBoxRememberPassword->winEnable(state); - if( buttonTOS ) - buttonTOS->winEnable(state); - - if (textEntryMonth) - textEntryMonth->winEnable(state); - if (textEntryDay) - textEntryDay->winEnable(state); - if( textEntryYear ) - textEntryYear->winEnable(state); -} - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Login Menu */ -//------------------------------------------------------------------------------------------------- -void WOLLoginMenuInit( WindowLayout *layout, void *userData ) -{ - nextScreen = NULL; - buttonPushed = false; - isShuttingDown = false; - loginAttemptTime = 0; - - if (!loginPref) - { - loginPref = NEW GameSpyLoginPreferences; - loginPref->load(PREF_FILENAME); - } - - // if the ESRB warning is blank (other country) hide the box - GameWindow *esrbTitle = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("GameSpyLoginProfile.wnd:StaticTextESRBTop") ); - GameWindow *esrbParent = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("GameSpyLoginProfile.wnd:ParentESRB") ); - if (esrbTitle && esrbParent) - { - if ( GadgetStaticTextGetText( esrbTitle ).getLength() < 2 ) - { - esrbParent->winHide(TRUE); - } - } - - parentWOLLoginID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:WOLLoginMenuParent" ); - buttonBackID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ButtonBack" ); - buttonLoginID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ButtonLogin" ); - buttonCreateAccountID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ButtonCreateAccount" ); - buttonUseAccountID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ButtonUseAccount" ); - buttonDontUseAccountID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ButtonDontUseAccount" ); - buttonTOSID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ButtonTOS" ); - parentTOSID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ParentTOS" ); - buttonTOSOKID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ButtonTOSOK" ); - listboxTOSID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ListboxTOS" ); - comboBoxEmailID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ComboBoxEmail" ); - comboBoxLoginNameID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ComboBoxLoginName" ); - textEntryLoginNameID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:TextEntryLoginName" ); - textEntryPasswordID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:TextEntryPassword" ); - checkBoxRememberPasswordID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:CheckBoxRememberInfo" ); - textEntryMonthID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:TextEntryMonth" ); - textEntryDayID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:TextEntryDay" ); - textEntryYearID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:TextEntryYear" ); - - parentWOLLogin = TheWindowManager->winGetWindowFromId( NULL, parentWOLLoginID ); - buttonBack = TheWindowManager->winGetWindowFromId( NULL, buttonBackID); - buttonLogin = TheWindowManager->winGetWindowFromId( NULL, buttonLoginID); - buttonCreateAccount = TheWindowManager->winGetWindowFromId( NULL, buttonCreateAccountID); - buttonUseAccount = TheWindowManager->winGetWindowFromId( NULL, buttonUseAccountID); - buttonDontUseAccount = TheWindowManager->winGetWindowFromId( NULL, buttonDontUseAccountID); - buttonTOS = TheWindowManager->winGetWindowFromId( NULL, buttonTOSID); - parentTOS = TheWindowManager->winGetWindowFromId( NULL, parentTOSID); - buttonTOSOK = TheWindowManager->winGetWindowFromId( NULL, buttonTOSOKID); - listboxTOS = TheWindowManager->winGetWindowFromId( NULL, listboxTOSID); - comboBoxEmail = TheWindowManager->winGetWindowFromId( NULL, comboBoxEmailID); - comboBoxLoginName = TheWindowManager->winGetWindowFromId( NULL, comboBoxLoginNameID); - textEntryLoginName = TheWindowManager->winGetWindowFromId( NULL, textEntryLoginNameID); - textEntryPassword = TheWindowManager->winGetWindowFromId( NULL, textEntryPasswordID); - checkBoxRememberPassword = TheWindowManager->winGetWindowFromId( NULL, checkBoxRememberPasswordID); - textEntryMonth = TheWindowManager->winGetWindowFromId( NULL, textEntryMonthID); - textEntryDay = TheWindowManager->winGetWindowFromId( NULL, textEntryDayID); - textEntryYear = TheWindowManager->winGetWindowFromId( NULL, textEntryYearID); - - GadgetTextEntrySetText(textEntryMonth, UnicodeString::TheEmptyString); - - GadgetTextEntrySetText(textEntryDay, UnicodeString::TheEmptyString); - - GadgetTextEntrySetText(textEntryYear, UnicodeString::TheEmptyString); - - - - GameWindowList tabList; - tabList.push_front(comboBoxEmail); - tabList.push_back(comboBoxLoginName); - tabList.push_back(textEntryPassword); - tabList.push_back(textEntryMonth); - tabList.push_back(textEntryDay); - tabList.push_back(textEntryYear); - tabList.push_back(checkBoxRememberPassword); - tabList.push_back(buttonLogin); - tabList.push_back(buttonCreateAccount); - tabList.push_back(buttonTOS); - tabList.push_back(buttonBack); - TheWindowManager->clearTabList(); - TheWindowManager->registerTabList(tabList); - TheWindowManager->winSetFocus( comboBoxEmail ); - // short form or long form? -#ifdef ALLOW_NON_PROFILED_LOGIN - if (parentWOLLogin) - { - GameSpyUseProfiles = true; -#endif // ALLOW_NON_PROFILED_LOGIN - - DEBUG_ASSERTCRASH(buttonBack, ("buttonBack missing!")); - DEBUG_ASSERTCRASH(buttonLogin, ("buttonLogin missing!")); - DEBUG_ASSERTCRASH(buttonCreateAccount, ("buttonCreateAccount missing!")); - //DEBUG_ASSERTCRASH(buttonDontUseAccount, ("buttonDontUseAccount missing!")); - DEBUG_ASSERTCRASH(comboBoxEmail, ("comboBoxEmail missing!")); - DEBUG_ASSERTCRASH(comboBoxLoginName, ("comboBoxLoginName missing!")); - DEBUG_ASSERTCRASH(textEntryPassword, ("textEntryPassword missing!")); - - //TheShell->registerWithAnimateManager(parentWOLLogin, WIN_ANIMATION_SLIDE_TOP, TRUE); - /**/ -// TheShell->registerWithAnimateManager(buttonTOS, WIN_ANIMATION_SLIDE_BOTTOM, TRUE); - //TheShell->registerWithAnimateManager(buttonCreateAccount, WIN_ANIMATION_SLIDE_LEFT, TRUE); - //TheShell->registerWithAnimateManager(buttonDontUseAccount, WIN_ANIMATION_SLIDE_LEFT, TRUE); -// TheShell->registerWithAnimateManager(buttonBack, WIN_ANIMATION_SLIDE_BOTTOM, TRUE); - /**/ -#ifdef ALLOW_NON_PROFILED_LOGIN - } - else - { - GameSpyUseProfiles = false; - - parentWOLLoginID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:WOLLoginMenuParent" ); - buttonBackID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ButtonBack" ); - buttonLoginID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ButtonLogin" ); - buttonCreateAccountID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ButtonCreateAccount" ); - buttonUseAccountID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ButtonUseAccount" ); - buttonDontUseAccountID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ButtonDontUseAccount" ); - buttonTOSID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ButtonTOS" ); - parentTOSID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ParentTOS" ); - buttonTOSOKID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ButtonTOSOK" ); - listboxTOSID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ListboxTOS" ); - comboBoxEmailID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ComboBoxEmail" ); - textEntryLoginNameID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:TextEntryLoginName" ); - textEntryPasswordID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:TextEntryPassword" ); - checkBoxRememberPasswordID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:CheckBoxRememberPassword" ); - - parentWOLLogin = TheWindowManager->winGetWindowFromId( NULL, parentWOLLoginID ); - buttonBack = TheWindowManager->winGetWindowFromId( NULL, buttonBackID); - buttonLogin = TheWindowManager->winGetWindowFromId( NULL, buttonLoginID); - buttonCreateAccount = TheWindowManager->winGetWindowFromId( NULL, buttonCreateAccountID); - buttonUseAccount = TheWindowManager->winGetWindowFromId( NULL, buttonUseAccountID); - buttonDontUseAccount = TheWindowManager->winGetWindowFromId( NULL, buttonDontUseAccountID); - comboBoxEmail = TheWindowManager->winGetWindowFromId( NULL, comboBoxEmailID); - buttonTOS = TheWindowManager->winGetWindowFromId( NULL, buttonTOSID); - parentTOS = TheWindowManager->winGetWindowFromId( NULL, parentTOSID); - buttonTOSOK = TheWindowManager->winGetWindowFromId( NULL, buttonTOSOKID); - listboxTOS = TheWindowManager->winGetWindowFromId( NULL, listboxTOSID); - textEntryLoginName = TheWindowManager->winGetWindowFromId( NULL, textEntryLoginNameID); - textEntryPassword = TheWindowManager->winGetWindowFromId( NULL, textEntryPasswordID); - checkBoxRememberPassword = TheWindowManager->winGetWindowFromId( NULL, checkBoxRememberPasswordID); - - DEBUG_ASSERTCRASH(buttonBack, ("buttonBack missing!")); - DEBUG_ASSERTCRASH(buttonLogin, ("buttonLogin missing!")); - DEBUG_ASSERTCRASH(buttonCreateAccount, ("buttonCreateAccount missing!")); - DEBUG_ASSERTCRASH(buttonUseAccount, ("buttonUseAccount missing!")); - DEBUG_ASSERTCRASH(textEntryLoginName, ("textEntryLoginName missing!")); - TheWindowManager->winSetFocus( textEntryLoginName ); - //TheShell->registerWithAnimateManager(parentWOLLogin, WIN_ANIMATION_SLIDE_TOP, TRUE); - -// TheShell->registerWithAnimateManager(buttonTOS, WIN_ANIMATION_SLIDE_LEFT, TRUE); -// TheShell->registerWithAnimateManager(buttonCreateAccount, WIN_ANIMATION_SLIDE_LEFT, TRUE); -// TheShell->registerWithAnimateManager(buttonUseAccount, WIN_ANIMATION_SLIDE_LEFT, TRUE); -// TheShell->registerWithAnimateManager(buttonBack, WIN_ANIMATION_SLIDE_RIGHT, TRUE); - - } -#endif // ALLOW_NON_PROFILED_LOGIN - - -#ifdef ALLOW_NON_PROFILED_LOGIN - if (GameSpyUseProfiles) - { -#endif // ALLOW_NON_PROFILED_LOGIN - // Read login names from registry... - GadgetComboBoxReset(comboBoxEmail); - GadgetTextEntrySetText(textEntryPassword, UnicodeString.TheEmptyString); - - // look for cached nicks to add - AsciiString lastName; - AsciiString lastEmail; - Bool markCheckBox = FALSE; - UserPreferences::const_iterator it = loginPref->find("lastName"); - if (it != loginPref->end()) - { - lastName = it->second; - } - it = loginPref->find("lastEmail"); - if (it != loginPref->end()) - { - lastEmail = it->second; - } - - // fill in list of Emails, and select the most recent - AsciiStringList cachedEmails = loginPref->getEmails(); - AsciiStringListIterator eIt = cachedEmails.begin(); - Int selectedPos = -1; - while (eIt != cachedEmails.end()) - { - UnicodeString uniEmail; - uniEmail.translate(*eIt); - Int pos = GadgetComboBoxAddEntry(comboBoxEmail, uniEmail, GameSpyColor[GSCOLOR_DEFAULT]); - if (*eIt == lastEmail) - selectedPos = pos; - - ++eIt; - } - if (selectedPos >= 0) - { - GadgetComboBoxSetSelectedPos(comboBoxEmail, selectedPos); - - // fill in the password for the selected email - UnicodeString pass; - pass.translate(loginPref->getPasswordForEmail(lastEmail)); - GadgetTextEntrySetText(textEntryPassword, pass); - - AsciiString month,day,year; - loginPref->getDateForEmail(lastEmail, month, day, year); - pass.translate(month); - GadgetTextEntrySetText(textEntryMonth, pass); - pass.translate(day); - GadgetTextEntrySetText(textEntryDay, pass); - pass.translate(year); - GadgetTextEntrySetText(textEntryYear, pass); - - markCheckBox = TRUE; - } - - // fill in list of nicks for selected email, selecting the most recent - GadgetComboBoxReset(comboBoxLoginName); - AsciiStringList cachedNicks = loginPref->getNicksForEmail(lastEmail); - AsciiStringListIterator nIt = cachedNicks.begin(); - selectedPos = -1; - while (nIt != cachedNicks.end()) - { - UnicodeString uniNick; - uniNick.translate(*nIt); - Int pos = GadgetComboBoxAddEntry(comboBoxLoginName, uniNick, GameSpyColor[GSCOLOR_DEFAULT]); - if (*nIt == lastName) - selectedPos = pos; - - ++nIt; - } - if (selectedPos >= 0) - { - GadgetComboBoxSetSelectedPos(comboBoxLoginName, selectedPos); - markCheckBox = TRUE; - } - // always start with not storing information - if( markCheckBox) - GadgetCheckBoxSetChecked(checkBoxRememberPassword, TRUE); - else - GadgetCheckBoxSetChecked(checkBoxRememberPassword, FALSE); -#ifdef ALLOW_NON_PROFILED_LOGIN - } - else - { - // Read login names from registry... - GadgetComboBoxReset(comboBoxLoginName); - UnicodeString nick; - - UserPreferences::const_iterator it = loginPref->find("lastName"); - if (it != loginPref->end()) - { - nick.translate(it->second); - } - else - { - char userBuf[32] = ""; - unsigned long bufSize = 32; - GetUserName(userBuf, &bufSize); - nick.translate(userBuf); - } - - GadgetTextEntrySetText(textEntryLoginName, nick); - } -#endif // ALLOW_NON_PROFILED_LOGIN - - EnableLoginControls(TRUE); - - // Show Menu - layout->hide( FALSE ); - - // Set Keyboard to Main Parent - - RaiseGSMessageBox(); - - OptionPreferences optionPref; - if (!optionPref.getBool("SawTOS", TRUE)) - { - TheWindowManager->winSendSystemMsg( parentWOLLogin, GBM_SELECTED, - (WindowMsgData)buttonTOS, buttonTOSID ); - } - TheTransitionHandler->setGroup("GameSpyLoginProfileFade"); - -} // WOLLoginMenuInit - -//------------------------------------------------------------------------------------------------- -/** WOL Login Menu shutdown method */ -//------------------------------------------------------------------------------------------------- -static Bool loggedInOK = false; -void WOLLoginMenuShutdown( WindowLayout *layout, void *userData ) -{ - isShuttingDown = true; - loggedInOK = false; - TheWindowManager->clearTabList(); - - // if we are shutting down for an immediate pop, skip the animations - Bool popImmediate = *(Bool *)userData; - if( popImmediate ) - { - - shutdownComplete( layout ); - return; - - } //end if - - TheShell->reverseAnimatewindow(); - TheTransitionHandler->reverse("GameSpyLoginProfileFade"); - -} // WOLLoginMenuShutdown - - -// this is used to check if we've got all the pings -static void checkLogin( void ) -{ - if (loggedInOK && ThePinger && !ThePinger->arePingsInProgress()) - { - // save off our ping string, and end those threads - AsciiString pingStr = ThePinger->getPingString( 1000 ); - DEBUG_LOG(("Ping string is %s\n", pingStr.str())); - TheGameSpyInfo->setPingString(pingStr); - //delete ThePinger; - //ThePinger = NULL; - - buttonPushed = true; - loggedInOK = false; // don't try this again - - loginAttemptTime = 0; - - // start looking for group rooms - TheGameSpyInfo->clearGroupRoomList(); - - SignalUIInteraction(SHELL_SCRIPT_HOOK_GENERALS_ONLINE_LOGIN); - nextScreen = "Menus/WOLWelcomeMenu.wnd"; - TheShell->pop(); - - // read in some cached data - GameSpyMiscPreferences mPref; - PSPlayerStats localPSStats = GameSpyPSMessageQueueInterface::parsePlayerKVPairs(mPref.getCachedStats().str()); - localPSStats.id = TheGameSpyInfo->getLocalProfileID(); - TheGameSpyInfo->setCachedLocalPlayerStats(localPSStats); -// TheGameSpyPSMessageQueue->trackPlayerStats(localPSStats); - - // and push the info around to other players -// PSResponse newResp; -// newResp.responseType = PSResponse::PSRESPONSE_PLAYERSTATS; -// newResp.player = localPSStats; -// TheGameSpyPSMessageQueue->addResponse(newResp); - } -} - -//------------------------------------------------------------------------------------------------- -/** WOL Login Menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLLoginMenuUpdate( WindowLayout * layout, void *userData) -{ - - // We'll only be successful if we've requested to - if(isShuttingDown && TheShell->isAnimFinished() && TheTransitionHandler->isFinished()) - shutdownComplete(layout); - - if (TheShell->isAnimFinished() && !buttonPushed && TheGameSpyPeerMessageQueue) - { - PingResponse pingResp; - if (ThePinger && ThePinger->getResponse(pingResp)) - { - checkLogin(); - } - - PeerResponse resp; - if (!loggedInOK && TheGameSpyPeerMessageQueue->getResponse( resp )) - { - switch (resp.peerResponseType) - { - case PeerResponse::PEERRESPONSE_GROUPROOM: - { - GameSpyGroupRoom room; - room.m_groupID = resp.groupRoom.id; - room.m_maxWaiting = resp.groupRoom.maxWaiting; - room.m_name = resp.groupRoomName.c_str(); - room.m_translatedName = UnicodeString(L"TEST"); - room.m_numGames = resp.groupRoom.numGames; - room.m_numPlaying = resp.groupRoom.numPlaying; - room.m_numWaiting = resp.groupRoom.numWaiting; - TheGameSpyInfo->addGroupRoom( room ); - } - break; - case PeerResponse::PEERRESPONSE_LOGIN: - { - loggedInOK = true; - - // fetch our player info - TheGameSpyInfo->setLocalName( resp.nick.c_str() ); - TheGameSpyInfo->setLocalProfileID( resp.player.profileID ); - TheGameSpyInfo->loadSavedIgnoreList(); - TheGameSpyInfo->setLocalIPs(resp.player.internalIP, resp.player.externalIP); - TheGameSpyInfo->readAdditionalDisconnects(); - //TheGameSpyInfo->setLocalEmail( resp.player.email ); - //TheGameSpyInfo->setLocalPassword( resp) - - GameSpyMiscPreferences miscPref; - TheGameSpyInfo->setMaxMessagesPerUpdate(miscPref.getMaxMessagesPerUpdate()); - } - break; - case PeerResponse::PEERRESPONSE_DISCONNECT: - { - loginAttemptTime = 0; - UnicodeString title, body; - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", resp.discon.reason); - title = TheGameText->fetch( "GUI:GSErrorTitle" ); - body = TheGameText->fetch( disconMunkee ); - GSMessageBoxOk( title, body ); - EnableLoginControls( TRUE ); - - // kill & restart the threads - AsciiString motd = TheGameSpyInfo->getMOTD(); - AsciiString config = TheGameSpyInfo->getConfig(); - DEBUG_LOG(("Tearing down GameSpy from WOLLoginMenuUpdate(PEERRESPONSE_DISCONNECT)\n")); - TearDownGameSpy(); - SetUpGameSpy( motd.str(), config.str() ); - } - break; - } - } - - checkLogin(); - } - - if (TheGameSpyInfo && !buttonPushed && loginAttemptTime && (loginAttemptTime + loginTimeoutInMS < timeGetTime())) - { - // timed out a login attempt, so say so - loginAttemptTime = 0; - UnicodeString title, body; - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason4"); // ("could not connect to server") - title = TheGameText->fetch( "GUI:GSErrorTitle" ); - body = TheGameText->fetch( disconMunkee ); - GSMessageBoxOk( title, body ); - EnableLoginControls( TRUE ); - - // kill & restart the threads - AsciiString motd = TheGameSpyInfo->getMOTD(); - AsciiString config = TheGameSpyInfo->getConfig(); - DEBUG_LOG(("Tearing down GameSpy from WOLLoginMenuUpdate(login timeout)\n")); - TearDownGameSpy(); - SetUpGameSpy( motd.str(), config.str() ); - } - -}// WOLLoginMenuUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Login Menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLLoginMenuInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - if (buttonPushed) - break; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonBack, buttonBackID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// WOLLoginMenuInput - -static Bool isNickOkay(UnicodeString nick) -{ - static const WideChar * legalIRCChars = L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789[]`_^{|}-"; - - Int len = nick.getLength(); - if (len == 0) - return TRUE; - - if (len == 1 && nick.getCharAt(0) == L'-') - return FALSE; - - WideChar newChar = nick.getCharAt(len-1); - if (wcschr(legalIRCChars, newChar) == NULL) - return FALSE; - - return TRUE; -} - -static Bool isAgeOkay(AsciiString &month, AsciiString &day, AsciiString year) -{ - if(month.isEmpty() || day.isEmpty() || year.isEmpty() || year.getLength() != 4) - return FALSE; - - Int monthInt = atoi(month.str()); - Int dayInt = atoi(day.str()); - - if(monthInt > 12 || dayInt > 31) - return FALSE; - // setup date buffer for local region date format - month.format("%02.2d",monthInt); - day.format("%02.2d",dayInt); - - // test the year first - #define DATE_BUFFER_SIZE 256 - char dateBuffer[ DATE_BUFFER_SIZE ]; - GetDateFormat( LOCALE_SYSTEM_DEFAULT, - 0, NULL, - "yyyy", - dateBuffer, DATE_BUFFER_SIZE ); - Int sysVal = atoi(dateBuffer); - Int userVal = atoi(year.str()); - if(sysVal - userVal >= 14) - return TRUE; - else if( sysVal - userVal <= 12) - return FALSE; - - GetDateFormat( LOCALE_SYSTEM_DEFAULT, - 0, NULL, - "MM", - dateBuffer, DATE_BUFFER_SIZE ); - sysVal = atoi(dateBuffer); - userVal = atoi(month.str()); - if(sysVal - userVal >0 ) - return TRUE; - else if( sysVal -userVal < 0 ) - return FALSE; -// month.format("%02.2d",userVal); - GetDateFormat( LOCALE_SYSTEM_DEFAULT, - 0, NULL, - "dd", - dateBuffer, DATE_BUFFER_SIZE ); - sysVal = atoi(dateBuffer); - userVal = atoi(day.str()); - if(sysVal - userVal< 0) - return FALSE; -// day.format("%02.2d",userVal); - return TRUE; -} - -//------------------------------------------------------------------------------------------------- -/** WOL Login Menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLLoginMenuSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - - switch( msg ) - { - - - case GWM_CREATE: - { - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - // someone typed in a combo box. Clear password (or fill it in if the typed name matches a known login name) - case GCM_UPDATE_TEXT: - { - UnicodeString uNick = GadgetComboBoxGetText(comboBoxLoginName); - UnicodeString uEmail = GadgetComboBoxGetText(comboBoxEmail); - AsciiString nick, email; - nick.translate(uNick); - email.translate(uEmail); - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - UnicodeString trimmedNick = uNick, trimmedEmail = uEmail; - trimmedNick.trim(); - trimmedEmail.trim(); - if (!trimmedNick.isEmpty()) - { - if (trimmedNick.getCharAt(trimmedNick.getLength()-1) == L'\\') - trimmedNick.removeLastChar(); - if (trimmedNick.getCharAt(trimmedNick.getLength()-1) == L'/') - trimmedNick.removeLastChar(); - } - if (!trimmedEmail.isEmpty()) - { - if (trimmedEmail.getCharAt(trimmedEmail.getLength()-1) == L'\\') - trimmedEmail.removeLastChar(); - if (trimmedEmail.getCharAt(trimmedEmail.getLength()-1) == L'/') - trimmedEmail.removeLastChar(); - } - if (trimmedEmail.getLength() != uEmail.getLength()) - { - // we just trimmed a space. set the text back and bail - GadgetComboBoxSetText(comboBoxEmail, trimmedEmail); - break; - } - if (trimmedNick.getLength() != nick.getLength()) - { - // we just trimmed a space. set the text back and bail - GadgetComboBoxSetText(comboBoxLoginName, trimmedNick); - break; - } - - if (controlID == comboBoxEmailID) - { - // email changed. look up password, and choose new login names - - // fill in the password for the selected email - UnicodeString pass; - pass.translate(loginPref->getPasswordForEmail(email)); - GadgetTextEntrySetText(textEntryPassword, pass); - - // fill in list of nicks for selected email, selecting the first - AsciiStringList cachedNicks = loginPref->getNicksForEmail(email); - AsciiStringListIterator nIt = cachedNicks.begin(); - Int selectedPos = -1; - GadgetComboBoxReset(comboBoxLoginName); - while (nIt != cachedNicks.end()) - { - UnicodeString uniNick; - uniNick.translate(*nIt); - GadgetComboBoxAddEntry(comboBoxLoginName, uniNick, GameSpyColor[GSCOLOR_DEFAULT]); - selectedPos = 0; - ++nIt; - } - if (selectedPos >= 0) - { - GadgetComboBoxSetSelectedPos(comboBoxLoginName, selectedPos); - GadgetCheckBoxSetChecked(checkBoxRememberPassword, true); - AsciiString month,day,year; - loginPref->getDateForEmail(email, month, day, year); - pass.translate(month); - GadgetTextEntrySetText(textEntryMonth, pass); - pass.translate(day); - GadgetTextEntrySetText(textEntryDay, pass); - pass.translate(year); - GadgetTextEntrySetText(textEntryYear, pass); - - } - else - { - GadgetCheckBoxSetChecked(checkBoxRememberPassword, false); - GadgetTextEntrySetText(textEntryMonth, UnicodeString::TheEmptyString); - GadgetTextEntrySetText(textEntryDay, UnicodeString::TheEmptyString); - GadgetTextEntrySetText(textEntryYear, UnicodeString::TheEmptyString); - - } - } - else if (controlID == comboBoxLoginNameID) - { - // they typed a new login name. Email & pass shouldn't change - } - - break; - } - - case GCM_SELECTED: - { - if (buttonPushed) - break; - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if (controlID == comboBoxEmailID) - { - // email changed. look up password, and choose new login names - UnicodeString uEmail = GadgetComboBoxGetText(comboBoxEmail); - AsciiString email; - email.translate(uEmail); - - // fill in the password for the selected email - UnicodeString pass; - pass.translate(loginPref->getPasswordForEmail(email)); - GadgetTextEntrySetText(textEntryPassword, pass); - - // fill in list of nicks for selected email, selecting the first - AsciiStringList cachedNicks = loginPref->getNicksForEmail(email); - AsciiStringListIterator nIt = cachedNicks.begin(); - Int selectedPos = -1; - GadgetComboBoxReset(comboBoxLoginName); - while (nIt != cachedNicks.end()) - { - UnicodeString uniNick; - uniNick.translate(*nIt); - GadgetComboBoxAddEntry(comboBoxLoginName, uniNick, GameSpyColor[GSCOLOR_DEFAULT]); - selectedPos = 0; - ++nIt; - } - if (selectedPos >= 0) - { - GadgetComboBoxSetSelectedPos(comboBoxLoginName, selectedPos); - GadgetCheckBoxSetChecked(checkBoxRememberPassword, true); - AsciiString month,day,year; - loginPref->getDateForEmail(email, month, day, year); - pass.translate(month); - GadgetTextEntrySetText(textEntryMonth, pass); - pass.translate(day); - GadgetTextEntrySetText(textEntryDay, pass); - pass.translate(year); - GadgetTextEntrySetText(textEntryYear, pass); - - } - else - { - GadgetCheckBoxSetChecked(checkBoxRememberPassword, false); - GadgetTextEntrySetText(textEntryMonth, UnicodeString::TheEmptyString); - GadgetTextEntrySetText(textEntryDay, UnicodeString::TheEmptyString); - GadgetTextEntrySetText(textEntryYear, UnicodeString::TheEmptyString); - } - - } - else if (controlID == comboBoxLoginNameID) - { - // they typed a new login name. Email & pass shouldn't change - } - break; - } - - case GBM_SELECTED: - { - if (buttonPushed) - break; - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - // If we back out, just bail - we haven't gotten far enough to need to log out - if ( controlID == buttonBackID ) - { - buttonPushed = true; - TearDownGameSpy(); - TheShell->pop(); - } //if ( controlID == buttonBack ) -#ifdef ALLOW_NON_PROFILED_LOGIN - else if ( controlID == buttonUseAccountID ) - { - buttonPushed = true; - nextScreen = "Menus/GameSpyLoginProfile.wnd"; - TheShell->pop(); - //TheShell->push( "Menus/GameSpyLoginProfile.wnd" ); - } //if ( controlID == buttonUseAccount ) - else if ( controlID == buttonDontUseAccountID ) - { - buttonPushed = true; - nextScreen = "Menus/GameSpyLoginQuick.wnd"; - TheShell->pop(); - //TheShell->push( "Menus/GameSpyLoginQuick.wnd" ); - } //if ( controlID == buttonDontUseAccount ) -#endif // ALLOW_NON_PROFILED_LOGIN - else if ( controlID == buttonCreateAccountID ) - { -#ifdef ALLOW_NON_PROFILED_LOGIN - if (GameSpyUseProfiles) - { -#endif // ALLOW_NON_PROFILED_LOGIN - // actually attempt to create an account based on info entered - AsciiString month, day, year; - month.translate( GadgetTextEntryGetText(textEntryMonth) ); - day.translate( GadgetTextEntryGetText(textEntryDay) ); - year.translate( GadgetTextEntryGetText(textEntryYear) ); - - if(!isAgeOkay(month, day, year)) - { - GSMessageBoxOk(TheGameText->fetch("GUI:AgeFailedTitle"), TheGameText->fetch("GUI:AgeFailed")); - break; - } - - AsciiString login, password, email; - email.translate( GadgetComboBoxGetText(comboBoxEmail) ); - login.translate( GadgetComboBoxGetText(comboBoxLoginName) ); - password.translate( GadgetTextEntryGetText(textEntryPassword) ); - - if ( !email.isEmpty() && !login.isEmpty() && !password.isEmpty() ) - { - loginAttemptTime = timeGetTime(); - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_LOGINNEW; - strcpy(req.arg.login.nick, login.str()); - strcpy(req.arg.login.email, email.str()); - strcpy(req.arg.login.password, password.str()); - req.arg.login.hasFirewall = TRUE; - - TheGameSpyInfo->setLocalBaseName( login ); - //TheGameSpyInfo->setLocalProfileID( resp.player.profileID ); - TheGameSpyInfo->setLocalEmail( email ); - TheGameSpyInfo->setLocalPassword( password ); - DEBUG_LOG(("before create: TheGameSpyInfo->stuff(%s/%s/%s)\n", TheGameSpyInfo->getLocalBaseName().str(), TheGameSpyInfo->getLocalEmail().str(), TheGameSpyInfo->getLocalPassword().str())); - - TheGameSpyBuddyMessageQueue->addRequest( req ); - if(checkBoxRememberPassword && GadgetCheckBoxIsChecked(checkBoxRememberPassword)) - { - (*loginPref)["lastName"] = login; - (*loginPref)["lastEmail"] = email; - (*loginPref)["useProfiles"] = "yes"; - AsciiString date; - date = month; - date.concat(day); - date.concat(year); - - loginPref->addLogin(email, login, password, date); - } - - EnableLoginControls( FALSE ); - - // fire off some pings - startPings(); - } - else - { - // user didn't fill in all info. prompt him. - if(email.isEmpty() && login.isEmpty() && password.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSNoLoginInfoAll")); - else if( email.isEmpty() && login.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSNoLoginInfoEmailNickname")); - else if( email.isEmpty() && password.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSNoLoginInfoEmailPassword")); - else if( login.isEmpty() && password.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSNoLoginInfoNicknamePassword")); - else if( email.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSNoLoginInfoEmail")); - else if( password.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSNoLoginInfoPassword")); - else if( login.isEmpty() ) - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSNoLoginInfoNickname")); - else - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSNoLoginInfoAll")); - } -#ifdef ALLOW_NON_PROFILED_LOGIN - } - else - { - // not the profile screen - switch to it - buttonPushed = TRUE; - nextScreen = "Menus/GameSpyLoginProfile.wnd"; - TheShell->pop(); - } -#endif // ALLOW_NON_PROFILED_LOGIN - } //if ( controlID == buttonCreateAccount ) - else if ( controlID == buttonLoginID ) - { - AsciiString login, password, email; - -#ifdef ALLOW_NON_PROFILED_LOGIN - if (GameSpyUseProfiles) - { -#endif // ALLOW_NON_PROFILED_LOGIN - AsciiString month, day, year; - month.translate( GadgetTextEntryGetText(textEntryMonth) ); - day.translate( GadgetTextEntryGetText(textEntryDay) ); - year.translate( GadgetTextEntryGetText(textEntryYear) ); - - if(!isAgeOkay(month, day, year)) - { - GSMessageBoxOk(TheGameText->fetch("GUI:AgeFailedTitle"), TheGameText->fetch("GUI:AgeFailed")); - break; - } - - email.translate( GadgetComboBoxGetText(comboBoxEmail) ); - login.translate( GadgetComboBoxGetText(comboBoxLoginName) ); - password.translate( GadgetTextEntryGetText(textEntryPassword) ); - - if ( !email.isEmpty() && !login.isEmpty() && !password.isEmpty() ) - { - loginAttemptTime = timeGetTime(); - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_LOGIN; - strcpy(req.arg.login.nick, login.str()); - strcpy(req.arg.login.email, email.str()); - strcpy(req.arg.login.password, password.str()); - req.arg.login.hasFirewall = true; - - TheGameSpyInfo->setLocalBaseName( login ); - //TheGameSpyInfo->setLocalProfileID( resp.player.profileID ); - TheGameSpyInfo->setLocalEmail( email ); - TheGameSpyInfo->setLocalPassword( password ); - DEBUG_LOG(("before login: TheGameSpyInfo->stuff(%s/%s/%s)\n", TheGameSpyInfo->getLocalBaseName().str(), TheGameSpyInfo->getLocalEmail().str(), TheGameSpyInfo->getLocalPassword().str())); - - TheGameSpyBuddyMessageQueue->addRequest( req ); - if(checkBoxRememberPassword && GadgetCheckBoxIsChecked(checkBoxRememberPassword)) - { - (*loginPref)["lastName"] = login; - (*loginPref)["lastEmail"] = email; - (*loginPref)["useProfiles"] = "yes"; - AsciiString date; - date = month; - date.concat(day); - date.concat(year); - - loginPref->addLogin(email, login, password,date); - } - else - { - loginPref->forgetLogin(email); - } - EnableLoginControls( FALSE ); - - // fire off some pings - startPings(); - } - else - { - // user didn't fill in all info. prompt him. - if(email.isEmpty() && login.isEmpty() && password.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSNoLoginInfoAll")); - else if( email.isEmpty() && login.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSNoLoginInfoEmailNickname")); - else if( email.isEmpty() && password.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSNoLoginInfoEmailPassword")); - else if( login.isEmpty() && password.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSNoLoginInfoNicknamePassword")); - else if( email.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSNoLoginInfoEmail")); - else if( password.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSNoLoginInfoPassword")); - else if( login.isEmpty() ) - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSNoLoginInfoNickname")); - else - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSNoLoginInfoAll")); - } -#ifdef ALLOW_NON_PROFILED_LOGIN - } - else - { - login.translate( GadgetTextEntryGetText(textEntryLoginName) ); - - if ( !login.isEmpty() ) - { - loginAttemptTime = timeGetTime(); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_LOGIN; - req.nick = login.str(); - req.login.profileID = 0; - TheGameSpyPeerMessageQueue->addRequest( req ); - - (*loginPref)["lastName"] = login; - loginPref->erase("lastEmail"); - (*loginPref)["useProfiles"] = "no"; - EnableLoginControls( FALSE ); - - // fire off some pings - startPings(); - } - } -#endif // ALLOW_NON_PROFILED_LOGIN - - } //if ( controlID == buttonLogin ) - else if ( controlID == buttonTOSID ) - { - parentTOS->winHide(FALSE); - - if (1) - { - // Okay, no web browser. This means we're looking at a UTF-8 text file. - GadgetListBoxReset(listboxTOS); - AsciiString fileName; - fileName.format("Data\\%s\\TOS.txt", GetRegistryLanguage().str()); - File *theFile = TheFileSystem->openFile(fileName.str(), File::READ); - if (theFile) - { - Int size = theFile->size(); - - char *fileBuf = new char[size]; - Color tosColor = GameMakeColor(255, 255, 255, 255); - - Int bytesRead = theFile->read(fileBuf, size); - if (bytesRead == size && size > 2) - { - fileBuf[size-1] = 0; // just to be safe - AsciiString asciiBuf = fileBuf+2; - AsciiString asciiLine; - while (asciiBuf.nextToken(&asciiLine, "\r\n")) - { - UnicodeString uniLine; - uniLine = UnicodeString(MultiByteToWideCharSingleLine(asciiLine.str()).c_str()); - int len = uniLine.getLength(); - for (int index = len-1; index >= 0; index--) - { - if (iswspace(uniLine.getCharAt(index))) - { - uniLine.removeLastChar(); - } - else - { - break; - } - } - //uniLine.trim(); - DEBUG_LOG(("adding TOS line: [%ls]\n", uniLine.str())); - GadgetListBoxAddEntryText(listboxTOS, uniLine, tosColor, -1); - } - - } - - delete fileBuf; - fileBuf = NULL; - - theFile->close(); - theFile = NULL; - } - } - EnableLoginControls( FALSE ); - buttonBack->winEnable(FALSE); - - } - else if ( controlID == buttonTOSOKID ) - { - EnableLoginControls( TRUE ); - - parentTOS->winHide(TRUE); - - OptionPreferences optionPref; - optionPref["SawTOS"] = "yes"; - optionPref.write(); - buttonBack->winEnable(TRUE); - } - break; - }// case GBM_SELECTED: - - case GEM_EDIT_DONE: - { - break; - } - /* - case GEM_UPDATE_TEXT: - { - if (buttonPushed) - break; - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if ( controlID == textEntryLoginNameID ) - { - UnicodeString munkee = GadgetTextEntryGetText( textEntryLoginName ); - if ( !isNickOkay( munkee ) ) - { - munkee.removeLastChar(); - GadgetTextEntrySetText( textEntryLoginName, munkee ); - } - }// if ( controlID == textEntryLoginNameID ) - break; - }//case GEM_UPDATE_TEXT: - */ - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLLoginMenuSystem - - diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLMapSelectMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLMapSelectMenu.cpp deleted file mode 100644 index 7cef8850394..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLMapSelectMenu.cpp +++ /dev/null @@ -1,471 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: WOLMapSelectMenu.cpp //////////////////////////////////////////////////////////////////////// -// Author: Matt Campbell, December 2001 -// Description: MapSelect menu window callbacks -/////////////////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/CustomMatchPreferences.h" -#include "Common/GameEngine.h" -#include "Common/MessageStream.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/GadgetRadioButton.h" -#include "GameClient/Shell.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetListBox.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameClient/MapUtil.h" -#include "GameNetwork/GUIUtil.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -static NameKeyType buttonBack = NAMEKEY_INVALID; -static NameKeyType buttonOK = NAMEKEY_INVALID; -static NameKeyType listboxMap = NAMEKEY_INVALID; -static GameWindow *parent = NULL; -static Bool raiseMessageBoxes = FALSE; -static GameWindow *winMapPreview = NULL; -static NameKeyType winMapPreviewID = NAMEKEY_INVALID; - -static NameKeyType radioButtonSystemMapsID = NAMEKEY_INVALID; -static NameKeyType radioButtonUserMapsID = NAMEKEY_INVALID; - -extern WindowLayout *WOLMapSelectLayout; ///< Map selection overlay -static GameWindow *mapList = NULL; - -static GameWindow *buttonMapStartPosition[MAX_SLOTS] = {NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL }; -static NameKeyType buttonMapStartPositionID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; - -static GameWindow *winMapWindow = NULL; - -static void NullifyControls(void) -{ - parent = NULL; - winMapPreview = NULL; - mapList = NULL; - for (Int i=0; iwinGetWindowFromId( NULL, TheNameKeyGenerator->nameToKey("GameSpyGameOptionsMenu.wnd:ButtonBack") ); - if(win) - win->winEnable( show ); -} - -// PUBLIC FUNCTIONS /////////////////////////////////////////////////////////////////////////////// - -//------------------------------------------------------------------------------------------------- -/** Initialize the MapSelect menu */ -//------------------------------------------------------------------------------------------------- -void WOLMapSelectMenuInit( WindowLayout *layout, void *userData ) -{ - - // set keyboard focus to main parent - AsciiString parentName( "WOLMapSelectMenu.wnd:WOLMapSelectMenuParent" ); - NameKeyType parentID = TheNameKeyGenerator->nameToKey( parentName ); - parent = TheWindowManager->winGetWindowFromId( NULL, parentID ); - - TheWindowManager->winSetFocus( parent ); - - CustomMatchPreferences pref; - Bool usesSystemMapDir = pref.usesSystemMapDir(); - winMapPreviewID = TheNameKeyGenerator->nameToKey( AsciiString("WOLMapSelectMenu.wnd:WinMapPreview") ); - winMapPreview = TheWindowManager->winGetWindowFromId(parent, winMapPreviewID); - - const MapMetaData *mmd = TheMapCache->findMap(TheGameSpyGame->getMap()); - if (mmd) - { - usesSystemMapDir = mmd->m_isOfficial; - } - - buttonBack = TheNameKeyGenerator->nameToKey( AsciiString("WOLMapSelectMenu.wnd:ButtonBack") ); - buttonOK = TheNameKeyGenerator->nameToKey( AsciiString("WOLMapSelectMenu.wnd:ButtonOK") ); - listboxMap = TheNameKeyGenerator->nameToKey( AsciiString("WOLMapSelectMenu.wnd:ListboxMap") ); - radioButtonSystemMapsID = TheNameKeyGenerator->nameToKey( "WOLMapSelectMenu.wnd:RadioButtonSystemMaps" ); - radioButtonUserMapsID = TheNameKeyGenerator->nameToKey( "WOLMapSelectMenu.wnd:RadioButtonUserMaps" ); - winMapWindow = TheWindowManager->winGetWindowFromId( parent, listboxMap ); - - GameWindow *radioButtonSystemMaps = TheWindowManager->winGetWindowFromId( parent, radioButtonSystemMapsID ); - GameWindow *radioButtonUserMaps = TheWindowManager->winGetWindowFromId( parent, radioButtonUserMapsID ); - if (usesSystemMapDir) - GadgetRadioSetSelection( radioButtonSystemMaps, FALSE ); - else - GadgetRadioSetSelection( radioButtonUserMaps, FALSE ); - - AsciiString tmpString; - for (Int i = 0; i < MAX_SLOTS; i++) - { - tmpString.format("WOLMapSelectMenu.wnd:ButtonMapStartPosition%d", i); - buttonMapStartPositionID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - buttonMapStartPosition[i] = TheWindowManager->winGetWindowFromId( winMapPreview, buttonMapStartPositionID[i] ); - DEBUG_ASSERTCRASH(buttonMapStartPosition[i], ("Could not find the ButtonMapStartPosition[%d]",i )); - buttonMapStartPosition[i]->winHide(TRUE); - buttonMapStartPosition[i]->winEnable(FALSE); - } - - raiseMessageBoxes = TRUE; - showGameSpyGameOptionsUnderlyingGUIElements( FALSE ); - - // get the listbox window - AsciiString listString( "WOLMapSelectMenu.wnd:ListboxMap" ); - NameKeyType mapListID = TheNameKeyGenerator->nameToKey( listString ); - mapList = TheWindowManager->winGetWindowFromId( parent, mapListID ); - if( mapList ) - { - if (TheMapCache) - TheMapCache->updateCache(); - populateMapListbox( mapList, usesSystemMapDir, TRUE, TheGameSpyGame->getMap() ); - } - -} // end WOLMapSelectMenuInit - -//------------------------------------------------------------------------------------------------- -/** MapSelect menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLMapSelectMenuShutdown( WindowLayout *layout, void *userData ) -{ - NullifyControls(); - - // hide menu - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout ); - -} // end WOLMapSelectMenuShutdown - -//------------------------------------------------------------------------------------------------- -/** MapSelect menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLMapSelectMenuUpdate( WindowLayout *layout, void *userData ) -{ - - if (raiseMessageBoxes) - { - RaiseGSMessageBox(); - raiseMessageBoxes = false; - } - - // No update because the game setup screen is up at the same - // time and it does the update for us... -} // end WOLMapSelectMenuUpdate - -//------------------------------------------------------------------------------------------------- -/** Map select menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLMapSelectMenuInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - AsciiString buttonName( "WOLMapSelectMenu.wnd:ButtonBack" ); - NameKeyType buttonID = TheNameKeyGenerator->nameToKey( buttonName ); - GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonID ); - - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)button, buttonID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; - -} // end WOLMapSelectMenuInput -void WOLPositionStartSpots( void ); - -//------------------------------------------------------------------------------------------------- -/** MapSelect menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLMapSelectMenuSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CREATE: - { - break; - - } // end create - - //--------------------------------------------------------------------------------------------- - case GWM_DESTROY: - { - NullifyControls(); - break; - - } // end case - - // -------------------------------------------------------------------------------------------- - case GWM_INPUT_FOCUS: - { - - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - - } // end input - - //--------------------------------------------------------------------------------------------- - case GLM_DOUBLE_CLICKED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if( controlID == listboxMap ) - { - int rowSelected = mData2; - - if (rowSelected >= 0) - { - GadgetListBoxSetSelected( control, rowSelected ); - GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonOK ); - - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)button, buttonOK ); - } - } - break; - } - //--------------------------------------------------------------------------------------------- - case GLM_SELECTED: - { - - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if( controlID == listboxMap ) - { - int rowSelected = mData2; - if( rowSelected < 0 ) - { - positionStartSpots( AsciiString::TheEmptyString, buttonMapStartPosition, winMapPreview); -// winMapPreview->winClearStatus(WIN_STATUS_IMAGE); - break; - } - winMapPreview->winSetStatus(WIN_STATUS_IMAGE); - UnicodeString map; - // get text of the map to load - map = GadgetListBoxGetText( winMapWindow, rowSelected, 0 ); - - // set the map name in the global data map name - AsciiString asciiMap; - const char *mapFname = (const char *)GadgetListBoxGetItemData( winMapWindow, rowSelected ); - DEBUG_ASSERTCRASH(mapFname, ("No map item data")); - if (mapFname) - asciiMap = mapFname; - else - asciiMap.translate( map ); - asciiMap.toLower(); - Image *image = getMapPreviewImage(asciiMap); - winMapPreview->winSetUserData((void *)TheMapCache->findMap(asciiMap)); - if(image) - { - winMapPreview->winSetEnabledImage(0, image); - } - else - { - winMapPreview->winClearStatus(WIN_STATUS_IMAGE); - } - positionStartSpots( asciiMap, buttonMapStartPosition, winMapPreview); - } - break; - } - //--------------------------------------------------------------------------------------------- - case GBM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if( controlID == buttonBack ) - { - showGameSpyGameOptionsUnderlyingGUIElements( TRUE ); - - WOLMapSelectLayout->destroyWindows(); - WOLMapSelectLayout->deleteInstance(); - WOLMapSelectLayout = NULL; - WOLPositionStartSpots(); - } // end if - else if ( controlID == radioButtonSystemMapsID ) - { - if (TheMapCache) - TheMapCache->updateCache(); - populateMapListbox( mapList, TRUE, TRUE, TheGameSpyGame->getMap() ); - CustomMatchPreferences pref; - pref.setUsesSystemMapDir(TRUE); - pref.write(); - } - else if ( controlID == radioButtonUserMapsID ) - { - if (TheMapCache) - TheMapCache->updateCache(); - populateMapListbox( mapList, FALSE, TRUE, TheGameSpyGame->getMap() ); - CustomMatchPreferences pref; - pref.setUsesSystemMapDir(FALSE); - pref.write(); - } - else if( controlID == buttonOK ) - { - Int selected; - UnicodeString map; - - // get the selected index - GadgetListBoxGetSelected( winMapWindow, &selected ); - - if( selected != -1 ) - { - - // get text of the map to load - map = GadgetListBoxGetText( winMapWindow, selected, 0 ); - - - // set the map name in the global data map name - AsciiString asciiMap; - const char *mapFname = (const char *)GadgetListBoxGetItemData( winMapWindow, selected ); - DEBUG_ASSERTCRASH(mapFname, ("No map item data")); - if (mapFname) - asciiMap = mapFname; - else - asciiMap.translate( map ); - TheGameSpyGame->setMap(asciiMap); - asciiMap.toLower(); - std::map::iterator it = TheMapCache->find(asciiMap); - if (it != TheMapCache->end()) - { - TheGameSpyGame->getGameSpySlot(0)->setMapAvailability(TRUE); - TheGameSpyGame->setMapCRC( it->second.m_CRC ); - TheGameSpyGame->setMapSize( it->second.m_filesize ); - } - - TheGameSpyGame->adjustSlotsForMap(); // BGC- adjust the slots for the new map. - TheGameSpyGame->resetAccepted(); - TheGameSpyGame->resetStartSpots(); - TheGameSpyInfo->setGameOptions(); - - WOLDisplaySlotList(); - WOLDisplayGameOptions(); - - WOLMapSelectLayout->destroyWindows(); - WOLMapSelectLayout->deleteInstance(); - WOLMapSelectLayout = NULL; - - showGameSpyGameOptionsUnderlyingGUIElements( TRUE ); - - WOLPositionStartSpots(); - - } // end if - - } // end else if - - break; - - } // end selected - - default: - return MSG_IGNORED; - - } // end switch - - return MSG_HANDLED; - -} // end WOLMapSelectMenuSystem diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLMessageWindow.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLMessageWindow.cpp deleted file mode 100644 index 897b3defb8f..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLMessageWindow.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLMessageWindow.cpp -// Author: Chris Huybregts, November 2001 -// Description: Lan Lobby Menu -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameNetwork/IPEnumeration.h" -//#include "GameNetwork/WOL.h" - - - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentWOLMessageWindowID = NAMEKEY_INVALID; -static NameKeyType buttonCancelID = NAMEKEY_INVALID; - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentWOLMessageWindow = NULL; -static GameWindow *buttonCancel = NULL; - - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOLMessage Window */ -//------------------------------------------------------------------------------------------------- -void WOLMessageWindowInit( WindowLayout *layout, void *userData ) -{ - parentWOLMessageWindowID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLMessageWindow.wnd:WOLMessageWindowParent" ) ); - buttonCancelID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLMessageWindow.wnd:ButtonCancel" ) ); - parentWOLMessageWindow = TheWindowManager->winGetWindowFromId( NULL, parentWOLMessageWindowID ); - buttonCancel = TheWindowManager->winGetWindowFromId( NULL, buttonCancelID); - - - // Show Menu - layout->hide( FALSE ); - - // Set Keyboard to Main Parent - TheWindowManager->winSetFocus( parentWOLMessageWindow ); - -} // WOLMessageWindowInit - -//------------------------------------------------------------------------------------------------- -/** WOLMessage Window shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLMessageWindowShutdown( WindowLayout *layout, void *userData ) -{ - - // hide menu - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout ); -} // WOLMessageWindowShutdown - - -//------------------------------------------------------------------------------------------------- -/** WOLMessage Window update method */ -//------------------------------------------------------------------------------------------------- -void WOLMessageWindowUpdate( WindowLayout * layout, void *userData) -{ - /* - if (WOL::TheWOL) - WOL::TheWOL->update(); - */ - -}// WOLMessageWindowUpdate - -//------------------------------------------------------------------------------------------------- -/** WOLMessage Window input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLMessageWindowInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonCancel, buttonCancelID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// WOLMessageWindowInput - -//------------------------------------------------------------------------------------------------- -/** WOLMessage Window window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLMessageWindowSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - - switch( msg ) - { - - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - case GBM_SELECTED: - { - break; - }// case GBM_SELECTED: - - case GEM_EDIT_DONE: - { - break; - } - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLMessageWindowSystem diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQMScoreScreen.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQMScoreScreen.cpp deleted file mode 100644 index 26b21f3e7bd..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQMScoreScreen.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLQMScoreScreen.cpp -// Author: Matt Campbell, November 2001 -// Description: QuickMatch score screen (different from normal screen in that it has 'QM' and 'Discon' buttons) -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetTextEntry.h" -//#include "GameNetwork/WOL.h" -//#include "GameNetwork/WOLmenus.h" - - - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentWOLQMScoreID = NAMEKEY_INVALID; -static NameKeyType buttonDisconnectID = NAMEKEY_INVALID; -static NameKeyType buttonQuickmatchID = NAMEKEY_INVALID; - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentWOLQMScore = NULL; -static GameWindow *buttonDisconnect = NULL; -static GameWindow *buttonQuickmatch = NULL; - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Status Menu */ -//------------------------------------------------------------------------------------------------- -void WOLQMScoreScreenInit( WindowLayout *layout, void *userData ) -{ - parentWOLQMScoreID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLQMScoreScreen.wnd:WOLQMScoreScreenParent" ) ); - buttonDisconnectID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLQMScoreScreen.wnd:ButtonDisconnect" ) ); - buttonQuickmatchID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLQMScoreScreen.wnd:ButtonQuickMatch" ) ); - parentWOLQMScore = TheWindowManager->winGetWindowFromId( NULL, parentWOLQMScoreID ); - buttonDisconnect = TheWindowManager->winGetWindowFromId( NULL, buttonDisconnectID); - buttonQuickmatch = TheWindowManager->winGetWindowFromId( NULL, buttonQuickmatchID); - - /* - if (WOL::TheWOL->getState() == WOL::WOLAPI_FATAL_ERROR) - { - // We can get to the score screen even though we've been disconnected. Just hide - // any buttons that lead back into WOL. - - buttonQuickmatch->winHide( TRUE ); - } - */ - - // Show Menu - layout->hide( FALSE ); - - // Set Keyboard to Main Parent - TheWindowManager->winSetFocus( parentWOLQMScore ); - - //progressLayout = TheShell->top(); - -} // WOLQMScoreScreenInit - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLQMScoreScreenShutdown( WindowLayout *layout, void *userData ) -{ - - // hide menu - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout ); - - //progressLayout = NULL; - -} // WOLQMScoreScreenShutdown - - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLQMScoreScreenUpdate( WindowLayout * layout, void *userData) -{ - /* - if (WOL::TheWOL) - WOL::TheWOL->update(); - */ -}// WOLQMScoreScreenUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLQMScoreScreenInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonDisconnect, buttonDisconnectID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// WOLQMScoreScreenInput - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLQMScoreScreenSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - - switch( msg ) - { - - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're given the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - case GBM_SELECTED: - { - /* - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if ( controlID == buttonDisconnectID ) - { - //TheShell->pop(); - if (WOL::TheWOL->setState( WOL::WOLAPI_FATAL_ERROR )) - { - WOL::TheWOL->addCommand( WOL::WOLCOMMAND_RESET ); // don't display an error, log out, or anything - } - - } //if ( controlID == buttonDisconnect ) - else if ( controlID == buttonQuickmatchID ) - { - //TheShell->pop(); - if (WOL::TheWOL->getState() != WOL::WOLAPI_FATAL_ERROR) - { - if (WOL::TheWOL->setState( WOL::WOLAPI_TOURNAMENT )) - { - WOL::TheWOL->setScreen( WOL::WOLAPI_MENU_QUICKMATCH ); - WOL::TheWOL->addCommand( WOL::WOLCOMMAND_FIND_MATCH_CHANNEL ); - } - } - - } //if ( controlID == buttonDisconnect ) - */ - break; - }// case GBM_SELECTED: - - case GEM_EDIT_DONE: - { - break; - } - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLQMScoreScreenSystem diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp deleted file mode 100644 index 2b42682acb8..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp +++ /dev/null @@ -1,1832 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLQuickMatchMenu.cpp -// Author: Chris Huybregts, November 2001 -// Description: Lan Lobby Menu -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "Common/QuickmatchPreferences.h" -#include "Common/LadderPreferences.h" -#include "Common/MultiplayerSettings.h" -#include "Common/PlayerTemplate.h" -#include "GameClient/AnimateWindowManager.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/GameText.h" -#include "GameClient/InGameUI.h" -#include "GameClient/Shell.h" -#include "GameClient/ShellHooks.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetComboBox.h" -#include "GameClient/GadgetPushButton.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/MapUtil.h" -#include "GameClient/GameWindowTransitions.h" - -#include "GameLogic/GameLogic.h" - -#include "GameNetwork/NAT.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameNetwork/GameSpy/BuddyDefs.h" -#include "GameNetwork/GameSpy/GSConfig.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PersistentStorageDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/RankPointValue.h" -#include "GameNetwork/GameSpy/LadderDefs.h" -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -#ifdef DEBUG_LOGGING -#include "Common/MiniLog.h" -//#define PERF_TEST -static LogClass s_perfLog("QMPerf.txt"); -static Bool s_inQM = FALSE; -#define PERF_LOG(x) s_perfLog.log x -#else // DEBUG_LOGGING -#define PERF_LOG(x) {} -#endif // DEBUG_LOGGING - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentWOLQuickMatchID = NAMEKEY_INVALID; -static NameKeyType buttonBackID = NAMEKEY_INVALID; -static NameKeyType buttonStartID = NAMEKEY_INVALID; -static NameKeyType buttonStopID = NAMEKEY_INVALID; -static NameKeyType buttonWidenID = NAMEKEY_INVALID; -static NameKeyType buttonBuddiesID = NAMEKEY_INVALID; -static NameKeyType listboxQuickMatchID = NAMEKEY_INVALID; -static NameKeyType listboxMapSelectID = NAMEKEY_INVALID; -static NameKeyType buttonSelectAllMapsID = NAMEKEY_INVALID; -static NameKeyType buttonSelectNoMapsID = NAMEKEY_INVALID; -//static NameKeyType textEntryMaxDisconnectsID = NAMEKEY_INVALID; -//static NameKeyType textEntryMaxPointsID = NAMEKEY_INVALID; -//static NameKeyType textEntryMinPointsID = NAMEKEY_INVALID; -static NameKeyType textEntryWaitTimeID = NAMEKEY_INVALID; -static NameKeyType comboBoxNumPlayersID = NAMEKEY_INVALID; -static NameKeyType comboBoxMaxPingID = NAMEKEY_INVALID; -static NameKeyType comboBoxLadderID = NAMEKEY_INVALID; -static NameKeyType comboBoxMaxDisconnectsID = NAMEKEY_INVALID; -static NameKeyType staticTextNumPlayersID = NAMEKEY_INVALID; -static NameKeyType comboBoxSideID = NAMEKEY_INVALID; -static NameKeyType comboBoxColorID = NAMEKEY_INVALID; - - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentWOLQuickMatch = NULL; -static GameWindow *buttonBack = NULL; -static GameWindow *buttonStart = NULL; -static GameWindow *buttonStop = NULL; -static GameWindow *buttonWiden = NULL; -GameWindow *quickmatchTextWindow = NULL; -static GameWindow *listboxMapSelect = NULL; -//static GameWindow *textEntryMaxDisconnects = NULL; -//static GameWindow *textEntryMaxPoints = NULL; -//static GameWindow *textEntryMinPoints = NULL; -static GameWindow *textEntryWaitTime = NULL; -static GameWindow *comboBoxNumPlayers = NULL; -static GameWindow *comboBoxMaxPing = NULL; -static GameWindow *comboBoxLadder = NULL; -static GameWindow *comboBoxDisabledLadder = NULL; // enable and disable this, but never use it. it is a stand-in for comboBoxLadder for when there are no ladders -static GameWindow *comboBoxMaxDisconnects = NULL; -static GameWindow *staticTextNumPlayers = NULL; -static GameWindow *comboBoxSide = NULL; -static GameWindow *comboBoxColor = NULL; - -static Bool isShuttingDown = false; -static Bool buttonPushed = false; -static char *nextScreen = NULL; -static Bool raiseMessageBoxes = false; -static Bool isInInit = FALSE; -static const Image *selectedImage = NULL; -static const Image *unselectedImage = NULL; - -static bool isPopulatingLadderBox = false; -static Int maxPingEntries = 0; -static Int maxPoints= 100; -static Int minPoints = 0; - -static const LadderInfo * getLadderInfo( void ); - - -// [SKB: Jul 01 2003 @ 7:7pm] : -// German2 now has fewer maps. When trying to do a QM with a Retail version -// the bool string sent to the QMBot is almost always a different size. This -// mapping is kept so that we now send a string of all maps instead of just -// the ones that are visible to the user. - -#define VARIABLE_NUMBER_OF_MAPS 1 - -#if VARIABLE_NUMBER_OF_MAPS -typedef std::vector MapListboxIndex; -static MapListboxIndex mapListboxIndex; -#endif - - -static Bool isInfoShown(void) -{ - static NameKeyType parentStatsID = NAMEKEY("WOLQuickMatchMenu.wnd:ParentStats"); - GameWindow *parentStats = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, parentStatsID ); - if (parentStats) - return !parentStats->winIsHidden(); - return FALSE; -} - -static void hideInfoGadgets(Bool doIt) -{ - static NameKeyType parentStatsID = NAMEKEY("WOLQuickMatchMenu.wnd:ParentStats"); - GameWindow *parentStats = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, parentStatsID ); - if (parentStats) - { - parentStats->winHide(doIt); - } -} - -static void hideOptionsGadgets(Bool doIt) -{ - static NameKeyType parentOptionsID = NAMEKEY("WOLQuickMatchMenu.wnd:ParentOptions"); - GameWindow *parentOptions = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, parentOptionsID ); - if (parentOptions) - { - parentOptions->winHide(doIt); - if (comboBoxSide) - comboBoxSide->winHide(doIt); - if (comboBoxColor) - comboBoxColor->winHide(doIt); - if (comboBoxNumPlayers) - comboBoxNumPlayers->winHide(doIt); - if (comboBoxLadder) - comboBoxLadder->winHide(doIt); - if (comboBoxDisabledLadder) - comboBoxDisabledLadder->winHide(doIt); - if (comboBoxMaxPing) - comboBoxMaxPing->winHide(doIt); - if (comboBoxMaxDisconnects) - comboBoxMaxDisconnects->winHide(doIt); - } -} - -static void enableOptionsGadgets(Bool doIt) -{ -#ifdef PERF_TEST - s_inQM = !doIt; -#endif // PERF_TEST - static NameKeyType parentOptionsID = NAMEKEY("WOLQuickMatchMenu.wnd:ParentOptions"); - GameWindow *parentOptions = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, parentOptionsID ); - const LadderInfo *li = getLadderInfo(); - if (parentOptions) - { - parentOptions->winEnable(doIt); - if (comboBoxSide) - comboBoxSide->winEnable(doIt && (!li || !li->randomFactions)); - if (comboBoxColor) - comboBoxColor->winEnable(doIt); - if (comboBoxNumPlayers) - comboBoxNumPlayers->winEnable(doIt); - if (comboBoxLadder) - comboBoxLadder->winEnable(doIt); - if (comboBoxDisabledLadder) - comboBoxDisabledLadder->winEnable(FALSE); - if (comboBoxMaxPing) - comboBoxMaxPing->winEnable(doIt); - if (comboBoxMaxDisconnects) - comboBoxMaxDisconnects->winEnable(doIt); - } -} - -enum -{ - MAX_DISCONNECTS_ANY = 0, - MAX_DISCONNECTS_5 = 5, - MAX_DISCONNECTS_10 = 10, - MAX_DISCONNECTS_25 = 25, - MAX_DISCONNECTS_50 = 50, -}; -enum{ MAX_DISCONNECTS_COUNT = 5 }; - -static Int MAX_DISCONNECTS[MAX_DISCONNECTS_COUNT] = {MAX_DISCONNECTS_ANY, MAX_DISCONNECTS_5, - MAX_DISCONNECTS_10, MAX_DISCONNECTS_25, - MAX_DISCONNECTS_50}; - - -void UpdateStartButton(void) -{ - if (!comboBoxLadder || !buttonStart || !listboxMapSelect) - return; - - Int index; - Int selected; - GadgetComboBoxGetSelectedPos( comboBoxLadder, &selected ); - index = (Int)GadgetComboBoxGetItemData( comboBoxLadder, selected ); - const LadderInfo *li = TheLadderList->findLadderByIndex( index ); - if (li) - { - buttonStart->winEnable(TRUE); - return; - } - - Int numMaps = GadgetListBoxGetNumEntries(listboxMapSelect); - for ( Int i=0; iwinEnable(TRUE); - return; - } - } - buttonStart->winEnable(FALSE); -} - -// ----------------------------------------------------------------------------- - -static void populateQMColorComboBox(QuickMatchPreferences& pref) -{ - Int numColors = TheMultiplayerSettings->getNumColors(); - UnicodeString colorName; - - GadgetComboBoxReset(comboBoxColor); - - MultiplayerColorDefinition *def = TheMultiplayerSettings->getColor(PLAYERTEMPLATE_RANDOM); - Int newIndex = GadgetComboBoxAddEntry(comboBoxColor, TheGameText->fetch("GUI:???"), def->getColor()); - GadgetComboBoxSetItemData(comboBoxColor, newIndex, (void *)-1); - - for (Int c=0; cgetColor(c); - if (!def) - continue; - - colorName = TheGameText->fetch(def->getTooltipName().str()); - newIndex = GadgetComboBoxAddEntry(comboBoxColor, colorName, def->getColor()); - GadgetComboBoxSetItemData(comboBoxColor, newIndex, (void *)c); - } - GadgetComboBoxSetSelectedPos(comboBoxColor, pref.getColor()); -} - -// ----------------------------------------------------------------------------- - -static void populateQMSideComboBox(Int favSide, const LadderInfo *li = NULL) -{ - Int numPlayerTemplates = ThePlayerTemplateStore->getPlayerTemplateCount(); - UnicodeString playerTemplateName; - - GadgetComboBoxReset(comboBoxSide); - - MultiplayerColorDefinition *def = TheMultiplayerSettings->getColor(PLAYERTEMPLATE_RANDOM); - Int newIndex = GadgetComboBoxAddEntry(comboBoxSide, TheGameText->fetch("GUI:Random"), def->getColor()); - GadgetComboBoxSetItemData(comboBoxSide, newIndex, (void *)PLAYERTEMPLATE_RANDOM); - - std::set seenSides; - - Int entryToSelect = 0; // select Random by default - - for (Int c=0; cgetNthPlayerTemplate(c); - if (!fac) - continue; - - if (fac->getStartingBuilding().isEmpty()) - continue; - - AsciiString side; - side.format("SIDE:%s", fac->getSide().str()); - if (seenSides.find(side) != seenSides.end()) - continue; - - if (li) - { - if (std::find(li->validFactions.begin(), li->validFactions.end(), fac->getSide()) == li->validFactions.end()) - continue; // ladder doesn't allow it. - } - - seenSides.insert(side); - - newIndex = GadgetComboBoxAddEntry(comboBoxSide, TheGameText->fetch(side), def->getColor()); - GadgetComboBoxSetItemData(comboBoxSide, newIndex, (void *)c); - - if (c == favSide) - entryToSelect = newIndex; - } - seenSides.clear(); - - GadgetComboBoxSetSelectedPos(comboBoxSide, entryToSelect); - if (li && li->randomFactions) - comboBoxSide->winEnable(FALSE); - else - comboBoxSide->winEnable(TRUE); -} - -void HandleQMLadderSelection(Int ladderID) -{ - if (!parentWOLQuickMatch) - return; - - QuickMatchPreferences pref; - - if (ladderID < 1) - { - pref.setLastLadder(AsciiString::TheEmptyString, 0); - pref.write(); - return; - } - - const LadderInfo *info = TheLadderList->findLadderByIndex(ladderID); - if (!info) - { - pref.setLastLadder(AsciiString::TheEmptyString, 0); - } - else - { - pref.setLastLadder(info->address, info->port); - } - - pref.write(); -} - -static inline Bool isValidLadder( const LadderInfo *lad ) -{ - if (lad && lad->index > 0 && lad->validQM) - { - PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(TheGameSpyInfo->getLocalProfileID()); - Int numWins = 0; - PerGeneralMap::iterator it; - for (it = stats.wins.begin(); it != stats.wins.end(); ++it) - { - numWins += it->second; - } - if (!lad->maxWins || lad->maxWins >=numWins) - { - if (!lad->minWins || lad->minWins<=numWins) - { - return TRUE; - } - } - } - return FALSE; -} - -void PopulateQMLadderListBox( GameWindow *win ) -{ - if (!parentWOLQuickMatch || !comboBoxLadder) - return; - - isPopulatingLadderBox = true; - - QuickMatchPreferences pref; - AsciiString userPrefFilename; - Int localProfile = TheGameSpyInfo->getLocalProfileID(); - - Color specialColor = GameSpyColor[GSCOLOR_MAP_SELECTED]; - Color normalColor = GameSpyColor[GSCOLOR_MAP_UNSELECTED]; - Color favoriteColor = GameSpyColor[GSCOLOR_MAP_UNSELECTED]; - Int index; - GadgetListBoxReset( win ); - - std::set usedLadders; - - // start with "No Ladder" - index = GadgetListBoxAddEntryText( win, TheGameText->fetch("GUI:NoLadder"), normalColor, -1 ); - GadgetListBoxSetItemData( win, 0, index ); - - // add the last ladder - Int selectedPos = 0; - AsciiString lastLadderAddr = pref.getLastLadderAddr(); - UnsignedShort lastLadderPort = pref.getLastLadderPort(); - const LadderInfo *info = TheLadderList->findLadder( lastLadderAddr, lastLadderPort ); - if (isValidLadder(info)) - { - usedLadders.insert(info); - index = GadgetListBoxAddEntryText( win, info->name, favoriteColor, -1 ); - GadgetListBoxSetItemData( win, (void *)(info->index), index ); - selectedPos = index; - } - - // our recent ladders - LadderPreferences ladPref; - ladPref.loadProfile( localProfile ); - const LadderPrefMap recentLadders = ladPref.getRecentLadders(); - for (LadderPrefMap::const_iterator cit = recentLadders.begin(); cit != recentLadders.end(); ++cit) - { - AsciiString addr = cit->second.address; - UnsignedShort port = cit->second.port; - if (addr == lastLadderAddr && port == lastLadderPort) - continue; - const LadderInfo *info = TheLadderList->findLadder( addr, port ); - if (isValidLadder(info) && usedLadders.find(info) == usedLadders.end()) - { - usedLadders.insert(info); - index = GadgetListBoxAddEntryText( win, info->name, favoriteColor, -1 ); - GadgetListBoxSetItemData( win, (void *)(info->index), index ); - } - } - - // special ladders - const LadderInfoList *lil = TheLadderList->getSpecialLadders(); - LadderInfoList::const_iterator lit; - for (lit = lil->begin(); lit != lil->end(); ++lit) - { - const LadderInfo *info = *lit; - if (isValidLadder(info) && usedLadders.find(info) == usedLadders.end()) - { - usedLadders.insert(info); - index = GadgetListBoxAddEntryText( win, info->name, specialColor, -1 ); - GadgetListBoxSetItemData( win, (void *)(info->index), index ); - } - } - - // standard ladders - lil = TheLadderList->getStandardLadders(); - for (lit = lil->begin(); lit != lil->end(); ++lit) - { - const LadderInfo *info = *lit; - if (isValidLadder(info) && usedLadders.find(info) == usedLadders.end()) - { - usedLadders.insert(info); - index = GadgetListBoxAddEntryText( win, info->name, normalColor, -1 ); - GadgetListBoxSetItemData( win, (void *)(info->index), index ); - } - } - - GadgetListBoxSetSelected( win, selectedPos ); - isPopulatingLadderBox = false; -} - -static const LadderInfo * getLadderInfo( void ) -{ - Int index; - Int selected; - GadgetComboBoxGetSelectedPos( comboBoxLadder, &selected ); - index = (Int)GadgetComboBoxGetItemData( comboBoxLadder, selected ); - const LadderInfo *li = TheLadderList->findLadderByIndex( index ); - return li; -} - -void PopulateQMLadderComboBox( void ) -{ - if (!parentWOLQuickMatch || !comboBoxLadder) - return; - - isPopulatingLadderBox = true; - - QuickMatchPreferences pref; - Int localProfile = TheGameSpyInfo->getLocalProfileID(); - - Color specialColor = GameSpyColor[GSCOLOR_MAP_SELECTED]; - Color normalColor = GameSpyColor[GSCOLOR_MAP_UNSELECTED]; - Int index; - GadgetComboBoxReset( comboBoxLadder ); - index = GadgetComboBoxAddEntry( comboBoxLadder, TheGameText->fetch("GUI:NoLadder"), normalColor ); - GadgetComboBoxSetItemData( comboBoxLadder, index, 0 ); - - std::set usedLadders; - - Int selectedPos = 0; - AsciiString lastLadderAddr = pref.getLastLadderAddr(); - UnsignedShort lastLadderPort = pref.getLastLadderPort(); - const LadderInfo *info = TheLadderList->findLadder( lastLadderAddr, lastLadderPort ); - if (isValidLadder(info)) - { - usedLadders.insert(info); - index = GadgetComboBoxAddEntry( comboBoxLadder, info->name, specialColor ); - GadgetComboBoxSetItemData( comboBoxLadder, index, (void *)(info->index) ); - selectedPos = index; - - // we selected a ladder? No game size choice for us... - GadgetComboBoxSetSelectedPos(comboBoxNumPlayers, info->playersPerTeam-1); - comboBoxNumPlayers->winEnable( FALSE ); - } - else - { - comboBoxNumPlayers->winEnable( TRUE ); - } - - LadderPreferences ladPref; - ladPref.loadProfile( localProfile ); - const LadderPrefMap recentLadders = ladPref.getRecentLadders(); - for (LadderPrefMap::const_iterator cit = recentLadders.begin(); cit != recentLadders.end(); ++cit) - { - AsciiString addr = cit->second.address; - UnsignedShort port = cit->second.port; - if (addr == lastLadderAddr && port == lastLadderPort) - continue; - const LadderInfo *info = TheLadderList->findLadder( addr, port ); - if (isValidLadder(info) && usedLadders.find(info) == usedLadders.end()) - { - usedLadders.insert(info); - index = GadgetComboBoxAddEntry( comboBoxLadder, info->name, normalColor ); - GadgetComboBoxSetItemData( comboBoxLadder, index, (void *)(info->index) ); - } - } - - index = GadgetComboBoxAddEntry( comboBoxLadder, TheGameText->fetch("GUI:ChooseLadder"), normalColor ); - GadgetComboBoxSetItemData( comboBoxLadder, index, (void *)-1 ); - - GadgetComboBoxSetSelectedPos( comboBoxLadder, selectedPos ); - isPopulatingLadderBox = false; - - populateQMSideComboBox(pref.getSide(), getLadderInfo()); // this will set side to random and disable if necessary -} - -static void populateQuickMatchMapSelectListbox( QuickMatchPreferences& pref ) -{ - std::list maps = TheGameSpyConfig->getQMMaps(); - - // enable/disable box based on ladder status - Int index; - Int selected; - GadgetComboBoxGetSelectedPos( comboBoxLadder, &selected ); - index = (Int)GadgetComboBoxGetItemData( comboBoxLadder, selected ); - const LadderInfo *li = TheLadderList->findLadderByIndex( index ); - //listboxMapSelect->winEnable( li == NULL || li->randomMaps == FALSE ); - - Int numPlayers = 0; - if (li) - { - numPlayers = li->playersPerTeam*2; - - maps = li->validMaps; - } - else - { - GadgetComboBoxGetSelectedPos(comboBoxNumPlayers, &selected); - if (selected < 0) - selected = 0; - numPlayers = (selected+1)*2; - } - - #if VARIABLE_NUMBER_OF_MAPS - mapListboxIndex.clear(); - #endif - - GadgetListBoxReset(listboxMapSelect); - for (std::list::const_iterator it = maps.begin(); it != maps.end(); ++it) - { - AsciiString theMap = *it; - const MapMetaData *md = TheMapCache->findMap(theMap); - if (md && md->m_numPlayers >= numPlayers) - { - UnicodeString displayName; - displayName = md->m_displayName; - Bool isSelected = pref.isMapSelected(theMap); - if (li && li->randomMaps) - isSelected = TRUE; - Int width = 10; - Int height = 10; - const Image *img = (isSelected)?selectedImage:unselectedImage; - if ( img ) - { - width = min(GadgetListBoxGetColumnWidth(listboxMapSelect, 0), img->getImageWidth()); - height = width; - } - Int index = GadgetListBoxAddEntryImage(listboxMapSelect, img, -1, 0, height, width); - GadgetListBoxAddEntryText(listboxMapSelect, displayName, GameSpyColor[(isSelected)?GSCOLOR_MAP_SELECTED:GSCOLOR_MAP_UNSELECTED], index, 1); - GadgetListBoxSetItemData(listboxMapSelect, (void *)isSelected, index); - GadgetListBoxSetItemData(listboxMapSelect, (void *)md, index, 1); - - #if VARIABLE_NUMBER_OF_MAPS - mapListboxIndex.push_back(index); - #endif - } - else - { - #if VARIABLE_NUMBER_OF_MAPS - // [SKB: Jul 01 2003 @ 7:9pm] : - // Keep track of maps that are not visible right now so - // they are added to the information sent to the QMBot. - mapListboxIndex.push_back(-1); - #endif - } - } -} - -static void saveQuickMatchOptions( void ) -{ - if(isInInit) - return; - QuickMatchPreferences pref; - - std::list maps = TheGameSpyConfig->getQMMaps(); - - Int index; - Int selected; - GadgetComboBoxGetSelectedPos( comboBoxLadder, &selected ); - index = (Int)GadgetComboBoxGetItemData( comboBoxLadder, selected ); - const LadderInfo *li = TheLadderList->findLadderByIndex( index ); - Int numPlayers = 0; - - if (li) - { - pref.setLastLadder( li->address, li->port ); - numPlayers = li->playersPerTeam*2; - - pref.write(); - //return; // don't save our defaults based on the tournament's defaults - } - else - { - pref.setLastLadder( AsciiString::TheEmptyString, 0 ); - GadgetComboBoxGetSelectedPos(comboBoxNumPlayers, &selected); - if (selected < 0) - selected = 0; - numPlayers = (selected+1)*2; - } - - if (!li || !li->randomMaps) // don't save the map as selected if we couldn't choose - { - Int row = 0; - Int entries = GadgetListBoxGetNumEntries(listboxMapSelect); - while ( row < entries) - { - const MapMetaData *md = (const MapMetaData *)GadgetListBoxGetItemData(listboxMapSelect, row, 1); - if(md) - pref.setMapSelected(md->m_fileName, (Bool)GadgetListBoxGetItemData(listboxMapSelect, row)); - row++; - } - } - - UnicodeString u; - AsciiString a; -// u = GadgetTextEntryGetText(textEntryMaxDisconnects); -// a.translate(u); -// pref.setMaxDisconnects(atoi(a.str())); -// u = GadgetTextEntryGetText(textEntryMaxPoints); -// a.translate(u); -// pref.setMaxPoints(max(100, atoi(a.str()))); -// u = GadgetTextEntryGetText(textEntryMinPoints); -// a.translate(u); -// pref.setMinPoints(min(100, atoi(a.str()))); - //u = GadgetTextEntryGetText(textEntryWaitTime); - //a.translate(u); - //pref.setWaitTime(atoi(a.str())); - - GadgetComboBoxGetSelectedPos(comboBoxNumPlayers, &selected); - pref.setNumPlayers(selected); - GadgetComboBoxGetSelectedPos(comboBoxMaxPing, &selected); - pref.setMaxPing(selected); - - Int item; - GadgetComboBoxGetSelectedPos(comboBoxSide, &selected); - item = (Int)GadgetComboBoxGetItemData(comboBoxSide, selected); - pref.setSide(max(0, item)); - GadgetComboBoxGetSelectedPos(comboBoxColor, &selected); - pref.setColor(max(0, selected)); - - GadgetComboBoxGetSelectedPos(comboBoxMaxDisconnects, &selected); - pref.setMaxDisconnects(selected); - - - pref.write(); -} - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Quick Match Menu */ -//------------------------------------------------------------------------------------------------- -void WOLQuickMatchMenuInit( WindowLayout *layout, void *userData ) -{ - isInInit = TRUE; - if (TheGameSpyGame && TheGameSpyGame->isGameInProgress()) - { - TheGameSpyGame->setGameInProgress(FALSE); - - // check if we were disconnected - Int disconReason; - if (TheGameSpyInfo->isDisconnectedAfterGameStart(&disconReason)) - { - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", disconReason); - UnicodeString title, body; - title = TheGameText->fetch( "GUI:GSErrorTitle" ); - body = TheGameText->fetch( disconMunkee ); - GameSpyCloseAllOverlays(); - GSMessageBoxOk( title, body ); - TheGameSpyInfo->reset(); - DEBUG_LOG(("WOLQuickMatchMenuInit() - game was in progress, and we were disconnected, so pop immediate back to main menu\n")); - TheShell->popImmediate(); - return; - } - } - - nextScreen = NULL; - buttonPushed = false; - isShuttingDown = false; - raiseMessageBoxes = true; - - if (TheNAT != NULL) { - delete TheNAT; - TheNAT = NULL; - } - - parentWOLQuickMatchID = NAMEKEY( "WOLQuickMatchMenu.wnd:WOLQuickMatchMenuParent" ); - buttonBackID = NAMEKEY( "WOLQuickMatchMenu.wnd:ButtonBack" ); - buttonBuddiesID = NAMEKEY( "WOLQuickMatchMenu.wnd:ButtonBuddies" ); - buttonStartID = NAMEKEY( "WOLQuickMatchMenu.wnd:ButtonStart" ); - buttonStopID = NAMEKEY( "WOLQuickMatchMenu.wnd:ButtonStop" ); - buttonWidenID = NAMEKEY( "WOLQuickMatchMenu.wnd:ButtonWiden" ); - listboxQuickMatchID = NAMEKEY( "WOLQuickMatchMenu.wnd:ListboxQuickMatch" ); - listboxMapSelectID = NAMEKEY( "WOLQuickMatchMenu.wnd:ListBoxMapSelect" ); - buttonSelectAllMapsID = NAMEKEY( "WOLQuickMatchMenu.wnd:ButtonSelectAllMaps" ); - buttonSelectNoMapsID = NAMEKEY( "WOLQuickMatchMenu.wnd:ButtonSelectNoMaps" ); - //textEntryMaxDisconnectsID = NAMEKEY( "WOLQuickMatchMenu.wnd:TextEntryMaxDisconnects" ); - //textEntryMaxPointsID = NAMEKEY( "WOLQuickMatchMenu.wnd:TextEntryMaxPointPercent" ); - //textEntryMinPointsID = NAMEKEY( "WOLQuickMatchMenu.wnd:TextEntryMinPointPercent" ); - textEntryWaitTimeID = NAMEKEY( "WOLQuickMatchMenu.wnd:TextEntryWaitTime" ); - comboBoxMaxPingID = NAMEKEY( "WOLQuickMatchMenu.wnd:ComboBoxMaxPing" ); - comboBoxNumPlayersID = NAMEKEY( "WOLQuickMatchMenu.wnd:ComboBoxNumPlayers" ); - comboBoxLadderID = NAMEKEY( "WOLQuickMatchMenu.wnd:ComboBoxLadder" ); - comboBoxMaxDisconnectsID = NAMEKEY( "WOLQuickMatchMenu.wnd:ComboBoxMaxDisconnects" ); - staticTextNumPlayersID = NAMEKEY( "WOLQuickMatchMenu.wnd:StaticTextNumPlayers" ); - comboBoxSideID = NAMEKEY( "WOLQuickMatchMenu.wnd:ComboBoxSide" ); - comboBoxColorID = NAMEKEY( "WOLQuickMatchMenu.wnd:ComboBoxColor" ); - - parentWOLQuickMatch = TheWindowManager->winGetWindowFromId( NULL, parentWOLQuickMatchID ); - buttonBack = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, buttonBackID); - buttonStart = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, buttonStartID); - buttonStop = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, buttonStopID); - buttonWiden = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, buttonWidenID); - quickmatchTextWindow = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, listboxQuickMatchID); - listboxMapSelect = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, listboxMapSelectID); - //textEntryMaxDisconnects = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, textEntryMaxDisconnectsID ); - //textEntryMaxPoints = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, textEntryMaxPointsID ); - //textEntryMinPoints = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, textEntryMinPointsID ); - textEntryWaitTime = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, textEntryWaitTimeID ); - comboBoxMaxPing = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, comboBoxMaxPingID ); - comboBoxNumPlayers = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, comboBoxNumPlayersID ); - comboBoxLadder = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, comboBoxLadderID ); - comboBoxMaxDisconnects = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, comboBoxMaxDisconnectsID ); - TheGameSpyInfo->registerTextWindow(quickmatchTextWindow); - staticTextNumPlayers = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, staticTextNumPlayersID ); - comboBoxSide = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, comboBoxSideID ); - comboBoxColor = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, comboBoxColorID ); - - if (TheLadderList->getStandardLadders()->size() == 0 - && TheLadderList->getSpecialLadders()->size() == 0 - && TheLadderList->getLocalLadders()->size() == 0) - { - // no ladders, so just disable them - comboBoxDisabledLadder = comboBoxLadder; - comboBoxLadder = NULL; - - isPopulatingLadderBox = TRUE; - - Color normalColor = GameSpyColor[GSCOLOR_MAP_UNSELECTED]; - Int index; - GadgetComboBoxReset( comboBoxDisabledLadder ); - index = GadgetComboBoxAddEntry( comboBoxDisabledLadder, TheGameText->fetch("GUI:NoLadder"), normalColor ); - GadgetComboBoxSetItemData( comboBoxDisabledLadder, index, 0 ); - GadgetComboBoxSetSelectedPos( comboBoxDisabledLadder, index ); - - isPopulatingLadderBox = FALSE; - - /** This code would actually *hide* the combo box, but it doesn't look as good. Left here since someone will want to - ** see it at some point. :P - if (comboBoxLadder) - { - comboBoxLadder->winHide(TRUE); - comboBoxLadder->winEnable(FALSE); - } - comboBoxLadder = NULL; - GameWindow *staticTextLadder = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, - NAMEKEY("WOLQuickMatchMenu.wnd:StaticTextLadder") ); - if (staticTextLadder) - staticTextLadder->winHide(TRUE); - */ - } - - GameWindow *buttonBuddies = TheWindowManager->winGetWindowFromId(NULL, buttonBuddiesID); - if (buttonBuddies) - buttonBuddies->winEnable(TRUE); - - GameWindow *staticTextTitle = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, - NAMEKEY("WOLQuickMatchMenu.wnd:StaticTextTitle") ); - if (staticTextTitle) - { - UnicodeString tmp; - tmp.format(TheGameText->fetch("GUI:QuickMatchTitle"), TheGameSpyInfo->getLocalName().str()); - GadgetStaticTextSetText(staticTextTitle, tmp); - } - - // QM is not going yet, so disable the Widen Search button - buttonWiden->winEnable( FALSE ); - buttonStop->winHide( TRUE ); - buttonStart->winHide( FALSE ); - GadgetListBoxReset(quickmatchTextWindow); - enableOptionsGadgets(TRUE); - - // Show Menu - layout->hide( FALSE ); - - // Set Keyboard to Main Parent - TheWindowManager->winSetFocus( parentWOLQuickMatch ); - - // fill in preferences - selectedImage = TheMappedImageCollection->findImageByName("CustomMatch_selected"); - unselectedImage = TheMappedImageCollection->findImageByName("CustomMatch_deselected"); - QuickMatchPreferences pref; - - - UnicodeString s; -// s.format(L"%d", pref.getMaxDisconnects()); -// GadgetTextEntrySetText(textEntryMaxDisconnects, s); -// s.format(L"%d", pref.getMaxPoints()); -// GadgetTextEntrySetText(textEntryMaxPoints, s); -// s.format(L"%d", pref.getMinPoints()); -// GadgetTextEntrySetText(textEntryMinPoints, s); - //s.format(L"%d", pref.getWaitTime()); - //GadgetTextEntrySetText(textEntryWaitTime, s); - maxPoints= pref.getMaxPoints(); - minPoints = pref.getMinPoints(); - - Color c = GameSpyColor[GSCOLOR_DEFAULT]; - GadgetComboBoxReset( comboBoxNumPlayers ); - Int i; - for (i=1; i<5; ++i) - { - s.format(TheGameText->fetch("GUI:PlayersVersusPlayers"), i, i); - GadgetComboBoxAddEntry( comboBoxNumPlayers, s, c ); - } - GadgetComboBoxSetSelectedPos( comboBoxNumPlayers, max(0, pref.getNumPlayers()) ); - - GadgetComboBoxReset(comboBoxMaxDisconnects); - GadgetComboBoxAddEntry( comboBoxMaxDisconnects, TheGameText->fetch("GUI:Any"), c); - for( i = 1; i < MAX_DISCONNECTS_COUNT; ++i ) - { - s.format(L"%d", MAX_DISCONNECTS[i]); - GadgetComboBoxAddEntry( comboBoxMaxDisconnects, s, c ); - } - Int maxDisconIndex = max(0, pref.getMaxDisconnects()); - GadgetComboBoxSetSelectedPos(comboBoxMaxDisconnects, maxDisconIndex); - - GadgetComboBoxReset( comboBoxMaxPing ); - maxPingEntries = (TheGameSpyConfig->getPingTimeoutInMs() - 1) / 100; - maxPingEntries++; // need to add the entry for the actual timeout - for (i=1; i fetch("GUI:TimeInMilliseconds"), i*100); - GadgetComboBoxAddEntry( comboBoxMaxPing, s, c ); - } - GadgetComboBoxAddEntry( comboBoxMaxPing, TheGameText->fetch("GUI:ANY"), c ); - i = pref.getMaxPing(); - if( i < 0 ) - i = 0; - if( i >= maxPingEntries ) - i = maxPingEntries - 1; - GadgetComboBoxSetSelectedPos( comboBoxMaxPing, i ); - - populateQMColorComboBox(pref); - populateQMSideComboBox(pref.getSide(), getLadderInfo()); - - PopulateQMLadderComboBox(); - TheShell->showShellMap(TRUE); - TheGameSpyGame->reset(); - - GadgetListBoxReset(listboxMapSelect); - populateQuickMatchMapSelectListbox(pref); - - UpdateLocalPlayerStats(); - UpdateStartButton(); - TheTransitionHandler->setGroup("WOLQuickMatchMenuFade"); - isInInit= FALSE; -} // WOLQuickMatchMenuInit - -//------------------------------------------------------------------------------------------------- -/** This is called when a shutdown is complete for this menu */ -//------------------------------------------------------------------------------------------------- -static void shutdownComplete( WindowLayout *layout ) -{ - - isShuttingDown = false; - - // hide the layout - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout, (nextScreen != NULL) ); - - if (nextScreen != NULL) - { - TheShell->push(nextScreen); - } - - nextScreen = NULL; - -} // end if - -//------------------------------------------------------------------------------------------------- -/** WOL Quick Match Menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLQuickMatchMenuShutdown( WindowLayout *layout, void *userData ) -{ - TheGameSpyInfo->unregisterTextWindow(quickmatchTextWindow); - - if (!TheGameEngine->getQuitting()) - saveQuickMatchOptions(); - - parentWOLQuickMatch = NULL; - buttonBack = NULL; - quickmatchTextWindow = NULL; - selectedImage = unselectedImage = NULL; - - isShuttingDown = true; - - // if we are shutting down for an immediate pop, skip the animations - Bool popImmediate = *(Bool *)userData; - if( popImmediate ) - { - - shutdownComplete( layout ); - return; - - } //end if - - TheShell->reverseAnimatewindow(); - TheTransitionHandler->reverse("WOLQuickMatchMenuFade"); - - RaiseGSMessageBox(); -} // WOLQuickMatchMenuShutdown - - -#ifdef PERF_TEST -static const char* getMessageString(Int t) -{ - switch(t) - { - case PeerResponse::PEERRESPONSE_LOGIN: - return "login"; - case PeerResponse::PEERRESPONSE_DISCONNECT: - return "disconnect"; - case PeerResponse::PEERRESPONSE_MESSAGE: - return "message"; - case PeerResponse::PEERRESPONSE_GROUPROOM: - return "group room"; - case PeerResponse::PEERRESPONSE_STAGINGROOM: - return "staging room"; - case PeerResponse::PEERRESPONSE_STAGINGROOMPLAYERINFO: - return "staging room player info"; - case PeerResponse::PEERRESPONSE_JOINGROUPROOM: - return "group room join"; - case PeerResponse::PEERRESPONSE_CREATESTAGINGROOM: - return "staging room create"; - case PeerResponse::PEERRESPONSE_JOINSTAGINGROOM: - return "staging room join"; - case PeerResponse::PEERRESPONSE_PLAYERJOIN: - return "player join"; - case PeerResponse::PEERRESPONSE_PLAYERLEFT: - return "player part"; - case PeerResponse::PEERRESPONSE_PLAYERCHANGEDNICK: - return "player nick"; - case PeerResponse::PEERRESPONSE_PLAYERINFO: - return "player info"; - case PeerResponse::PEERRESPONSE_PLAYERCHANGEDFLAGS: - return "player flags"; - case PeerResponse::PEERRESPONSE_ROOMUTM: - return "room UTM"; - case PeerResponse::PEERRESPONSE_PLAYERUTM: - return "player UTM"; - case PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS: - return "QM status"; - case PeerResponse::PEERRESPONSE_GAMESTART: - return "game start"; - case PeerResponse::PEERRESPONSE_FAILEDTOHOST: - return "host failure"; - } - return "unknown"; -} -#endif // PERF_TEST - -//------------------------------------------------------------------------------------------------- -/** WOL Quick Match Menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLQuickMatchMenuUpdate( WindowLayout * layout, void *userData) -{ - if (TheGameLogic->isInShellGame() && TheGameLogic->getFrame() == 1) - { - SignalUIInteraction(SHELL_SCRIPT_HOOK_GENERALS_ONLINE_ENTERED_FROM_GAME); - } - - // We'll only be successful if we've requested to - if(isShuttingDown && TheShell->isAnimFinished()&& TheTransitionHandler->isFinished()) - shutdownComplete(layout); - - if (raiseMessageBoxes) - { - RaiseGSMessageBox(); - raiseMessageBoxes = false; - } - - /// @todo: MDC handle disconnects in-game the same way as Custom Match! - - if (TheShell->isAnimFinished() && !buttonPushed && TheGameSpyPeerMessageQueue) - { - HandleBuddyResponses(); - HandlePersistentStorageResponses(); - - if (TheGameSpyGame && TheGameSpyGame->isGameInProgress()) - { - if (TheGameSpyInfo->isDisconnectedAfterGameStart(NULL)) - { - return; // already been disconnected, so don't worry. - } - - Int allowedMessages = TheGameSpyInfo->getMaxMessagesPerUpdate(); - Bool sawImportantMessage = FALSE; - PeerResponse resp; - while (allowedMessages-- && !sawImportantMessage && TheGameSpyPeerMessageQueue->getResponse( resp )) - { - switch (resp.peerResponseType) - { - case PeerResponse::PEERRESPONSE_DISCONNECT: - { - sawImportantMessage = TRUE; - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", resp.discon.reason); - - // check for scorescreen - NameKeyType listboxChatWindowScoreScreenID = NAMEKEY("ScoreScreen.wnd:ListboxChatWindowScoreScreen"); - GameWindow *listboxChatWindowScoreScreen = TheWindowManager->winGetWindowFromId( NULL, listboxChatWindowScoreScreenID ); - if (listboxChatWindowScoreScreen) - { - GadgetListBoxAddEntryText(listboxChatWindowScoreScreen, TheGameText->fetch(disconMunkee), - GameSpyColor[GSCOLOR_DEFAULT], -1); - } - else - { - // still ingame - TheInGameUI->message(disconMunkee); - } - TheGameSpyInfo->markAsDisconnectedAfterGameStart(resp.discon.reason); - } - } - } - - return; // if we're in game, all we care about is if we've been disconnected from the chat server - } - - if (TheNAT != NULL) { - NATStateType NATState = TheNAT->update(); - if (NATState == NATSTATE_DONE) - { - TheGameSpyGame->launchGame(); - if (TheGameSpyInfo) // this can be blown away by a disconnect on the map transfer screen - TheGameSpyInfo->leaveStagingRoom(); - return; // don't do any more processing this frame, in case the screen goes away - } - else if (NATState == NATSTATE_FAILED) - { - // delete TheNAT, its no good for us anymore. - delete TheNAT; - TheNAT = NULL; - - // Just back out. This cleans up some slot list problems - buttonPushed = true; - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:NATNegotiationFailed")); - nextScreen = "Menus/WOLWelcomeMenu.wnd"; - TheShell->pop(); - return; // don't do any more processing this frame, in case the screen goes away - } - } - -#ifdef PERF_TEST - UnsignedInt start = timeGetTime(); - UnsignedInt end = timeGetTime(); - std::list responses; - Int numMessages = 0; -#endif // PERF_TEST - - Int allowedMessages = TheGameSpyInfo->getMaxMessagesPerUpdate(); - Bool sawImportantMessage = FALSE; - PeerResponse resp; - while (allowedMessages-- && !sawImportantMessage && TheGameSpyPeerMessageQueue->getResponse( resp )) - { -#ifdef PERF_TEST - ++numMessages; - responses.push_back(resp.peerResponseType); -#endif // PERF_TEST - switch (resp.peerResponseType) - { - case PeerResponse::PEERRESPONSE_PLAYERUTM: - { - if (!stricmp(resp.command.c_str(), "STATS")) - { - DEBUG_LOG(("Saw STATS from %s, data was '%s'\n", resp.nick.c_str(), resp.commandOptions.c_str())); - AsciiString data = resp.commandOptions.c_str(); - AsciiString idStr; - data.nextToken(&idStr, " "); - Int id = atoi(idStr.str()); - DEBUG_LOG(("data: %d(%s) - '%s'\n", id, idStr.str(), data.str())); - - PSPlayerStats stats = TheGameSpyPSMessageQueue->parsePlayerKVPairs(data.str()); - PSPlayerStats oldStats = TheGameSpyPSMessageQueue->findPlayerStatsByID(id); - stats.id = id; - DEBUG_LOG(("Parsed ID is %d, old ID is %d\n", stats.id, oldStats.id)); - if (stats.id && (oldStats.id == 0)) - TheGameSpyPSMessageQueue->trackPlayerStats(stats); - - // now fill in the profileID in the game slot - AsciiString nick = resp.nick.c_str(); - for (Int i=0; igetGameSpySlot(i); - if (slot && slot->isHuman() && (slot->getLoginName().compareNoCase(nick) == 0)) - { - slot->setProfileID(id); - break; - } - } - } - Int slotNum = TheGameSpyGame->getSlotNum(resp.nick.c_str()); - if ((slotNum >= 0) && (slotNum < MAX_SLOTS) && (!stricmp(resp.command.c_str(), "NAT"))) { - // this is a command for NAT negotiations, pass if off to TheNAT - sawImportantMessage = TRUE; - if (TheNAT != NULL) { - TheNAT->processGlobalMessage(slotNum, resp.commandOptions.c_str()); - } - } - /* - else if (key == "NAT") - { - if ((val >= FirewallHelperClass::FIREWALL_TYPE_SIMPLE) && - (val <= FirewallHelperClass::FIREWALL_TYPE_DESTINATION_PORT_DELTA)) - { - slot->setNATBehavior((FirewallHelperClass::FirewallBehaviorType)val); - DEBUG_LOG(("Setting NAT behavior to %d for player %d\n", val, slotNum)); - change = true; - } - else - { - DEBUG_LOG(("Rejecting invalid NAT behavior %d from player %d\n", val, slotNum)); - } - } - */ - } - break; - - case PeerResponse::PEERRESPONSE_DISCONNECT: - { - sawImportantMessage = TRUE; - UnicodeString title, body; - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", resp.discon.reason); - title = TheGameText->fetch( "GUI:GSErrorTitle" ); - body = TheGameText->fetch( disconMunkee ); - GameSpyCloseAllOverlays(); - GSMessageBoxOk( title, body ); - TheGameSpyInfo->reset(); - TheShell->pop(); - } - case PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS: - { - sawImportantMessage = TRUE; - switch( resp.qmStatus.status ) - { - case QM_IDLE: - //TheGameSpyInfo->addText(UnicodeString(L"Status: QM_IDLE"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - break; - case QM_JOININGQMCHANNEL: - TheGameSpyInfo->addText(TheGameText->fetch("QM:JOININGQMCHANNEL"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - break; - case QM_LOOKINGFORBOT: - TheGameSpyInfo->addText(TheGameText->fetch("QM:LOOKINGFORBOT"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - break; - case QM_SENTINFO: - TheGameSpyInfo->addText(TheGameText->fetch("QM:SENTINFO"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - break; - case QM_WORKING: - { - UnicodeString s; - s.format(TheGameText->fetch("QM:WORKING"), resp.qmStatus.poolSize); - TheGameSpyInfo->addText(s, GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - } - buttonWiden->winEnable( TRUE ); - break; - case QM_POOLSIZE: - { - UnicodeString s; - s.format(TheGameText->fetch("QM:POOLSIZE"), resp.qmStatus.poolSize); - TheGameSpyInfo->addText(s, GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - } - break; - case QM_WIDENINGSEARCH: - TheGameSpyInfo->addText(TheGameText->fetch("QM:WIDENINGSEARCH"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - buttonWiden->winEnable( FALSE ); - break; - case QM_MATCHED: - { - TheGameSpyInfo->addText(TheGameText->fetch("QM:MATCHED"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - buttonWiden->winEnable( FALSE ); - - TheGameSpyGame->enterGame(); - TheGameSpyGame->setSeed(resp.qmStatus.seed); - - TheGameSpyGame->markGameAsQM(); - - const LadderInfo *info = getLadderInfo(); - if (!info) - { - TheGameSpyGame->setLadderIP("localhost"); - TheGameSpyGame->setLadderPort(0); - } - else - { - TheGameSpyGame->setLadderIP(info->address); - TheGameSpyGame->setLadderPort(info->port); - } - - Int i; - Int numPlayers = 0; - for (i=0; i maps = TheGameSpyConfig->getQMMaps(); - - #if VARIABLE_NUMBER_OF_MAPS - std::list::const_iterator it = maps.begin(); - std::advance(it, resp.qmStatus.mapIdx); - - AsciiString theMap = *it; - theMap.toLower(); - TheGameSpyGame->setMap(theMap); - - #else - for (std::list::const_iterator it = maps.begin(); it != maps.end(); ++it) - { - AsciiString theMap = *it; - theMap.toLower(); - const MapMetaData *md = TheMapCache->findMap(theMap); - - if (md && md->m_numPlayers >= numPlayers) - { - TheGameSpyGame->setMap(*it); - if (resp.qmStatus.mapIdx-- == 0) - break; - } - } - #endif - - Int numPlayersPerTeam = numPlayers/2; - DEBUG_ASSERTCRASH(numPlayersPerTeam, ("0 players per team???")); - if (!numPlayersPerTeam) - numPlayersPerTeam = 1; - - for (i=0; igetGameSpySlot(i); - if (resp.stagingRoomPlayerNames[i].empty()) - { - slot->setState(SLOT_CLOSED); - } - else - { - AsciiString aName = resp.stagingRoomPlayerNames[i].c_str(); - UnicodeString uName; - uName.translate(aName); - slot->setState(SLOT_PLAYER, uName, resp.qmStatus.IP[i]); - slot->setColor(resp.qmStatus.color[i]); - slot->setPlayerTemplate(resp.qmStatus.side[i]); - //slot->setProfileID(0); - slot->setNATBehavior((FirewallHelperClass::FirewallBehaviorType)resp.qmStatus.nat[i]); - slot->setLocale(""); - slot->setTeamNumber( i/numPlayersPerTeam ); - if (i==0) - TheGameSpyGame->setGameName(uName); - } - } - - DEBUG_LOG(("Starting a QM game: options=[%s]\n", GameInfoToAsciiString(TheGameSpyGame).str())); - SendStatsToOtherPlayers(TheGameSpyGame); - TheGameSpyGame->startGame(0); - GameWindow *buttonBuddies = TheWindowManager->winGetWindowFromId(NULL, buttonBuddiesID); - if (buttonBuddies) - buttonBuddies->winEnable(FALSE); - GameSpyCloseOverlay(GSOVERLAY_BUDDY); - } - break; - case QM_INCHANNEL: - TheGameSpyInfo->addText(TheGameText->fetch("QM:INCHANNEL"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - break; - case QM_NEGOTIATINGFIREWALLS: - TheGameSpyInfo->addText(TheGameText->fetch("QM:NEGOTIATINGFIREWALLS"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - break; - case QM_STARTINGGAME: - TheGameSpyInfo->addText(TheGameText->fetch("QM:STARTINGGAME"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - break; - case QM_COULDNOTFINDBOT: - TheGameSpyInfo->addText(TheGameText->fetch("QM:COULDNOTFINDBOT"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - buttonWiden->winEnable( FALSE ); - buttonStart->winHide( FALSE ); - buttonStop->winHide( TRUE ); - enableOptionsGadgets(TRUE); - break; - case QM_COULDNOTFINDCHANNEL: - TheGameSpyInfo->addText(TheGameText->fetch("QM:COULDNOTFINDCHANNEL"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - buttonWiden->winEnable( FALSE ); - buttonStart->winHide( FALSE ); - buttonStop->winHide( TRUE ); - enableOptionsGadgets(TRUE); - break; - case QM_COULDNOTNEGOTIATEFIREWALLS: - TheGameSpyInfo->addText(TheGameText->fetch("QM:COULDNOTNEGOTIATEFIREWALLS"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - buttonWiden->winEnable( FALSE ); - buttonStart->winHide( FALSE ); - buttonStop->winHide( TRUE ); - enableOptionsGadgets(TRUE); - break; - case QM_STOPPED: - TheGameSpyInfo->addText(TheGameText->fetch("QM:STOPPED"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - buttonWiden->winEnable( FALSE ); - buttonStart->winHide( FALSE ); - buttonStop->winHide( TRUE ); - enableOptionsGadgets(TRUE); - break; - } - } - break; - } - } -#ifdef PERF_TEST - // check performance - end = timeGetTime(); - UnsignedInt frameTime = end-start; - if (frameTime > 100 || responses.size() > 20) - { - UnicodeString munkee; - munkee.format(L"inQM:%d %d ms, %d messages", s_inQM, frameTime, responses.size()); - TheGameSpyInfo->addText(munkee, GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - PERF_LOG(("%ls\n", munkee.str())); - - std::list::const_iterator it; - for (it = responses.begin(); it != responses.end(); ++it) - { - PERF_LOG((" %s\n", getMessageString(*it))); - } - } -#endif // PERF_TEST - } -}// WOLQuickMatchMenuUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Quick Match Menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLQuickMatchMenuInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - if (buttonPushed) - break; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - if(!buttonBack->winIsHidden()) - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonBack, buttonBackID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// WOLQuickMatchMenuInput - -//------------------------------------------------------------------------------------------------- -/** WOL Quick Match Menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLQuickMatchMenuSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - - switch( msg ) - { - - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - case GCM_SELECTED: - { - if (buttonPushed) - break; - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - Int pos = -1; - GadgetComboBoxGetSelectedPos(control, &pos); - - saveQuickMatchOptions(); - if (controlID == comboBoxLadderID && !isPopulatingLadderBox) - { - if (pos >= 0) - { - QuickMatchPreferences pref; - Int ladderID = (Int)GadgetComboBoxGetItemData(control, pos); - if (ladderID == 0) - { - // no ladder selected - enable buttons - GadgetComboBoxSetSelectedPos(comboBoxNumPlayers, max(0, pref.getNumPlayers()/2-1)); - comboBoxNumPlayers->winEnable( TRUE ); - populateQMSideComboBox(pref.getSide()); // this will set side to random and disable if necessary - } - else if (ladderID > 0) - { - // ladder selected - disable buttons - const LadderInfo *li = TheLadderList->findLadderByIndex(ladderID); - if (li) - GadgetComboBoxSetSelectedPos(comboBoxNumPlayers, li->playersPerTeam-1); - else - GadgetComboBoxSetSelectedPos(comboBoxNumPlayers, 0); - comboBoxNumPlayers->winEnable( FALSE ); - - populateQMSideComboBox(pref.getSide(), li); // this will set side to random and disable if necessary - } - else - { - // "Choose a ladder" selected - open overlay - PopulateQMLadderComboBox(); // this restores the non-"Choose a ladder" selection - GameSpyOpenOverlay( GSOVERLAY_LADDERSELECT ); - } - } - } - if (!isInInit) - { - QuickMatchPreferences pref; - populateQuickMatchMapSelectListbox(pref); - UpdateStartButton(); - } - break; - } // case GCM_SELECTED - - case GBM_SELECTED: - { - if (buttonPushed) - break; - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - static NameKeyType buttonOptionsID = NAMEKEY("WOLQuickMatchMenu.wnd:ButtonOptions"); - - if ( controlID == buttonStopID ) - { - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_STOPQUICKMATCH; - TheGameSpyPeerMessageQueue->addRequest(req); - buttonWiden->winEnable( FALSE ); - buttonStart->winHide( FALSE ); - buttonStop->winHide( TRUE ); - enableOptionsGadgets(TRUE); - TheGameSpyInfo->addText(TheGameText->fetch("GUI:QMAborted"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - } - else if ( controlID == buttonOptionsID ) - { - GameWindow *win =TheWindowManager->winGetWindowFromId(parentWOLQuickMatch,buttonOptionsID); - if (isInfoShown()) - { - hideInfoGadgets(TRUE); - hideOptionsGadgets(FALSE); - GadgetButtonSetText(win, TheGameText->fetch("GUI:PlayerInfo")); - } - else - { - hideInfoGadgets(FALSE); - hideOptionsGadgets(TRUE); - GadgetButtonSetText(win, TheGameText->fetch("GUI:Setup")); - } - } - else if ( controlID == buttonWidenID ) - { - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_WIDENQUICKMATCHSEARCH; - TheGameSpyPeerMessageQueue->addRequest(req); - buttonWiden->winEnable( FALSE ); - } - else if ( controlID == buttonStartID ) - { - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_STARTQUICKMATCH; - req.qmMaps.clear(); - - #if VARIABLE_NUMBER_OF_MAPS - for (MapListboxIndex::iterator idxIt = mapListboxIndex.begin(); idxIt != mapListboxIndex.end(); ++idxIt) { - Int index = (*idxIt); - if (index >= 0) - { - req.qmMaps.push_back(GadgetListBoxGetItemData(listboxMapSelect, index, 0)); - } - else - { - req.qmMaps.push_back(false); - } - } - #else - Int numMaps = GadgetListBoxGetNumEntries(listboxMapSelect); - for ( Int i=0; i= maxPingEntries - 1) - { - req.QM.maxPing = TheGameSpyConfig->getPingTimeoutInMs(); - } - else - req.QM.maxPing = (val+1)*100; - - PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(TheGameSpyInfo->getLocalProfileID()); - req.QM.points = CalculateRank(stats); - - Int ladderIndex, index, selected; - GadgetComboBoxGetSelectedPos( comboBoxLadder, &selected ); - ladderIndex = (Int)GadgetComboBoxGetItemData( comboBoxLadder, selected ); - const LadderInfo *ladderInfo = NULL; - if (ladderIndex < 0) - { - ladderIndex = 0; - } - if (ladderIndex) - { - ladderInfo = TheLadderList->findLadderByIndex( ladderIndex ); - if (!ladderInfo) - { - ladderIndex = 0; // sanity - } - } - req.QM.ladderID = ladderIndex; - - req.QM.ladderPassCRC = 0; - - index = -1; - GadgetComboBoxGetSelectedPos( comboBoxSide, &selected ); - if (selected >= 0) - index = (Int)GadgetComboBoxGetItemData( comboBoxSide, selected ); - req.QM.side = index; - if (ladderInfo && ladderInfo->randomFactions) - { - Int sideNum = GameClientRandomValue(0, ladderInfo->validFactions.size()-1); - DEBUG_LOG(("Looking for %d out of %d random sides\n", sideNum, ladderInfo->validFactions.size())); - AsciiStringListConstIterator cit = ladderInfo->validFactions.begin(); - while (sideNum) - { - ++cit; - --sideNum; - } - if (cit != ladderInfo->validFactions.end()) - { - Int numPlayerTemplates = ThePlayerTemplateStore->getPlayerTemplateCount(); - AsciiString sideStr = *cit; - DEBUG_LOG(("Chose %s as our side... finding\n", sideStr.str())); - for (Int c=0; cgetNthPlayerTemplate(c); - if (fac && fac->getSide() == sideStr) - { - DEBUG_LOG(("Found %s in index %d\n", sideStr.str(), c)); - req.QM.side = c; - break; - } - } - } - } - - index = -1; - GadgetComboBoxGetSelectedPos( comboBoxColor, &selected ); - if (selected >= 0) - index = (Int)GadgetComboBoxGetItemData( comboBoxColor, selected ); - req.QM.color = index; - - OptionPreferences natPref; - req.QM.NAT = natPref.getFirewallBehavior(); - - if (ladderIndex) - { - req.QM.numPlayers = (ladderInfo)?ladderInfo->playersPerTeam*2 : 2; - } - else - { - GadgetComboBoxGetSelectedPos(comboBoxNumPlayers, &val); - if (val < 0) - val = 0; - req.QM.numPlayers = (val+1)*2; - } - - Int numDiscons = 0; - PerGeneralMap::iterator it; - for(it =stats.discons.begin(); it != stats.discons.end(); ++it) - { - numDiscons += it->second; - } - for(it =stats.desyncs.begin(); it != stats.desyncs.end(); ++it) - { - numDiscons += it->second; - } - req.QM.discons = numDiscons; - - - strncpy(req.QM.pings, TheGameSpyInfo->getPingString().str(), 17); - req.QM.pings[16] = 0; - - req.QM.botID = TheGameSpyConfig->getQMBotID(); - req.QM.roomID = TheGameSpyConfig->getQMChannel(); - - req.QM.exeCRC = TheGlobalData->m_exeCRC; - req.QM.iniCRC = TheGlobalData->m_iniCRC; - - TheGameSpyPeerMessageQueue->addRequest(req); - buttonWiden->winEnable( FALSE ); - buttonStart->winHide( TRUE ); - buttonStop->winHide( FALSE ); - enableOptionsGadgets(FALSE); - - if (ladderIndex > 0) - { - // save the ladder as being played upon even if we cancel out of matching early... - LadderPreferences ladPref; - ladPref.loadProfile( TheGameSpyInfo->getLocalProfileID() ); - LadderPref p; - p.lastPlayDate = time(NULL); - p.address = ladderInfo->address; - p.port = ladderInfo->port; - p.name = ladderInfo->name; - ladPref.addRecentLadder( p ); - ladPref.write(); - } - } - else if ( controlID == buttonBuddiesID ) - { - GameSpyToggleOverlay( GSOVERLAY_BUDDY ); - } - else if ( controlID == buttonBackID ) - { - buttonPushed = true; - TheGameSpyInfo->leaveGroupRoom(); - nextScreen = "Menus/WOLWelcomeMenu.wnd"; - TheShell->pop(); - } //if ( controlID == buttonBack ) - else if ( controlID == buttonSelectAllMapsID ) - { - Int numMaps = GadgetListBoxGetNumEntries(listboxMapSelect); - for ( Int i=0; iwinGetWindowId(); - Int selected = (Int)mData2; - - if ( controlID == listboxMapSelectID ) - { - const LadderInfo *li = getLadderInfo(); - if (selected >= 0 && (!li || !li->randomMaps)) - { - Bool wasSelected = (Bool)GadgetListBoxGetItemData(control, selected, 0); - GadgetListBoxSetItemData(control, (void *)(!wasSelected), selected, 0); - Int width = 10; - Int height = 10; - const Image *img = (!wasSelected)?selectedImage:unselectedImage; - if ( img ) - { - width = min(GadgetListBoxGetColumnWidth(control, 0), img->getImageWidth()); - height = width; - } - GadgetListBoxAddEntryImage(control, img, selected, 0, height, width); - GadgetListBoxAddEntryText(control, GadgetListBoxGetText(control, selected, 1), GameSpyColor[(wasSelected)?GSCOLOR_MAP_UNSELECTED:GSCOLOR_MAP_SELECTED], selected, 1); - } - if (selected >= 0) - GadgetListBoxSetSelected(control, -1); - } - UpdateStartButton(); - break; - }// case GLM_SELECTED - - case GEM_EDIT_DONE: - { - break; - } - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLQuickMatchMenuSystem diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLStatusMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLStatusMenu.cpp deleted file mode 100644 index 87f13e7dcf1..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLStatusMenu.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLLoginMenu.cpp -// Author: Chris Huybregts, November 2001 -// Description: Lan Lobby Menu -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetTextEntry.h" -//#include "GameNetwork/WOL.h" -//#include "GameNetwork/WOLmenus.h" - - - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentWOLStatusID = NAMEKEY_INVALID; -static NameKeyType buttonDisconnectID = NAMEKEY_INVALID; - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentWOLStatus = NULL; -static GameWindow *buttonDisconnect = NULL; -GameWindow *progressTextWindow = NULL; - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Status Menu */ -//------------------------------------------------------------------------------------------------- -void WOLStatusMenuInit( WindowLayout *layout, void *userData ) -{ - parentWOLStatusID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLStatusMenu.wnd:WOLStatusMenuParent" ) ); - buttonDisconnectID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLStatusMenu.wnd:ButtonDisconnect" ) ); - parentWOLStatus = TheWindowManager->winGetWindowFromId( NULL, parentWOLStatusID ); - buttonDisconnect = TheWindowManager->winGetWindowFromId( NULL, buttonDisconnectID); - - progressTextWindow = TheWindowManager->winGetWindowFromId( NULL, - TheNameKeyGenerator->nameToKey( AsciiString( "WOLStatusMenu.wnd:ListboxStatus" ) ) ); - - // Show Menu - layout->hide( FALSE ); - - // Set Keyboard to Main Parent - TheWindowManager->winSetFocus( parentWOLStatus ); - - //progressLayout = TheShell->top(); - - //WOL::raiseWOLMessageBox(); -} // WOLStatusMenuInit - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLStatusMenuShutdown( WindowLayout *layout, void *userData ) -{ - - // hide menu - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout ); - - //progressLayout = NULL; - - //WOL::raiseWOLMessageBox(); -} // WOLStatusMenuShutdown - - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLStatusMenuUpdate( WindowLayout * layout, void *userData) -{ - //if (WOL::TheWOL) - //WOL::TheWOL->update(); -}// WOLStatusMenuUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLStatusMenuInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonDisconnect, buttonDisconnectID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// WOLStatusMenuInput - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLStatusMenuSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - - switch( msg ) - { - - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - case GBM_SELECTED: - { - /* - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if ( controlID == buttonDisconnectID ) - { - //TheShell->pop(); - if (WOL::TheWOL->setState( WOL::WOLAPI_FATAL_ERROR )) - { - WOL::TheWOL->addCommand( WOL::WOLCOMMAND_RESET ); // don't display an error, log out, or anything - } - - } //if ( controlID == buttonDisconnect ) - */ - break; - }// case GBM_SELECTED: - - case GEM_EDIT_DONE: - { - break; - } - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLStatusMenuSystem diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLWelcomeMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLWelcomeMenu.cpp deleted file mode 100644 index 9721fee7a36..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLWelcomeMenu.cpp +++ /dev/null @@ -1,893 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLWelcomeMenu.cpp -// Author: Chris Huybregts, November 2001 -// Description: Lan Lobby Menu -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "GameSpy/peer/peer.h" - -#include "Common/GameEngine.h" -#include "Common/GameSpyMiscPreferences.h" -#include "Common/CustomMatchPreferences.h" -#include "Common/GlobalData.h" -#include "Common/UserPreferences.h" - -#include "GameClient/AnimateWindowManager.h" -#include "GameClient/Display.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/GameText.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/MessageBox.h" -#include "GameClient/GameWindowTransitions.h" - -#include "GameNetwork/FirewallHelper.h" -#include "GameNetwork/GameSpyOverlay.h" - -#include "GameNetwork/GameSpy/BuddyDefs.h" -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PersistentStorageDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/ThreadUtils.h" -#include "GameNetwork/GameSpy/MainMenuUtils.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -static Bool isShuttingDown = FALSE; -static Bool buttonPushed = FALSE; -static char *nextScreen = NULL; - -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentWOLWelcomeID = NAMEKEY_INVALID; -static NameKeyType buttonBackID = NAMEKEY_INVALID; -static NameKeyType buttonQuickMatchID = NAMEKEY_INVALID; -static NameKeyType buttonLobbyID = NAMEKEY_INVALID; -static NameKeyType buttonBuddiesID = NAMEKEY_INVALID; -static NameKeyType buttonLadderID = NAMEKEY_INVALID; -static NameKeyType buttonMyInfoID = NAMEKEY_INVALID; - -static NameKeyType listboxInfoID = NAMEKEY_INVALID; -static NameKeyType buttonOptionsID = NAMEKEY_INVALID; -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentWOLWelcome = NULL; -static GameWindow *buttonBack = NULL; -static GameWindow *buttonQuickMatch = NULL; -static GameWindow *buttonLobby = NULL; -static GameWindow *buttonBuddies = NULL; -static GameWindow *buttonLadder = NULL; -static GameWindow *buttonMyInfo = NULL; -static GameWindow *buttonbuttonOptions = NULL; -static WindowLayout *welcomeLayout = NULL; -static GameWindow *listboxInfo = NULL; - -static GameWindow *staticTextServerName = NULL; -static GameWindow *staticTextLastUpdated = NULL; - -static GameWindow *staticTextLadderWins = NULL; -static GameWindow *staticTextLadderLosses = NULL; -static GameWindow *staticTextLadderRank = NULL; -static GameWindow *staticTextLadderPoints = NULL; -static GameWindow *staticTextLadderDisconnects = NULL; - -static GameWindow *staticTextHighscoreWins = NULL; -static GameWindow *staticTextHighscoreLosses = NULL; -static GameWindow *staticTextHighscoreRank = NULL; -static GameWindow *staticTextHighscorePoints = NULL; - -static UnicodeString gServerName; -void updateServerDisplay(UnicodeString serverName) -{ - if (staticTextServerName) - { - GadgetStaticTextSetText(staticTextServerName, serverName); - } - gServerName = serverName; -} - -/* -void updateLocalPlayerScores(AsciiString name, const WOL::Ladder *ladder, const WOL::Highscore *highscore) -{ - if (ladder) - { - AsciiString a; - UnicodeString u; - - a.format("%d", ladder->wins); - u.translate(a); - GadgetStaticTextSetText(staticTextLadderWins, u); - - a.format("%d", ladder->losses); - u.translate(a); - GadgetStaticTextSetText(staticTextLadderLosses, u); - - a.format("%d", ladder->rank); - u.translate(a); - GadgetStaticTextSetText(staticTextLadderRank, u); - - a.format("%d", ladder->points); - u.translate(a); - GadgetStaticTextSetText(staticTextLadderPoints, u); - - a.format("%d", ladder->disconnects); - u.translate(a); - GadgetStaticTextSetText(staticTextLadderDisconnects, u); - } - if (highscore) - { - AsciiString a; - UnicodeString u; - - a.format("%d", highscore->wins); - u.translate(a); - GadgetStaticTextSetText(staticTextHighscoreWins, u); - - a.format("%d", highscore->losses); - u.translate(a); - GadgetStaticTextSetText(staticTextHighscoreLosses, u); - - a.format("%d", highscore->rank); - u.translate(a); - GadgetStaticTextSetText(staticTextHighscoreRank, u); - - a.format("%d", highscore->points); - u.translate(a); - GadgetStaticTextSetText(staticTextHighscorePoints, u); - } -} -*/ - - -static void enableControls( Bool state ) -{ -#ifndef _PLAYTEST - if (buttonQuickMatch) - buttonQuickMatch->winEnable(state); -#else - if (buttonQuickMatch) - buttonQuickMatch->winEnable(FALSE); -#endif - if (buttonLobby) - buttonLobby->winEnable(state); -} - -//------------------------------------------------------------------------------------------------- -/** This is called when a shutdown is complete for this menu */ -//------------------------------------------------------------------------------------------------- -static void shutdownComplete( WindowLayout *layout ) -{ - - isShuttingDown = FALSE; - - // hide the layout - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout, (nextScreen != NULL) ); - - if (nextScreen != NULL) - { - TheShell->push(nextScreen); - } - - nextScreen = NULL; - -} // end if - -//------------------------------------------------------------------------------------------------- -/** Handle Num Players Online data */ -//------------------------------------------------------------------------------------------------- - -static Int lastNumPlayersOnline = 0; - -static UnsignedByte grabUByte(const char *s) -{ - char tmp[5] = "0xff"; - tmp[2] = s[0]; - tmp[3] = s[1]; - UnsignedByte b = strtol(tmp, NULL, 16); - return b; -} - -static void updateNumPlayersOnline(void) -{ - GameWindow *playersOnlineWindow = TheWindowManager->winGetWindowFromId( - NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextNumPlayersOnline") ); - - if (playersOnlineWindow) - { - UnicodeString valStr; - valStr.format(TheGameText->fetch("GUI:NumPlayersOnline"), lastNumPlayersOnline); - GadgetStaticTextSetText(playersOnlineWindow, valStr); - } - - if (listboxInfo && TheGameSpyInfo) - { - GadgetListBoxReset(listboxInfo); - AsciiString aLine; - UnicodeString line; - AsciiString aMotd = TheGameSpyInfo->getMOTD(); - UnicodeString headingStr; - headingStr.format(TheGameText->fetch("MOTD:NumPlayersHeading"), lastNumPlayersOnline); - - while (headingStr.nextToken(&line, UnicodeString(L"\n"))) - { - if (line.getCharAt(line.getLength()-1) == '\r') - line.removeLastChar(); // there is a trailing '\r' - - line.trim(); - - if (line.isEmpty()) - { - line = UnicodeString(L" "); - } - - GadgetListBoxAddEntryText(listboxInfo, line, GameSpyColor[GSCOLOR_MOTD_HEADING], -1, -1); - } - GadgetListBoxAddEntryText(listboxInfo, UnicodeString(L" "), GameSpyColor[GSCOLOR_MOTD_HEADING], -1, -1); - - while (aMotd.nextToken(&aLine, "\n")) - { - if (aLine.getCharAt(aLine.getLength()-1) == '\r') - aLine.removeLastChar(); // there is a trailing '\r' - - aLine.trim(); - - if (aLine.isEmpty()) - { - aLine = " "; - } - - Color c = GameSpyColor[GSCOLOR_MOTD]; - if (aLine.startsWith("\\\\")) - { - aLine = aLine.str()+1; - } - else if (aLine.startsWith("\\") && aLine.getLength() > 9) - { - // take out the hex value from strings starting as "\ffffffffText" - UnsignedByte a, r, g, b; - a = grabUByte(aLine.str()+1); - r = grabUByte(aLine.str()+3); - g = grabUByte(aLine.str()+5); - b = grabUByte(aLine.str()+7); - c = GameMakeColor(r, g, b, a); - DEBUG_LOG(("MOTD line '%s' has color %X\n", aLine.str(), c)); - aLine = aLine.str() + 9; - } - line = UnicodeString(MultiByteToWideCharSingleLine(aLine.str()).c_str()); - - GadgetListBoxAddEntryText(listboxInfo, line, c, -1, -1); - } - } -} - -void HandleNumPlayersOnline( Int numPlayersOnline ) -{ - lastNumPlayersOnline = numPlayersOnline; - if (lastNumPlayersOnline < 1) - lastNumPlayersOnline = 1; - updateNumPlayersOnline(); -} - -//------------------------------------------------------------------------------------------------- -/** Handle Overall Stats data */ -//------------------------------------------------------------------------------------------------- - -static OverallStats s_statsUSA, s_statsChina, s_statsGLA; - -OverallStats::OverallStats() -{ - for (Int i=0; ifetch("GUI:PerSideWinPercentage"), REAL_TO_INT(val), sideStr.str()); - - /* - Int totalDenominator = s_statsUSA.wins[n] + s_statsChina.wins[n] + s_statsGLA.wins[n]; - if (!totalDenominator) - totalDenominator = 1; - - UnicodeString s; - s.format(TheGameText->fetch("GUI:PerSideWinPercentage"), REAL_TO_INT(stats.wins[n]*100/totalDenominator), sideStr.str()); - */ - return s; -} - -static void updateOverallStats(void) -{ - UnicodeString usa, china, gla; - GameWindow *win; - - usa = calcPercent(s_statsUSA, STATS_LASTWEEK, TheGameText->fetch("SIDE:America")); - china = calcPercent(s_statsChina, STATS_LASTWEEK, TheGameText->fetch("SIDE:China")); - gla = calcPercent(s_statsGLA, STATS_LASTWEEK, TheGameText->fetch("SIDE:GLA")); - DEBUG_LOG(("Last Week: %ls %ls %ls\n", usa.str(), china.str(), gla.str())); - win = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextUSALastWeek") ); - GadgetStaticTextSetText(win, usa); - win = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextChinaLastWeek") ); - GadgetStaticTextSetText(win, china); - win = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextGLALastWeek") ); - GadgetStaticTextSetText(win, gla); - - usa = calcPercent(s_statsUSA, STATS_TODAY, TheGameText->fetch("SIDE:America")); - china = calcPercent(s_statsChina, STATS_TODAY, TheGameText->fetch("SIDE:China")); - gla = calcPercent(s_statsGLA, STATS_TODAY, TheGameText->fetch("SIDE:GLA")); - DEBUG_LOG(("Today: %ls %ls %ls\n", usa.str(), china.str(), gla.str())); - win = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextUSAToday") ); - GadgetStaticTextSetText(win, usa); - win = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextChinaToday") ); - GadgetStaticTextSetText(win, china); - win = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextGLAToday") ); - GadgetStaticTextSetText(win, gla); -} - -void HandleOverallStats( const OverallStats& USA, const OverallStats& China, const OverallStats& GLA ) -{ - s_statsUSA = USA; - s_statsChina = China; - s_statsGLA = GLA; - updateOverallStats(); -} - -//------------------------------------------------------------------------------------------------- -/** Handle player stats */ -//------------------------------------------------------------------------------------------------- - -void UpdateLocalPlayerStats(void) -{ - - GameWindow *welcomeParent = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:WOLWelcomeMenuParent") ); - - if (welcomeParent) - { - PopulatePlayerInfoWindows( "WOLWelcomeMenu.wnd" ); - } - else - { - PopulatePlayerInfoWindows( "WOLQuickMatchMenu.wnd" ); - } - - return; -} - -static Bool raiseMessageBoxes = FALSE; -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Welcome Menu */ -//------------------------------------------------------------------------------------------------- -void WOLWelcomeMenuInit( WindowLayout *layout, void *userData ) -{ - nextScreen = NULL; - buttonPushed = FALSE; - isShuttingDown = FALSE; - - welcomeLayout = layout; - - //TheWOL->reset(); - - parentWOLWelcomeID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:WOLWelcomeMenuParent" ) ); - buttonBackID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonBack" ) ); - parentWOLWelcome = TheWindowManager->winGetWindowFromId( NULL, parentWOLWelcomeID ); - buttonBack = TheWindowManager->winGetWindowFromId( NULL, buttonBackID); - buttonOptionsID = TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:ButtonOptions" ); - buttonbuttonOptions = TheWindowManager->winGetWindowFromId( NULL, buttonOptionsID); - listboxInfoID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:InfoListbox" ) ); - - listboxInfo = TheWindowManager->winGetWindowFromId( NULL, listboxInfoID); - - staticTextServerName = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextServerName" )); - staticTextLastUpdated = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLastUpdated" )); - - staticTextLadderWins = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLadderWins" )); - staticTextLadderLosses = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLadderLosses" )); - staticTextLadderPoints = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLadderPoints" )); - staticTextLadderRank = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLadderRank" )); - staticTextLadderDisconnects = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextDisconnects" )); - - staticTextHighscoreWins = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextHighscoreWins" )); - staticTextHighscoreLosses = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextHighscoreLosses" )); - staticTextHighscorePoints = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextHighscorePoints" )); - staticTextHighscoreRank = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextHighscoreRank" )); - - if (staticTextServerName) - { - GadgetStaticTextSetText(staticTextServerName, gServerName); - } - - GameWindow *staticTextTitle = TheWindowManager->winGetWindowFromId(parentWOLWelcome, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextTitle")); - if (staticTextTitle && TheGameSpyInfo) - { - UnicodeString title; - title.format(TheGameText->fetch("GUI:WOLWelcome"), TheGameSpyInfo->getLocalBaseName().str()); - GadgetStaticTextSetText(staticTextTitle, title); - } - - // Clear some defaults - /* - UnicodeString questionMark = UnicodeString(L"?"); - GadgetStaticTextSetText(staticTextLastUpdated, questionMark); - GadgetStaticTextSetText(staticTextLadderWins, questionMark); - GadgetStaticTextSetText(staticTextLadderLosses, questionMark); - GadgetStaticTextSetText(staticTextLadderPoints, questionMark); - GadgetStaticTextSetText(staticTextLadderRank, questionMark); - GadgetStaticTextSetText(staticTextLadderDisconnects, questionMark); - GadgetStaticTextSetText(staticTextHighscoreWins, questionMark); - GadgetStaticTextSetText(staticTextHighscoreLosses, questionMark); - GadgetStaticTextSetText(staticTextHighscorePoints, questionMark); - GadgetStaticTextSetText(staticTextHighscoreRank, questionMark); - */ - - //DEBUG_ASSERTCRASH(listboxInfo, ("No control found!")); - - buttonQuickMatchID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonQuickMatch" ) ); - buttonQuickMatch = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonQuickMatchID ); - - buttonLobbyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonCustomMatch" ) ); - buttonLobby = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonLobbyID ); - - buttonBuddiesID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonBuddies" ) ); - buttonBuddies = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonBuddiesID ); - - buttonMyInfoID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonMyInfo" ) ); - buttonMyInfo = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonMyInfoID ); - - buttonLadderID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonLadder" ) ); - buttonLadder = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonLadderID ); - - if (TheFirewallHelper == NULL) { - TheFirewallHelper = createFirewallHelper(); - } - if (TheFirewallHelper->detectFirewall() == TRUE) { - // don't need to detect firewall, already been done. - delete TheFirewallHelper; - TheFirewallHelper = NULL; - } - /* - - if (TheGameSpyChat && TheGameSpyChat->isConnected()) - { - const char *keys[3] = { "locale", "wins", "losses" }; - char valueStrings[3][20]; - char *values[3] = { valueStrings[0], valueStrings[1], valueStrings[2] }; - _snprintf(values[0], 20, "%s", TheGameSpyPlayerInfo->getLocale().str()); - _snprintf(values[1], 20, "%d", TheGameSpyPlayerInfo->getWins()); - _snprintf(values[2], 20, "%d", TheGameSpyPlayerInfo->getLosses()); - peerSetGlobalKeys(TheGameSpyChat->getPeer(), 3, (const char **)keys, (const char **)values); - peerSetGlobalWatchKeys(TheGameSpyChat->getPeer(), GroupRoom, 3, keys, PEERFalse); - peerSetGlobalWatchKeys(TheGameSpyChat->getPeer(), StagingRoom, 3, keys, PEERFalse); - } - */ - -// // animate controls -// TheShell->registerWithAnimateManager(buttonQuickMatch, WIN_ANIMATION_SLIDE_LEFT, TRUE, 800); -// TheShell->registerWithAnimateManager(buttonLobby, WIN_ANIMATION_SLIDE_LEFT, TRUE, 600); -// //TheShell->registerWithAnimateManager(NULL, WIN_ANIMATION_SLIDE_LEFT, TRUE, 400); -// TheShell->registerWithAnimateManager(buttonBuddies, WIN_ANIMATION_SLIDE_LEFT, TRUE, 200); -// //TheShell->registerWithAnimateManager(NULL, WIN_ANIMATION_SLIDE_LEFT, TRUE, 1); -// TheShell->registerWithAnimateManager(buttonBack, WIN_ANIMATION_SLIDE_BOTTOM, TRUE, 1); - - // Show Menu - layout->hide( FALSE ); - - // Set Keyboard to Main Parent - TheWindowManager->winSetFocus( parentWOLWelcome ); - - enableControls( TheGameSpyInfo->gotGroupRoomList() ); - TheShell->showShellMap(TRUE); - - updateNumPlayersOnline(); - updateOverallStats(); - - UpdateLocalPlayerStats(); - - GameSpyMiscPreferences cPref; - if (cPref.getLocale() < LOC_MIN || cPref.getLocale() > LOC_MAX) - { - GameSpyOpenOverlay(GSOVERLAY_LOCALESELECT); - } - - raiseMessageBoxes = TRUE; - TheTransitionHandler->setGroup("WOLWelcomeMenuFade"); - -} // WOLWelcomeMenuInit - -//------------------------------------------------------------------------------------------------- -/** WOL Welcome Menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLWelcomeMenuShutdown( WindowLayout *layout, void *userData ) -{ - listboxInfo = NULL; - - if (TheFirewallHelper != NULL) { - delete TheFirewallHelper; - TheFirewallHelper = NULL; - } - - isShuttingDown = TRUE; - - // if we are shutting down for an immediate pop, skip the animations - Bool popImmediate = *(Bool *)userData; - if( popImmediate ) - { - - shutdownComplete( layout ); - return; - - } //end if - - TheShell->reverseAnimatewindow(); - TheTransitionHandler->reverse("WOLWelcomeMenuFade"); - - - RaiseGSMessageBox(); -} // WOLWelcomeMenuShutdown - - -//------------------------------------------------------------------------------------------------- -/** WOL Welcome Menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLWelcomeMenuUpdate( WindowLayout * layout, void *userData) -{ - // We'll only be successful if we've requested to - if(isShuttingDown && TheShell->isAnimFinished() && TheTransitionHandler->isFinished()) - shutdownComplete(layout); - - if (raiseMessageBoxes) - { - RaiseGSMessageBox(); - raiseMessageBoxes = FALSE; - } - - if (TheFirewallHelper != NULL) - { - if (TheFirewallHelper->behaviorDetectionUpdate()) - { - TheWritableGlobalData->m_firewallBehavior = TheFirewallHelper->getFirewallBehavior(); - - TheFirewallHelper->writeFirewallBehavior(); - - TheFirewallHelper->flagNeedToRefresh(FALSE); // 2/19/03 BGC, we're done, so we don't need to refresh the NAT anymore. - - // we are now done with the firewall helper - delete TheFirewallHelper; - TheFirewallHelper = NULL; - } - } - - if (TheShell->isAnimFinished() && !buttonPushed && TheGameSpyPeerMessageQueue) - { - HandleBuddyResponses(); - HandlePersistentStorageResponses(); - - Int allowedMessages = TheGameSpyInfo->getMaxMessagesPerUpdate(); - Bool sawImportantMessage = FALSE; - PeerResponse resp; - while (allowedMessages-- && !sawImportantMessage && TheGameSpyPeerMessageQueue->getResponse( resp )) - { - switch (resp.peerResponseType) - { - case PeerResponse::PEERRESPONSE_GROUPROOM: - { - GameSpyGroupRoom room; - room.m_groupID = resp.groupRoom.id; - room.m_maxWaiting = resp.groupRoom.maxWaiting; - room.m_name = resp.groupRoomName.c_str(); - room.m_translatedName = UnicodeString(L"TEST"); - room.m_numGames = resp.groupRoom.numGames; - room.m_numPlaying = resp.groupRoom.numPlaying; - room.m_numWaiting = resp.groupRoom.numWaiting; - TheGameSpyInfo->addGroupRoom( room ); - if (room.m_groupID == 0) - { - enableControls( TRUE ); - } - } - break; - case PeerResponse::PEERRESPONSE_JOINGROUPROOM: - { - sawImportantMessage = TRUE; - enableControls( TRUE ); - if (resp.joinGroupRoom.ok) - { - //buttonPushed = TRUE; - TheGameSpyInfo->setCurrentGroupRoom(resp.joinGroupRoom.id); - //GSMessageBoxOk( TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSGroupRoomJoinOK") ); - - buttonPushed = TRUE; - nextScreen = "Menus/WOLCustomLobby.wnd"; - TheShell->pop(); - //TheShell->push( "Menus/WOLCustomLobby.wnd" ); - } - else - { - GSMessageBoxOk( TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSGroupRoomJoinFail") ); - } - } - break; - case PeerResponse::PEERRESPONSE_DISCONNECT: - { - sawImportantMessage = TRUE; - UnicodeString title, body; - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", resp.discon.reason); - title = TheGameText->fetch( "GUI:GSErrorTitle" ); - body = TheGameText->fetch( disconMunkee ); - GameSpyCloseAllOverlays(); - GSMessageBoxOk( title, body ); - TheShell->pop(); - } - break; - } - } - } - -}// WOLWelcomeMenuUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Welcome Menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLWelcomeMenuInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - if (buttonPushed) - break; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonBack, buttonBackID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// WOLWelcomeMenuInput - -//------------------------------------------------------------------------------------------------- -/** WOL Welcome Menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLWelcomeMenuSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - - switch( msg ) - { - - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - case GBM_SELECTED: - { - if (buttonPushed) - break; - - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if ( controlID == buttonBackID ) - { - //DEBUG_ASSERTCRASH(TheGameSpyChat->getPeer(), ("No GameSpy Peer object!")); - //TheGameSpyChat->disconnectFromChat(); - - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_LOGOUT; - TheGameSpyPeerMessageQueue->addRequest( req ); - BuddyRequest breq; - breq.buddyRequestType = BuddyRequest::BUDDYREQUEST_LOGOUT; - TheGameSpyBuddyMessageQueue->addRequest( breq ); - - DEBUG_LOG(("Tearing down GameSpy from WOLWelcomeMenuSystem(GBM_SELECTED)\n")); - TearDownGameSpy(); - - /* - if (TheGameSpyChat->getPeer()) - { - peerDisconnect(TheGameSpyChat->getPeer()); - } - */ - - buttonPushed = TRUE; - - TheShell->pop(); - - /// @todo: log out instead of disconnecting - //TheWOL->addCommand( WOL::WOLCOMMAND_LOGOUT ); - /** - closeAllOverlays(); - TheShell->pop(); - delete TheWOL; - TheWOL = NULL; - delete TheWOLGame; - TheWOLGame = NULL; - **/ - - } //if ( controlID == buttonBack ) - else if (controlID == buttonOptionsID) - { - GameSpyOpenOverlay( GSOVERLAY_OPTIONS ); - } - else if (controlID == buttonQuickMatchID) - { - GameSpyMiscPreferences mPref; - if ((TheDisplay->getWidth() != 800 || TheDisplay->getHeight() != 600) && mPref.getQuickMatchResLocked()) - { - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:QuickMatch800x600")); - } - else - { - buttonPushed = TRUE; - nextScreen = "Menus/WOLQuickMatchMenu.wnd"; - TheShell->pop(); - } - }// else if - else if (controlID == buttonMyInfoID ) - { - SetLookAtPlayer(TheGameSpyInfo->getLocalProfileID(), TheGameSpyInfo->getLocalName()); - GameSpyToggleOverlay(GSOVERLAY_PLAYERINFO); - } - else if (controlID == buttonLobbyID) - { - //TheGameSpyChat->clearGroupRoomList(); - //peerListGroupRooms(TheGameSpyChat->getPeer(), ListGroupRoomsCallback, NULL, PEERTrue); - TheGameSpyInfo->joinBestGroupRoom(); - enableControls( FALSE ); - - - /* - TheWOL->setScreen(WOL::WOLAPI_MENU_CUSTOMLOBBY); - TheWOL->setGameMode(WOL::WOLTYPE_CUSTOM); - TheWOL->setState( WOL::WOLAPI_LOBBY ); - TheWOL->addCommand( WOL::WOLCOMMAND_REFRESH_CHANNELS ); - */ - }// else if - else if (controlID == buttonBuddiesID) - { - GameSpyToggleOverlay( GSOVERLAY_BUDDY ); - /* - Bool joinedRoom = FALSE; - ClearGroupRoomList(); - peerJoinTitleRoom(TheGameSpyChat->getPeer(), JoinRoomCallback, &joinedRoom, PEERTrue); - if (joinedRoom) - { - GameSpyUsingGroupRooms = FALSE; - GameSpyCurrentGroupRoomID = 0; - TheShell->pop(); - TheShell->push("Menus/WOLCustomLobby.wnd"); - } - else - { - GameSpyCurrentGroupRoomID = 0; - GSMessageBoxOk(UnicodeString(L"Oops"), UnicodeString(L"Unable to join title room"), NULL); - } - */ - } - else if (controlID == buttonLadderID) - { - TheShell->push(AsciiString("Menus/WOLLadderScreen.wnd")); - } - break; - }// case GBM_SELECTED: - - case GEM_EDIT_DONE: - { - break; - } - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLWelcomeMenuSystem diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp index d7a48d406e4..16fcdc80557 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp @@ -84,8 +84,6 @@ #include "GameLogic/FPUControl.h" #include "GameLogic/GameLogic.h" #include "GameNetwork/NetworkInterface.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" #include "GameClient/CampaignManager.h" #include "GameNetwork/RankPointValue.h" #include "GameClient/GameWindowTransitions.h" @@ -885,327 +883,6 @@ void MultiPlayerLoadScreen::processProgress(Int playerId, Int percentage) GadgetProgressBarSetProgress(m_progressBars[m_playerLookup[playerId]], percentage ); } -// GameSpyLoadScreen Class ////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -GameSpyLoadScreen::GameSpyLoadScreen( void ) -{ - - // Added By Sadullah Nader - // Initializations missing and needed - m_mapPreview = NULL; - // - - for(Int i = 0; i < MAX_SLOTS; ++i) - { - - // Added By Sadullah Nader - // Initializations missing and needed - m_buttonMapStartPosition[i] = NULL; - m_playerRank[i] = NULL; - // - - m_playerOfficerMedal[i] = NULL; - m_progressBars[i] = NULL; - m_playerNames[i] = NULL; - m_playerSide[i]= NULL; - m_playerLookup[i] = -1; - m_playerFavoriteFactions[i]= NULL; - m_playerTotalDisconnects[i]= NULL; - m_playerWin[i]= NULL; - m_playerWinLosses[i]= NULL; - } -} - -GameSpyLoadScreen::~GameSpyLoadScreen( void ) -{ - for(Int i = 0; i < MAX_SLOTS; ++i) - { - m_progressBars[i] = NULL; - m_playerNames[i] = NULL; - m_playerSide[i]= NULL; - m_playerLookup[i] = -1; - m_playerFavoriteFactions[i]= NULL; - m_playerTotalDisconnects[i]= NULL; - m_playerWin[i]= NULL; - m_playerWinLosses[i]= NULL; - } -} - -extern Int GetAdditionalDisconnectsFromUserFile(Int playerID); - -void GameSpyLoadScreen::init( GameInfo *game ) -{ - // create the layout of the load screen - m_loadScreen = TheWindowManager->winCreateFromScript( AsciiString( "Menus/GameSpyLoadScreen.wnd" ) ); - DEBUG_ASSERTCRASH(m_loadScreen, ("Can't initialize the Multiplayer loadscreen")); - m_loadScreen->winHide(FALSE); - m_loadScreen->winBringToTop(); - m_mapPreview = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "GameSpyLoadScreen.wnd:WinMapPreview")); - DEBUG_ASSERTCRASH(TheNetwork, ("Where the Heck is the Network!!!!")); - DEBUG_LOG(("NumPlayers %d\n", TheNetwork->getNumPlayers())); -GameSlot *lSlot = game->getSlot(game->getLocalSlotNum()); - const PlayerTemplate* pt; - if (lSlot->getPlayerTemplate() >= 0) - pt = ThePlayerTemplateStore->getNthPlayerTemplate(lSlot->getPlayerTemplate()); - else - pt = ThePlayerTemplateStore->findPlayerTemplate( TheNameKeyGenerator->nameToKey("FactionObserver") ); - const Image *loadScreenImage = TheMappedImageCollection->findImageByName(pt->getLoadScreen()); - if(loadScreenImage) - m_loadScreen->winSetEnabledImage(0, loadScreenImage); - - GameWindow *teamWin[MAX_SLOTS]; - for (Int i = 0; i < MAX_SLOTS; ++i) - { - teamWin[i] = NULL; - } - - Int netSlot = 0; - // Loop through and make the loadscreen look all good. - for (i = 0; i < MAX_SLOTS; ++i) - { - // Load the Progress Bar - AsciiString winName; - winName.format( "GameSpyLoadScreen.wnd:ProgressLoad%d",i); - m_progressBars[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName )); - DEBUG_ASSERTCRASH(m_progressBars[i], ("Can't initialize the progressbars for the GameSpyLoadScreen loadscreen")); - // set the progressbar to zero - GadgetProgressBarSetProgress(m_progressBars[i], 0 ); - - // Load the Player's name - winName.format( "GameSpyLoadScreen.wnd:StaticTextPlayer%d",i); - m_playerNames[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName )); - DEBUG_ASSERTCRASH(m_playerNames[i], ("Can't initialize the Names for the GameSpyLoadScreen loadscreen")); - - // Load MapStart Positions - winName.format( "GameSpyLoadScreen.wnd:ButtonMapStartPosition%d",i); - m_buttonMapStartPosition[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName )); - DEBUG_ASSERTCRASH(m_buttonMapStartPosition[i], ("Can't initialize the MapStart Positions for the GameSpyLoadScreen loadscreen")); - - - // Load the Player's Side - winName.format( "GameSpyLoadScreen.wnd:StaticTextSide%d",i); - m_playerSide[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName )); - DEBUG_ASSERTCRASH(m_playerSide[i], ("Can't initialize the Sides for the GameSpyLoadScreen loadscreen")); - - // Load the Player's window - winName.format( "GameSpyLoadScreen.wnd:WinPlayer%d",i); - m_playerWin[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName )); - DEBUG_ASSERTCRASH(m_playerWin[i], ("Can't initialize the WinPlayer for the GameSpyLoadScreen loadscreen")); - - // Load the Player's m_playerTotalDisconnects - winName.format( "GameSpyLoadScreen.wnd:StaticTextTotalDisconnects%d",i); - m_playerTotalDisconnects[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName )); - DEBUG_ASSERTCRASH(m_playerTotalDisconnects[i], ("Can't initialize the m_playerTotalDisconnects for the GameSpyLoadScreen loadscreen")); - -// // Load the Player's m_playerFavoriteFactions -// winName.format( "GameSpyLoadScreen.wnd:StaticTextFavoriteFaction%d",i); -// m_playerFavoriteFactions[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName )); -// DEBUG_ASSERTCRASH(m_playerFavoriteFactions[i], ("Can't initialize the StaticTextFavoriteFaction for the GameSpyLoadScreen loadscreen")); - - // Load the Player's m_playerWinLosses - winName.format( "GameSpyLoadScreen.wnd:StaticTextWinLoss%d",i); - m_playerWinLosses[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName )); - DEBUG_ASSERTCRASH(m_playerWinLosses[i], ("Can't initialize the m_playerWinLosses for the GameSpyLoadScreen loadscreen")); - - // Load the Player's m_playerWinLosses - winName.format( "GameSpyLoadScreen.wnd:WinRank%d",i); - m_playerRank[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName )); - DEBUG_ASSERTCRASH(m_playerRank[i], ("Can't initialize the m_playerRank for the GameSpyLoadScreen loadscreen")); - - // Load the Player's m_playerOfficerMedal - winName.format( "GameSpyLoadScreen.wnd:WinOfficer%d",i); - m_playerOfficerMedal[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName )); - DEBUG_ASSERTCRASH(m_playerOfficerMedal[i], ("Can't initialize the m_playerOfficerMedal for the GameSpyLoadScreen loadscreen")); - - winName.format( "MultiplayerLoadScreen.wnd:StaticTextTeam%d",i); - teamWin[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName )); - - // get the slot man! - GameSpyGameSlot *slot = (GameSpyGameSlot *)game->getSlot(i); - if (!slot || !slot->isOccupied()) - continue; - Color houseColor = TheMultiplayerSettings->getColor(slot->getApparentColor())->getColor(); - GadgetProgressBarSetEnabledBarColor(m_progressBars[netSlot],houseColor ); - - UnicodeString name = slot->getName(); - GadgetStaticTextSetText(m_playerNames[netSlot], name ); - m_playerNames[netSlot]->winSetEnabledTextColors(houseColor, m_playerNames[netSlot]->winGetEnabledTextBorderColor()); - - // Get the stats for the player - PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(slot->getProfileID()); - DEBUG_LOG(("LoadScreen - populating info for %ls(%d) - stats returned id %d\n", - slot->getName().str(), slot->getProfileID(), stats.id)); - - Bool isPreorder = TheGameSpyInfo->didPlayerPreorder(stats.id); - Int rankPoints = CalculateRank(stats); - Int favSide = GetFavoriteSide(stats); - const Image *preorderImg = TheMappedImageCollection->findImageByName("OfficersClubsmall"); - if (!isPreorder) - preorderImg = NULL; - const Image *rankImg = LookupSmallRankImage(favSide, rankPoints); - m_playerOfficerMedal[i]->winSetEnabledImage(0, preorderImg); - m_playerRank[i]->winSetEnabledImage(0, rankImg); - - UnicodeString formatString; - - // pop wins and losses - Int numLosses = 0; - PerGeneralMap::iterator it; - for(it = stats.losses.begin(); it != stats.losses.end(); ++it) - { - numLosses += it->second; - } - Int numWins = 0; - for(it =stats.wins.begin(); it != stats.wins.end(); ++it) - { - numWins += it->second; - } - formatString.format(L"%d/%d", numWins, numLosses); - GadgetStaticTextSetText(m_playerWinLosses[netSlot], formatString); - m_playerWinLosses[netSlot]->winSetEnabledTextColors(houseColor, m_playerWinLosses[netSlot]->winGetEnabledTextBorderColor()); - // favoriteFaction - Int numGames = 0; - Int favorite = 0; - for(it =stats.games.begin(); it != stats.games.end(); ++it) - { - if(it->second >= numGames) - { - numGames = it->second; - favorite = it->first; - } - } -// if(numGames == 0) -// GadgetStaticTextSetText(m_playerFavoriteFactions[netSlot], TheGameText->fetch("GUI:None")); -// else if( stats.gamesAsRandom > numGames ) -// GadgetStaticTextSetText(m_playerFavoriteFactions[netSlot], TheGameText->fetch("GUI:Random")); -// else -// { -// const PlayerTemplate *fac = ThePlayerTemplateStore->getNthPlayerTemplate(favorite); -// if (fac) -// { -// AsciiString side; -// side.format("SIDE:%s", fac->getSide().str()); -// -// GadgetStaticTextSetText(m_playerFavoriteFactions[netSlot], TheGameText->fetch(side)); -// } -// } -// m_playerFavoriteFactions[netSlot]->winSetEnabledTextColors(houseColor, m_playerFavoriteFactions[netSlot]->winGetEnabledTextBorderColor()); - // disconnects - numGames = 0; - for(it =stats.discons.begin(); it != stats.discons.end(); ++it) - { - numGames += it->second; - } - for(it =stats.desyncs.begin(); it != stats.desyncs.end(); ++it) - { - numGames += it->second; - } - numGames += GetAdditionalDisconnectsFromUserFile(stats.id); - - formatString.format(L"%d", numGames); - GadgetStaticTextSetText(m_playerTotalDisconnects[netSlot], formatString); - m_playerTotalDisconnects[netSlot]->winSetEnabledTextColors(houseColor, m_playerTotalDisconnects[netSlot]->winGetEnabledTextBorderColor()); - GadgetStaticTextSetText(m_playerSide[netSlot], slot->getApparentPlayerTemplateDisplayName() ); - m_playerSide[netSlot]->winSetEnabledTextColors(houseColor, m_playerSide[netSlot]->winGetEnabledTextBorderColor()); - - if (slot->isAI()) - { - if (m_progressBars[netSlot]) - m_progressBars[netSlot]->winHide(TRUE); - if (m_playerTotalDisconnects[netSlot]) - m_playerTotalDisconnects[netSlot]->winHide(TRUE); -// if (m_playerFavoriteFactions[netSlot]) -// m_playerFavoriteFactions[netSlot]->winHide(TRUE); - if (m_playerWinLosses[netSlot]) - m_playerWinLosses[netSlot]->winHide(TRUE); - if (m_playerRank[netSlot]) - m_playerRank[netSlot]->winHide(TRUE); - if (m_playerOfficerMedal[netSlot]) - m_playerOfficerMedal[netSlot]->winHide(TRUE); - } - - if (teamWin[netSlot]) - { - AsciiString teamStr; - teamStr.format("Team:%d", slot->getTeamNumber() + 1); - if (slot->isAI() && slot->getTeamNumber() == -1) - teamStr = "Team:AI"; - GadgetStaticTextSetText(teamWin[netSlot], TheGameText->fetch(teamStr)); - teamWin[netSlot]->winSetEnabledTextColors(houseColor, m_playerNames[netSlot]->winGetEnabledTextBorderColor()); - } - - m_playerLookup[i] = netSlot; // save our mapping so we can update progress correctly - - netSlot++; - } - - for(i = netSlot; i < MAX_SLOTS; ++i) - { - m_playerWin[i]->winHide(TRUE); - //m_playerNames[i]->winHide(TRUE); - //m_playerSide[i]->winHide(TRUE); - } - - if(m_mapPreview) - { - const MapMetaData *mmd = TheMapCache->findMap(game->getMap()); - Image *image = getMapPreviewImage(game->getMap()); - m_mapPreview->winSetUserData((void *)mmd); - - positionStartSpots( game, m_buttonMapStartPosition, m_mapPreview); - updateMapStartSpots( game, m_buttonMapStartPosition, TRUE ); - //positionAdditionalImages((MapMetaData *)mmd, m_mapPreview, TRUE); - if(image) - { - m_mapPreview->winSetStatus(WIN_STATUS_IMAGE); - m_mapPreview->winSetEnabledImage(0, image); - } - else - { - m_mapPreview->winClearStatus(WIN_STATUS_IMAGE); - } - } - - TheGameLogic->initTimeOutValues(); -} - -void GameSpyLoadScreen::reset( void ) -{ - setLoadScreen(NULL); - for(Int i = 0; i < MAX_SLOTS; ++i) - { - m_progressBars[i] = NULL; - m_playerNames[i] = NULL; - m_playerSide[i]= NULL; - } -} - -void GameSpyLoadScreen::update( Int percent ) -{ - if(percent <= 100) - TheNetwork->updateLoadProgress( percent ); - TheNetwork->liteupdate(); - - //GadgetProgressBarSetProgress(m_progressBars[TheNetwork->getLocalPlayerID()], percent ); - - TheMouse->setCursorTooltip(UnicodeString::TheEmptyString); - - // Do this last! - LoadScreen::update( percent ); -} - -void GameSpyLoadScreen::processProgress(Int playerId, Int percentage) -{ - - if( percentage < 0 || percentage > 100 || playerId >= MAX_SLOTS || playerId < 0 || m_playerLookup[playerId] == -1) - { - DEBUG_ASSERTCRASH(FALSE, ("Percentage %d was passed in for Player %d\n", percentage, playerId)); - } - //DEBUG_LOG(("Percentage %d was passed in for Player %d (in loadscreen position %d)\n", percentage, playerId, m_playerLookup[playerId])); - if(m_progressBars[m_playerLookup[playerId]]) - GadgetProgressBarSetProgress(m_progressBars[m_playerLookup[playerId]], percentage ); -} - // MapTransferLoadScreen Class ////////////////////////////////////////////////// //----------------------------------------------------------------------------- MapTransferLoadScreen::MapTransferLoadScreen( void ) diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy.cpp deleted file mode 100644 index 21c7e05934c..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy.cpp +++ /dev/null @@ -1,1417 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameSpy.cpp ////////////////////////////////////////////////////// -// GameSpy callbacks, etc -// Author: Matthew D. Campbell, February 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "GameSpy/GP/GP.h" -#include "GameSpy/gstats/gpersist.h" - -#include "GameNetwork/FirewallHelper.h" -#include "GameNetwork/GameSpy.h" -#include "GameNetwork/GameSpyChat.h" -#include "GameNetwork/GameSpyGameInfo.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameNetwork/GameSpyGP.h" -#include "GameNetwork/GameSpyPersistentStorage.h" -#include "GameNetwork/GameSpyThread.h" -#include "GameNetwork/NAT.h" -#include "GameClient/Shell.h" -#include "GameClient/MessageBox.h" -#include "GameClient/GameText.h" -#include "GameClient/MapUtil.h" -#include "Common/Version.h" -#include "Common/MultiplayerSettings.h" -#include "Common/PlayerTemplate.h" -#include "Common/RandomValue.h" -#include "Common/GlobalData.h" -#include "Common/UserPreferences.h" -#include "GameLogic/ScriptEngine.h" - -MutexClass TheGameSpyMutex; -static UnsignedInt mainThreadID = 0; -static Bool inThread = false; -#define ISMAINTHREAD ( ThreadClass::_Get_Current_Thread_ID() == mainThreadID ) -GameSpyThreadClass *TheGameSpyThread = NULL; - -/// polling/update thread function - -void GameSpyThreadClass::Thread_Function() -{ - - //poll network and update GameSpy object - - while (running) - { - inThread = true; - if (m_doLogin) - { - m_doLogin = false; - TheGameSpyChat->login(m_nick, m_pass, m_email); - } - if (m_readStats) - { - m_readStats = false; - TheGameSpyPlayerInfo->threadReadFromServer(); - } - if (m_updateLocale) - { - m_updateLocale = false; - TheGameSpyPlayerInfo->threadSetLocale(m_locale); - } - if (m_updateWins) - { - m_updateWins = false; - TheGameSpyPlayerInfo->threadSetLocale(m_wins); - } - if (m_updateLosses) - { - m_updateLosses = false; - TheGameSpyPlayerInfo->threadSetLocale(m_losses); - } - inThread = false; - Switch_Thread(); - } -} - -AsciiString GameSpyThreadClass::getNextShellScreen( void ) -{ - MutexClass::LockClass m(TheGameSpyMutex, 0); - if (m.Failed()) - return AsciiString::TheEmptyString; - return m_nextShellScreen; -} - -Bool GameSpyThreadClass::showLocaleSelect( void ) -{ - MutexClass::LockClass m(TheGameSpyMutex, 0); - if (m.Failed()) - return false; - return m_showLocaleSelect; -} - -void GameSpyThreadClass::setNextShellScreen( AsciiString nextShellScreen ) -{ - MutexClass::LockClass m(TheGameSpyMutex); - m_nextShellScreen = nextShellScreen; -} - -void GameSpyThreadClass::setShowLocaleSelect( Bool val ) -{ - MutexClass::LockClass m(TheGameSpyMutex); - m_showLocaleSelect = val; -} - -void createRoomCallback(PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, void *param); - - -class GameSpyChat : public GameSpyChatInterface -{ -public: - GameSpyChat(); - virtual ~GameSpyChat(); - - virtual void init( void ); - virtual void reset( void ); - virtual void update( void ); - - virtual Bool isConnected( void ); - virtual void login(AsciiString loginName, AsciiString password = AsciiString::TheEmptyString, AsciiString email = AsciiString::TheEmptyString); - virtual void reconnectProfile( void ); - virtual void disconnectFromChat( void ); - - virtual void UTMRoom( RoomType roomType, const char *key, const char *val, Bool authenticate = FALSE ); - virtual void UTMPlayer( const char *name, const char *key, const char *val, Bool authenticate = FALSE ); - virtual void startGame( void ); - virtual void leaveRoom( RoomType roomType ); - virtual void setReady( Bool ready ); - virtual void enumPlayers( RoomType roomType, peerEnumPlayersCallback callback, void *userData ); - virtual void startListingGames( peerListingGamesCallback callback ); - virtual void stopListingGames( void ); - - virtual void joinGroupRoom( Int ID ); - virtual void joinStagingRoom( GServer server, AsciiString password ); - virtual void createStagingRoom( AsciiString gameName, AsciiString password, Int maxPlayers ); - virtual void joinBestGroupRoom( void ); - - void loginQuick(AsciiString loginName); - void loginProfile(AsciiString loginName, AsciiString password, AsciiString email); - void setProfileID( Int ID ) { m_profileID = ID; } - - void _connectCallback(PEER peer, PEERBool success, void * param); - void _nickErrorCallback(PEER peer, int type, const char * nick, void * param); - void _GPConnectCallback(GPConnection * pconnection, GPConnectResponseArg * arg, void * param); - void _GPReconnectCallback(GPConnection * pconnection, GPConnectResponseArg * arg, void * param); - - inline void finishJoiningGroupRoom( void ) { m_joiningGroupRoom = false; } - inline void finishJoiningStagingRoom( void ) { m_joiningStagingRoom = false; } - -private: - UnsignedInt m_loginTimeoutPeriod; // in ms - UnsignedInt m_loginTimeout; - - Bool m_joiningGroupRoom; - Bool m_joiningStagingRoom; - - GameSpyThreadClass thread; -}; - -GameSpyChatInterface *TheGameSpyChat; -GameSpyChatInterface *createGameSpyChat( void ) -{ - mainThreadID = ThreadClass::_Get_Current_Thread_ID(); - return NEW GameSpyChat; -} - -void GameSpyChatInterface::clearGroupRoomList(void) -{ - m_groupRooms.clear(); -} - -GameSpyChat::GameSpyChat() -{ - m_peer = NULL; -} - -GameSpyChat::~GameSpyChat() -{ - reset(); - if (thread.Is_Running()) - thread.Stop(); - TheGameSpyThread = NULL; -} - -void GameSpyChat::init( void ) -{ - reset(); - - DEBUG_ASSERTCRASH(!thread.Is_Running(), ("Thread is running")); - - thread.Execute(); - thread.Set_Priority(0); - TheGameSpyThread = &thread; -} - -void GameSpyChat::reset( void ) -{ - MutexClass::LockClass m(TheGameSpyMutex); - m_loginName.clear(); - m_password.clear(); - m_email.clear(); - m_usingProfiles = false; - m_profileID = 0; - if (m_peer) - peerShutdown(m_peer); - m_peer = NULL; - m_groupRooms.clear(); - m_currentGroupRoomID = 0; - - m_loginTimeoutPeriod = 5000; - m_loginTimeout = 0; - - m_joiningGroupRoom = false; - m_joiningStagingRoom = false; - - //if (thread.Is_Running()) - //thread.Stop(); -} - -void GameSpyChat::update( void ) -{ - MutexClass::LockClass m(TheGameSpyMutex, 0); - if (!m.Failed() && m_peer) - { - if (!TheGameSpyThread->getNextShellScreen().isEmpty()) - { - TheShell->pop(); - TheShell->push(TheGameSpyThread->getNextShellScreen()); - TheGameSpyThread->setNextShellScreen( AsciiString.TheEmptyString ); - } - - if (TheGameSpyThread->showLocaleSelect()) - { - TheGameSpyThread->setShowLocaleSelect(false); - WindowLayout *layout = NULL; - layout = TheWindowManager->winCreateLayout( AsciiString( "Menus/PopupLocaleSelect.wnd" ) ); - layout->runInit(); - layout->hide( FALSE ); - layout->bringForward(); - TheWindowManager->winSetModal( layout->getFirstWindow() ); - } - - //if (!isConnected()) - //return; - - peerThink(m_peer); - - gpProcess(TheGPConnection); - - if (TheNAT != NULL) { - NATStateType NATState = TheNAT->update(); - if (NATState == NATSTATE_DONE) - { - GameSpyLaunchGame(); - } - else if (NATState == NATSTATE_FAILED) - { - GameSpyLaunchGame(); - } - } - - if (TheFirewallHelper != NULL) { - if (TheFirewallHelper->behaviorDetectionUpdate()) { - TheGlobalData->m_firewallBehavior = TheFirewallHelper->getFirewallBehavior(); - OptionPreferences *pref = NEW OptionPreferences; - char num[16]; - num[0] = 0; - itoa(TheGlobalData->m_firewallBehavior, num, 10); - AsciiString numstr; - numstr = num; - (*pref)["FirewallBehavior"] = numstr; - pref->write(); - - // we are now done with the firewall helper - delete TheFirewallHelper; - TheFirewallHelper = NULL; - } - } - - UnsignedInt now = timeGetTime(); - if (m_loginTimeout && now > m_loginTimeout) - { - // login timed out - m_loginTimeout = 0; - GSMessageBoxOk(UnicodeString(L"Error connecting"), UnicodeString(L"Timed out connecting"), NULL); - - // Enable controls again - //EnableLoginControls(TRUE); - - if (TheGameSpyGame) - delete TheGameSpyGame; - TheGameSpyGame = NULL; - - if (m_peer) - peerShutdown(m_peer); - m_peer = NULL; - - gpDisconnect(TheGPConnection); - gpDestroy(TheGPConnection); - } - } -} - -Bool GameSpyChat::isConnected( void ) -{ - return m_peer && peerIsConnected(m_peer); -} - -void GameSpyChat::UTMRoom( RoomType roomType, const char *key, const char *val, Bool authenticate ) -{ - peerUTMRoom( m_peer, roomType, key, val, (authenticate)?PEERTrue:PEERFalse ); -} - -void GameSpyChat::UTMPlayer( const char *name, const char *key, const char *val, Bool authenticate ) -{ - peerUTMPlayer( m_peer, name, key, val, (authenticate)?PEERTrue:PEERFalse ); -} - -void GameSpyChat::startGame( void ) -{ - peerStartGame( m_peer, NULL, PEER_STOP_REPORTING ); -} - -void GameSpyChat::leaveRoom( RoomType roomType ) -{ - peerLeaveRoom( m_peer, roomType, NULL ); -} - -void GameSpyChat::setReady( Bool ready ) -{ - peerSetReady( m_peer, (ready)?PEERTrue:PEERFalse ); -} - -void GameSpyChat::enumPlayers( RoomType roomType, peerEnumPlayersCallback callback, void *userData ) -{ - peerEnumPlayers( m_peer, roomType, callback, userData ); -} - -void GameSpyChat::startListingGames( peerListingGamesCallback callback ) -{ - peerSetUpdatesRoomChannel( m_peer, "#gmtest_updates" ); - peerStartListingGames( m_peer, NULL, callback, NULL ); -} - -void GameSpyChat::stopListingGames( void ) -{ - peerStopListingGames( m_peer ); -} - -void GameSpyChat::joinGroupRoom( Int ID ) -{ - if (m_joiningGroupRoom || m_joiningStagingRoom) - return; - - m_joiningGroupRoom = true; - - if (getCurrentGroupRoomID()) - { - leaveRoom(GroupRoom); - setCurrentGroupRoomID(0); - } - peerJoinGroupRoom(m_peer, ID, JoinRoomCallback, (void *)ID, PEERFalse); -} - -void GameSpyChat::joinStagingRoom( GServer server, AsciiString password ) -{ - if (m_joiningGroupRoom || m_joiningStagingRoom) - return; - - m_joiningStagingRoom = true; - - peerJoinStagingRoom(m_peer, server, password.str(), JoinRoomCallback, server, PEERFalse); -} - -void GameSpyChat::createStagingRoom( AsciiString gameName, AsciiString password, Int maxPlayers ) -{ - if (m_joiningGroupRoom || m_joiningStagingRoom) - return; - - m_joiningStagingRoom = true; - - Int oldGroupID = TheGameSpyChat->getCurrentGroupRoomID(); - - TheGameSpyChat->leaveRoom(GroupRoom); - TheGameSpyChat->setCurrentGroupRoomID(0); - - DEBUG_LOG(("GameSpyChat::createStagingRoom - creating staging room, name is %s\n", m_loginName.str())); - - peerCreateStagingRoom(m_peer, m_loginName.str(), maxPlayers, password.str(), createRoomCallback, (void *)oldGroupID, PEERFalse); -} - -void GameSpyChat::joinBestGroupRoom( void ) -{ - if (m_groupRooms.size()) - { - int minID = -1; - int minPlayers = 1000; - GroupRoomMap::iterator iter = m_groupRooms.begin(); - while (iter != m_groupRooms.end()) - { - GameSpyGroupRoom room = iter->second; - DEBUG_LOG(("Group room %d: %s (%d, %d, %d, %d)\n", room.m_groupID, room.m_name.str(), room.m_numWaiting, room.m_maxWaiting, - room.m_numGames, room.m_numPlaying)); - - if (minPlayers > 25 && room.m_numWaiting < minPlayers) - { - minID = room.m_groupID; - minPlayers = room.m_numWaiting; - } - - ++iter; - } - - if (minID > 0) - { - joinGroupRoom(minID); - } - else - { - GSMessageBoxOk(UnicodeString(L"Oops"), UnicodeString(L"No empty group rooms"), NULL); - } - } - else - { - GSMessageBoxOk(UnicodeString(L"Oops"), UnicodeString(L"No group rooms"), NULL); - } -} - -void GameSpyChat::disconnectFromChat( void ) -{ - TheScriptEngine->signalUIInteract("GameSpyLogout"); - - if (m_peer) - { - peerShutdown(m_peer); - m_peer = NULL; - } - if (TheGameSpyGame) - delete TheGameSpyGame; - TheGameSpyGame = NULL; -} - - - - - - -//----------------------------------------------------------------------- - -void DisconnectedCallback(PEER peer, const char * reason, - void * param) -{ - TheScriptEngine->signalUIInteract("GameSpyLogout"); - - if (TheGameSpyGame) - delete TheGameSpyGame; - TheGameSpyGame = NULL; - - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSDisconnected"), NULL); - - WindowLayout * mainMenu = TheShell->findScreenByFilename("Menus/MainMenu.wnd"); - if (mainMenu) - { - while (TheShell->top() != mainMenu) - { - TheShell->pop(); - } - } -} - -void ReadyChangedCallback(PEER peer, const char * nick, - PEERBool ready, void * param) -{ - if (TheGameSpyGame) - { - Int slotNum = TheGameSpyGame->getSlotNum(nick); - if (slotNum >= 0) - { - GameSlot *slot = TheGameSpyGame->getSlot(slotNum); - if (slot) - { - if (ready) { - slot->setAccept(); - } else { - slot->unAccept(); - } - - if (TheGameSpyGame->amIHost()) - { - peerUTMRoom(TheGameSpyChat->getPeer(), StagingRoom, "SL/", GameInfoToAsciiString(TheGameSpyGame).str(), PEERFalse); - } - - WOLDisplaySlotList(); - } - } - } -} - -void GameStartedCallback(PEER peer, unsigned int IP, - const char * message, void * param) -{ - GameSpyStartGame(); -} - -void populateLobbyPlayerListbox(void); -void PlayerJoinedCallback(PEER peer, RoomType roomType, - const char * nick, void * param) -{ - if (roomType == GroupRoom && TheGameSpyChat->getCurrentGroupRoomID()) - { - populateLobbyPlayerListbox(); - } - if (roomType == StagingRoom && TheGameSpyGame) - { - DEBUG_LOG(("StagingRoom, Game OK\n")); - for (Int i=1; igetSlot(i); - if (slot && slot->getState() == SLOT_OPEN) - { - DEBUG_LOG(("Putting %s in slot %d\n", nick, i)); - UnicodeString uName; - uName.translate(nick); - slot->setState(SLOT_PLAYER, uName); - slot->setColor(-1); - slot->setPlayerTemplate(-1); - slot->setStartPos(-1); - slot->setTeamNumber(-1); - TheGameSpyGame->resetAccepted(); - Int id; - UnsignedInt ip; - PEERBool success = peerGetPlayerInfoNoWait(TheGameSpyChat->getPeer(), nick, &ip, &id); - DEBUG_LOG(("PlayerJoinedCallback - result from peerGetPlayerInfoNoWait, %d: ip=%d.%d.%d.%d, id=%d\n", success, - (ip >> 24) & 0xff, - (ip >> 16) & 0xff, - (ip >> 8) & 0xff, - ip & 0xff, - id)); - success = PEERFalse; // silence compiler warnings in release build - slot->setIP(ip); - if (TheGameSpyGame->amIHost()) - { - peerUTMRoom(TheGameSpyChat->getPeer(), StagingRoom, "SL/", GameInfoToAsciiString(TheGameSpyGame).str(), PEERFalse); - } - - WOLDisplaySlotList(); - break; - } - } - if (i == MAX_SLOTS) - { - // we got all the way through without room for him - kick him - if (TheGameSpyGame->amIHost()) - { - peerUTMRoom(TheGameSpyChat->getPeer(), StagingRoom, "SL/", GameInfoToAsciiString(TheGameSpyGame).str(), PEERFalse); - } - } - } -} - -void PlayerLeftCallback(PEER peer, RoomType roomType, - const char * nick, const char * reason, - void * param) -{ - if (roomType == GroupRoom && TheGameSpyChat->getCurrentGroupRoomID()) - { - populateLobbyPlayerListbox(); - } - - if (roomType == StagingRoom && TheGameSpyGame) - { - Int slotNum = TheGameSpyGame->getSlotNum(nick); - if (slotNum >= 0) - { - GameSlot *slot = TheGameSpyGame->getSlot(slotNum); - if (slot) - { - slot->setState(SLOT_OPEN); - DEBUG_LOG(("Removing %s from slot %d\n", nick, slotNum)); - if (TheGameSpyGame->amIHost()) - { - peerUTMRoom(TheGameSpyChat->getPeer(), StagingRoom, "SL/", GameInfoToAsciiString(TheGameSpyGame).str(), PEERFalse); - } - TheGameSpyGame->resetAccepted(); - - WOLDisplaySlotList(); - } - } - } -} - -void PlayerChangedNickCallback(PEER peer, RoomType roomType, - const char * oldNick, - const char * newNick, void * param) -{ - if (TheGameSpyChat->getCurrentGroupRoomID()) - { - populateLobbyPlayerListbox(); - } -} - -void PingCallback(PEER peer, const char * nick, int ping, - void * param) -{ - DEBUG_LOG(("PingCallback\n")); -} - -void CrossPingCallback(PEER peer, const char * nick1, - const char * nick2, int crossPing, - void * param) -{ - DEBUG_LOG(("CrossPingCallback\n")); -} - -static void RoomUTMCallback(PEER peer, RoomType roomType, const char * nick, - const char * command, const char * parameters, - PEERBool authenticated, void * param) -{ - DEBUG_LOG(("RoomUTMCallback: %s says %s = [%s]\n", nick, command, parameters)); - if (roomType == StagingRoom && TheGameSpyGame) - { - Int slotNum = TheGameSpyGame->getSlotNum(nick); - if (slotNum == 0 && !TheGameSpyGame->amIHost()) - { - if (!strcmp(command, "SL")) - { - AsciiString options = parameters; - options.trim(); - ParseAsciiStringToGameInfo(TheGameSpyGame, options.str()); - WOLDisplaySlotList(); - } - else if (!strcmp(command, "HWS")) // HostWantsStart - { - Int slotNum = TheGameSpyGame->getLocalSlotNum(); - GameSlot *slot = TheGameSpyGame->getSlot(slotNum); - if (slot->isAccepted() == false) - { - GameSpyAddText(TheGameText->fetch("GUI:HostWantsToStart"), GSCOLOR_DEFAULT); - } - } - } - } -} - -static void PlayerUTMCallback(PEER peer, const char * nick, - const char * command, const char * parameters, - PEERBool authenticated, void * param) -{ - DEBUG_LOG(("PlayerUTMCallback: %s says %s = [%s]\n", nick, command, parameters)); - if (TheGameSpyGame) - { - Int slotNum = TheGameSpyGame->getSlotNum(nick); - if (slotNum != 0 && TheGameSpyGame->amIHost()) - { - if (!strcmp(command, "REQ")) - { - AsciiString options = parameters; - options.trim(); - - - Bool change = false; - Bool shouldUnaccept = false; - AsciiString key; - options.nextToken(&key, "="); - Int val = atoi(options.str()+1); - UnsignedInt uVal = atoi(options.str()+1); - DEBUG_LOG(("GameOpt request: key=%s, val=%s from player %d\n", key.str(), options.str(), slotNum)); - - GameSlot *slot = TheGameSpyGame->getSlot(slotNum); - if (!slot) - return; - - if (key == "Color") - { - if (val >= -1 && val < TheMultiplayerSettings->getNumColors() && val != slot->getColor()) - { - Bool colorAvailable = TRUE; - if(val != -1 ) - { - for(Int i=0; i getSlot(i); - if(val == checkSlot->getColor() && slot != checkSlot) - { - colorAvailable = FALSE; - break; - } - } - } - if(colorAvailable) - slot->setColor(val); - change = true; - } - else - { - DEBUG_LOG(("Rejecting invalid color %d\n", val)); - } - } - else if (key == "PlayerTemplate") - { - if (val >= PLAYERTEMPLATE_MIN && val < ThePlayerTemplateStore->getPlayerTemplateCount() && val != slot->getPlayerTemplate()) - { - slot->setPlayerTemplate(val); - change = true; - shouldUnaccept = true; - } - else - { - DEBUG_LOG(("Rejecting invalid PlayerTemplate %d\n", val)); - } - } - else if (key == "StartPos") - { - if (val >= -1 && val < MAX_SLOTS && val != slot->getStartPos()) - { - slot->setStartPos(val); - change = true; - shouldUnaccept = true; - } - else - { - DEBUG_LOG(("Rejecting invalid startPos %d\n", val)); - } - } - else if (key == "Team") - { - if (val >= -1 && val < MAX_SLOTS/2 && val != slot->getTeamNumber()) - { - slot->setTeamNumber(val); - change = true; - shouldUnaccept = true; - } - else - { - DEBUG_LOG(("Rejecting invalid team %d\n", val)); - } - } - else if (key == "IP") - { - if (uVal != slot->getIP()) - { - slot->setIP(uVal); - change = true; - shouldUnaccept = true; - } - else - { - DEBUG_LOG(("Rejecting invalid IP %d\n", uVal)); - } - } - else if (key == "NAT") - { - if ((val >= FirewallHelperClass::FIREWALL_TYPE_SIMPLE) && - (val <= FirewallHelperClass::FIREWALL_TYPE_DESTINATION_PORT_DELTA)) - { - slot->setNATBehavior((FirewallHelperClass::FirewallBehaviorType)val); - DEBUG_LOG(("Setting NAT behavior to %d for player %d\n", val, slotNum)); - change = true; - } - else - { - DEBUG_LOG(("Rejecting invalid NAT behavior %d from player %d\n", val, slotNum)); - } - } - - if (change) - { - if (shouldUnaccept) - TheGameSpyGame->resetAccepted(); - peerUTMRoom(TheGameSpyChat->getPeer(), StagingRoom, "SL/", GameInfoToAsciiString(TheGameSpyGame).str(), PEERFalse); - WOLDisplaySlotList(); - DEBUG_LOG(("Slot value is color=%d, PlayerTemplate=%d, startPos=%d, team=%d, IP=0x%8.8X\n", - slot->getColor(), slot->getPlayerTemplate(), slot->getStartPos(), slot->getTeamNumber(), slot->getIP())); - DEBUG_LOG(("Slot list updated to %s\n", GameInfoToAsciiString(TheGameSpyGame).str())); - } - - - } - } - } -} - -void GOABasicCallback(PEER peer, PEERBool playing, char * outbuf, - int maxlen, void * param) -{ - _snprintf(outbuf, maxlen, "\\gamename\\c&cgenerals\\gamever\\%s\\location\\%d", - TheVersion->getAsciiVersion().str(), 0); - outbuf[maxlen-1] = 0; - DEBUG_LOG(("GOABasicCallback: [%s]\n", outbuf)); - TheGameSpyGame->gotGOACall(); -} - -void GOAInfoCallback(PEER peer, PEERBool playing, char * outbuf, - int maxlen, void * param) -{ - _snprintf(outbuf, maxlen, "\\hostname\\%s\\hostport\\%d\\mapname\\%s\\gametype\\%s\\numplayers\\%d\\maxplayers\\%d\\gamemode\\%s", - TheGameSpyChat->getLoginName().str(), 0, TheGameSpyGame->getMap().str(), "battle", TheGameSpyGame->getNumPlayers(), TheGameSpyGame->getMaxPlayers(), "wait"); - outbuf[maxlen-1] = 0; - DEBUG_LOG(("GOAInfoCallback: [%s]\n", outbuf)); - TheGameSpyGame->gotGOACall(); -} - -void GOARulesCallback(PEER peer, PEERBool playing, char * outbuf, - int maxlen, void * param) -{ - _snprintf(outbuf, maxlen, "\\password\\0\\seed\\%d", - TheGameSpyGame->getSeed()); - outbuf[maxlen-1] = 0; - DEBUG_LOG(("GOARulesCallback: [%s]\n", outbuf)); - TheGameSpyGame->gotGOACall(); -} - -void GOAPlayersCallback(PEER peer, PEERBool playing, char * outbuf, - int maxlen, void * param) -{ - AsciiString buf, tmp; - for (Int i=0; igetSlot(i); - AsciiString name; - switch (slot->getState()) - { - case SLOT_OPEN: - name = "O"; - break; - case SLOT_CLOSED: - name = "X"; - break; - case SLOT_EASY_AI: - name = "CE"; - break; - case SLOT_MED_AI: - name = "CM"; - break; - case SLOT_BRUTAL_AI: - name = "CB"; - break; - case SLOT_PLAYER: - { - AsciiString tmp; - tmp.translate(slot->getName()); - name.format("H%s", tmp.str()); - } - break; - default: - name = "?"; - break; - } - tmp.format("\\player_%d\\%s\\color_%d\\%d\\faction_%d\\%d\\team_%d\\%d\\pos_%d\\%d", - i, name.str(), - i, slot->getColor(), - i, slot->getPlayerTemplate(), - i, slot->getTeamNumber(), - i, slot->getStartPos()); - buf.concat(tmp); - } - _snprintf(outbuf, maxlen, buf.str()); - outbuf[maxlen-1] = 0; - DEBUG_LOG(("GOAPlayersCallback: [%s]\n", outbuf)); - TheGameSpyGame->gotGOACall(); -} - -void JoinRoomCallback(PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, void *param) -{ - DEBUG_LOG(("JoinRoomCallback: success==%d, result==%d\n", success, result)); - switch (roomType) - { - case GroupRoom: - { - ((GameSpyChat *)TheGameSpyChat)->finishJoiningGroupRoom(); - if (success) - { - // update our internal group room ID - TheGameSpyChat->setCurrentGroupRoomID((Int)param); - - // see if we need to change screens - WindowLayout *layout = TheShell->top(); - AsciiString windowFile = layout->getFilename(); - DEBUG_LOG(("Joined group room, active screen was %s\n", windowFile.str())); - if (windowFile.compareNoCase("Menus/WOLCustomLobby.wnd") == 0) - { - // already on the right screen - just refresh it - //GroupRoomJoinLobbyRefresh(); - } - else - { - // change to the right screen - TheShell->pop(); - TheShell->push("Menus/WOLCustomLobby.wnd"); - } - } - else - { - // failed to join lobby - bail to welcome screen - WindowLayout *layout = TheShell->top(); - AsciiString windowFile = layout->getFilename(); - DEBUG_LOG(("Joined group room, active screen was %s\n", windowFile.str())); - if (windowFile.compareNoCase("Menus/WOLWelcomeMenu.wnd") != 0) - { - TheShell->pop(); - TheShell->push("Menus/WOLWelcomeMenu.wnd"); - } - GSMessageBoxOk(UnicodeString(L"Oops"), UnicodeString(L"Unable to join group room"), NULL); - } - - // Update buddy location - if (TheGameSpyChat->getUsingProfile()) - { - if (TheGameSpyChat->getCurrentGroupRoomID()) - { - AsciiString s; - s.format("c&cgenerals://0.0.0.0:0/%d", TheGameSpyChat->getCurrentGroupRoomID()); - gpSetStatus(TheGPConnection, GP_CHATTING, "Chatting", s.str()); - } - else - { - gpSetStatus(TheGPConnection, GP_ONLINE, "Online", ""); - } - } - } - break; - case StagingRoom: - { - ((GameSpyChat *)TheGameSpyChat)->finishJoiningStagingRoom(); - if (success) - { - DEBUG_LOG(("JoinRoomCallback - Joined staging room\n")); - GServer server = (GServer)param; - - // leave any chat channels - TheGameSpyChat->leaveRoom(GroupRoom); - TheGameSpyChat->setCurrentGroupRoomID(0); - - // set up game info - TheGameSpyGame->enterGame(); - TheGameSpyGame->setServer(server); - GameSlot *slot = TheGameSpyGame->getSlot(0); - AsciiString options, hostName; - hostName = ServerGetPlayerStringValue(server, 0, "player", ""); - UnicodeString uHostName; - uHostName.translate(hostName.str() + 1); // go past the 'H' - slot->setState(SLOT_PLAYER, uHostName); - UnsignedInt localIP = peerGetLocalIP(TheGameSpyChat->getPeer()); - GetLocalChatConnectionAddress("peerchat.gamespy.com", 6667, localIP); - localIP = ntohl(localIP); // The IP returned from GetLocalChatConnectionAddress is in network byte order. - options.format("IP=%d", localIP); - peerUTMPlayer(TheGameSpyChat->getPeer(), hostName.str(), "REQ/", options.str(), PEERFalse); - options.format("NAT=%d", TheFirewallHelper->getFirewallBehavior()); - peerUTMPlayer(TheGameSpyChat->getPeer(), hostName.str(), "REQ/", options.str(), PEERFalse); - - // refresh the map cache - TheMapCache->updateCache(); - - // switch screens - TheShell->pop(); - TheShell->push("Menus/GameSpyGameOptionsMenu.wnd"); - } - else - { - // let the user know - GSMessageBoxOk(UnicodeString(L"Oops"), UnicodeString(L"Unable to join game"), NULL); - DEBUG_LOG(("JoinRoomCallback - Failed to join staging room.\n")); - } - - // Update buddy location - if (TheGameSpyChat->getUsingProfile()) - { - if (TheGameSpyChat->getCurrentGroupRoomID()) - { - AsciiString s; - s.format("c&cgenerals://0.0.0.0:0/%d", TheGameSpyChat->getCurrentGroupRoomID()); - gpSetStatus(TheGPConnection, GP_CHATTING, "Chatting", s.str()); - } - else - { - gpSetStatus(TheGPConnection, GP_ONLINE, "Online", ""); - } - } - break; - } - } - - //*didJoin = (success == PEERJoinSuccess || success == PEERTrue); -} - -void createRoomCallback(PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, void *param) -{ - DEBUG_LOG(("CreateRoomCallback: success==%d, result==%d\n", success, result)); - - if (roomType != StagingRoom) - { - DEBUG_CRASH(("Non-staging room create!")); - return; - } - - ((GameSpyChat *)TheGameSpyChat)->finishJoiningStagingRoom(); - - Int oldGroupID = (Int)param; - - if (success) - { - // set up the game info - UnsignedInt localIP = peerGetLocalIP(TheGameSpyChat->getPeer()); - DEBUG_LOG(("createRoomCallback - peerGetLocalIP returned %d.%d.%d.%d as the local IP\n", - localIP >> 24, (localIP >> 16) & 0xff, (localIP >> 8) & 0xff, localIP & 0xff)); -// GetLocalChatConnectionAddress("peerchat.gamespy.com", 6667, localIP); -// DEBUG_LOG(("createRoomCallback - GetLocalChatConnectionAddress returned %d.%d.%d.%d as the local IP\n", -// localIP >> 24, (localIP >> 16) & 0xff, (localIP >> 8) & 0xff, localIP & 0xff)); - localIP = ntohl(localIP); // The IP returned from GetLocalChatConnectionAddress is in network byte order. - TheGameSpyGame->setLocalIP(localIP); - - UnicodeString name; - name.translate(TheGameSpyChat->getLoginName()); - TheGameSpyGame->enterGame(); -// TheGameSpyGame->setSeed(GameClientRandomValue(0, INT_MAX - 1)); - TheGameSpyGame->setSeed(GetTickCount()); - GameSlot newSlot; - newSlot.setState(SLOT_PLAYER, name); - newSlot.setIP(localIP); - TheGameSpyGame->setSlot(0,newSlot); - - TheMapCache->updateCache(); - - TheGameSpyGame->setMap(TheGlobalData->m_mapName); - AsciiString asciiMap; - asciiMap = TheGlobalData->m_mapName; - - asciiMap.toLower(); - std::map::iterator it = TheMapCache->find(asciiMap); - if (it != TheMapCache->end()) - { - TheGameSpyGame->getSlot(0)->setMapAvailability(true); - TheGameSpyGame->setMapCRC( it->second.m_CRC ); - TheGameSpyGame->setMapSize( it->second.m_filesize ); - - TheGameSpyGame->adjustSlotsForMap(); // BGC- adjust the slots for the new map. - } - - - // change to the proper screen - TheShell->pop(); - TheShell->push("Menus/GameSpyGameOptionsMenu.wnd"); - } - else - { - // join the lobby again - TheGameSpyChat->joinGroupRoom(oldGroupID); - GSMessageBoxOk(UnicodeString(L"Oops"), UnicodeString(L"Unable to create game"), NULL); - } - - // Update buddy location - if (TheGameSpyChat->getUsingProfile()) - { - if (TheGameSpyChat->getCurrentGroupRoomID()) - { - AsciiString s; - s.format("c&cgenerals://0.0.0.0:0/%d", TheGameSpyChat->getCurrentGroupRoomID()); - gpSetStatus(TheGPConnection, GP_CHATTING, "Chatting", s.str()); - } - else - { - gpSetStatus(TheGPConnection, GP_ONLINE, "Online", ""); - } - } -} - -// Gets called once for each group room when listing group rooms. -// After this has been called for each group room, it will be -// called one more time with groupID==0 and name==NULL. -///////////////////////////////////////////////////////////////// -void ListGroupRoomsCallback(PEER peer, PEERBool success, - int groupID, GServer server, - const char * name, int numWaiting, - int maxWaiting, int numGames, - int numPlaying, void * param) -{ - DEBUG_LOG(("ListGroupRoomsCallback\n")); - if (success) - { - if (groupID) - { - GroupRoomMap *grMap = TheGameSpyChat->getGroupRooms(); - (*grMap)[groupID].m_name = name; - (*grMap)[groupID].m_numWaiting = numWaiting; - (*grMap)[groupID].m_maxWaiting = maxWaiting; - (*grMap)[groupID].m_numGames = numGames; - (*grMap)[groupID].m_numPlaying = numPlaying; - (*grMap)[groupID].m_groupID = groupID; - } - else - { - // we've got the complete list. - UpdateGroupRoomList(); - } - } -} - -// Called when peerConnect completes. -static void connectCallback(PEER peer, PEERBool success, void * param) -{ - ((GameSpyChat *)TheGameSpyChat)->_connectCallback(peer, success, param); -} - -static void nickErrorCallback(PEER peer, int type, const char * nick, void * param) -{ - ((GameSpyChat *)TheGameSpyChat)->_nickErrorCallback(peer, type, nick, param); -} - -static void GPConnectCallback(GPConnection * pconnection, GPConnectResponseArg * arg, void * param) -{ - ((GameSpyChat *)TheGameSpyChat)->_GPConnectCallback(pconnection, arg, param); -} - -static void GPReconnectCallback(GPConnection * pconnection, GPConnectResponseArg * arg, void * param) -{ - ((GameSpyChat *)TheGameSpyChat)->_GPReconnectCallback(pconnection, arg, param); -} - -void GameSpyChat::_connectCallback(PEER peer, PEERBool success, void * param) -{ - m_loginTimeout = 0; - - if (!success) { - GSMessageBoxOk(UnicodeString(L"Error connecting"), UnicodeString(L"Failed to connect"), NULL); - DEBUG_LOG(("GameSpyChat::_connectCallback - failed to connect.\n")); - } - - if(!success) - { - peerShutdown(m_peer); - m_peer = NULL; - gpDisconnect(TheGPConnection); - gpDestroy(TheGPConnection); - - // Enable controls again - //EnableLoginControls(TRUE); - return; - } - - DEBUG_LOG(("Connected as profile %d (%s)\n", m_profileID, m_loginName.str())); - - TheGameSpyGame = NEW GameSpyGameInfo; - - // Enable controls again - //EnableLoginControls(TRUE); - - // the readFromServer() call will set the screen - if (m_profileID) - { - TheGameSpyPlayerInfo->readFromServer(); - } - - TheScriptEngine->signalUIInteract("GameSpyLogin"); - - TheShell->popImmediate(); - TheShell->push("Menus/WOLWelcomeMenu.wnd"); - - clearGroupRoomList(); - peerListGroupRooms(m_peer, ListGroupRoomsCallback, NULL, PEERFalse); -} - -// Called if there's an error with the nick. -void GameSpyChat::_nickErrorCallback(PEER peer, int type, const char * nick, void * param) -{ - // Let the user know. - ///////////////////// - if(type == PEER_IN_USE) - { - AsciiString nickStr = nick; - AsciiString origName, appendedVal; - nickStr.nextToken(&origName, "{}"); - nickStr.nextToken(&appendedVal, "{}"); - Int intVal = 1; - if (!appendedVal.isEmpty()) - { - intVal = atoi(appendedVal.str()) + 1; - } - DEBUG_LOG(("Nickname taken: origName=%s, tries=%d\n", origName.str(), intVal)); - - if (intVal < 10) - { - nickStr.format("%s{%d}", origName.str(), intVal); - // Retry the connect with a similar nick. - DEBUG_LOG(("GameSpyChat::_nickErrorCallback - nick was taken, setting to %s\n", nickStr.str())); - m_loginName = nickStr; - peerRetryWithNick(peer, nickStr.str()); - } - else - { - GSMessageBoxOk(UnicodeString(L"Error connecting"), UnicodeString(L"That nickname is already taken; please choose another one."), NULL); - // Cancel the connect. - peerRetryWithNick(peer, NULL); - - // Enable controls again - //EnableLoginControls(TRUE); - m_loginTimeout = 0; - } - } - else - { - GSMessageBoxOk(UnicodeString(L"Error connecting"), UnicodeString(L"That nickname contains at least 1 invalid character, please choose another one."), NULL); - // Cancel the connect. - peerRetryWithNick(peer, NULL); - - // Enable controls again - //EnableLoginControls(TRUE); - m_loginTimeout = 0; - } -} - -void GameSpyChat::_GPConnectCallback(GPConnection * pconnection, GPConnectResponseArg * arg, void * param) -{ - DEBUG_LOG(("GPConnectCallback:\n")); - GPResult *res = (GPResult *)param; - *res = arg->result; - - setProfileID(arg->profile); - - if (*res != GP_NO_ERROR) - { - // couldn't connect. bummer. - GSMessageBoxOk(UnicodeString(L"Error connecting"), UnicodeString(L"Error connecting to buddy server"), NULL); - gpDisconnect(TheGPConnection); - gpDestroy(TheGPConnection); - m_loginTimeout = 0; - return; - } - - // Connect to chat. - /////////////////// - peerConnect(m_peer, m_loginName.str(), m_profileID, nickErrorCallback, connectCallback, NULL, PEERFalse); -} - -static Bool inGPReconnect = false; -void GameSpyChat::_GPReconnectCallback(GPConnection * pconnection, GPConnectResponseArg * arg, void * param) -{ - inGPReconnect = false; - DEBUG_LOG(("GPConnectCallback:\n")); - - setProfileID(arg->profile); - - if (arg->result != GP_NO_ERROR) - { - // couldn't connect. bummer. - GSMessageBoxOk(UnicodeString(L"Error connecting"), UnicodeString(L"Error connecting to buddy server"), NULL); - gpDisconnect(TheGPConnection); - gpDestroy(TheGPConnection); - return; - } - else - { - // yay! we're back in! - GSMessageBoxOk(UnicodeString(L"Connected!"), UnicodeString(L"Reonnected to buddy server"), NULL); - } -} - -void GameSpyChat::loginProfile(AsciiString loginName, AsciiString password, AsciiString email) -{ - // Connect to GP. - /////////////////// - m_profileID = 0; - gpInitialize(TheGPConnection, 0); - gpSetCallback(TheGPConnection, GP_ERROR, (GPCallback)GPErrorCallback, NULL); - gpSetCallback(TheGPConnection, GP_RECV_BUDDY_REQUEST, (GPCallback)GPRecvBuddyRequestCallback, NULL); - gpSetCallback(TheGPConnection, GP_RECV_BUDDY_MESSAGE, (GPCallback)GPRecvBuddyMessageCallback, NULL); - gpSetCallback(TheGPConnection, GP_RECV_BUDDY_STATUS, (GPCallback)GPRecvBuddyStatusCallback, NULL); - - GPResult res = GP_PARAMETER_ERROR; - m_loginName = loginName; - DEBUG_LOG(("GameSpyChat::loginProfile - m_loginName set to %s\n", m_loginName.str())); - m_password = password; - m_email = email; - gpConnect(TheGPConnection, loginName.str(), email.str(), password.str(), GP_FIREWALL, GP_NON_BLOCKING, (GPCallback)GPConnectCallback, &res); - /* - if (res != GP_NO_ERROR) - { - // couldn't connect. bummer. - GSMessageBoxOk(UnicodeString(L"Error connecting"), UnicodeString(L"Error connecting to buddy server"), NULL); - gpDisconnect(TheGPConnection); - gpDestroy(TheGPConnection); - loginTimeout = 0; - return; - } - - // Connect to chat. - /////////////////// - GameSpyLocalNickname = loginName; - peerConnect(TheGameSpyChat->getPeer(), loginName.str(), GameSpyLocalProfile, nickErrorCallback, connectCallback, NULL, PEERFalse); - */ -} - -void GameSpyChat::reconnectProfile( void ) -{ - if (inGPReconnect) - return; - - inGPReconnect = true; - - gpInitialize(TheGPConnection, 0); - gpSetCallback(TheGPConnection, GP_ERROR, (GPCallback)GPErrorCallback, NULL); - gpSetCallback(TheGPConnection, GP_RECV_BUDDY_REQUEST, (GPCallback)GPRecvBuddyRequestCallback, NULL); - gpSetCallback(TheGPConnection, GP_RECV_BUDDY_MESSAGE, (GPCallback)GPRecvBuddyMessageCallback, NULL); - gpSetCallback(TheGPConnection, GP_RECV_BUDDY_STATUS, (GPCallback)GPRecvBuddyStatusCallback, NULL); - - gpConnect(TheGPConnection, m_loginName.str(), m_email.str(), m_password.str(), GP_FIREWALL, GP_NON_BLOCKING, (GPCallback)GPReconnectCallback, NULL); -} - -void GameSpyChat::loginQuick(AsciiString login) -{ - m_profileID = 0; // no buddy stuff - - // Connect to chat. - /////////////////// - m_loginName = login; - DEBUG_LOG(("GameSpyChat::loginQuick - setting login to %s\n", m_loginName)); - peerConnect(m_peer, login.str(), 0, nickErrorCallback, connectCallback, NULL, PEERFalse); -} - -void GameSpyChat::login(AsciiString loginName, AsciiString password, AsciiString email) -{ - MutexClass::LockClass m(TheGameSpyMutex); - if ( ISMAINTHREAD ) - { - thread.queueLogin(loginName, password, email); - return; - } - - // Setup the callbacks. - /////////////////////// - PEERCallbacks callbacks; - memset(&callbacks, 0, sizeof(PEERCallbacks)); - callbacks.disconnected = DisconnectedCallback; - callbacks.readyChanged = ReadyChangedCallback; - callbacks.roomMessage = RoomMessageCallback; - callbacks.playerMessage = PlayerMessageCallback; - callbacks.gameStarted = GameStartedCallback; - callbacks.playerJoined = PlayerJoinedCallback; - callbacks.playerLeft = PlayerLeftCallback; - callbacks.playerChangedNick = PlayerChangedNickCallback; - callbacks.ping = PingCallback; - callbacks.crossPing = CrossPingCallback; - callbacks.roomUTM = RoomUTMCallback; - callbacks.playerUTM = PlayerUTMCallback; - callbacks.GOABasic = GOABasicCallback; - callbacks.GOAInfo = GOAInfoCallback; - callbacks.GOARules = GOARulesCallback; - callbacks.GOAPlayers = GOAPlayersCallback; - //callbacks.globalKeyChanged = GlobalKeyChanged; - callbacks.param = NULL; - - // Init peer. - ///////////// - m_peer = peerInitialize(&callbacks); - if(!m_peer) - { - GSMessageBoxOk(UnicodeString(L"No Peer"), UnicodeString(L"No Peer"), NULL); - return; - } - - // Setup which rooms to do pings and cross-pings in. - //////////////////////////////////////////////////// - PEERBool pingRooms[NumRooms]; - PEERBool crossPingRooms[NumRooms]; - pingRooms[TitleRoom] = PEERTrue; - pingRooms[GroupRoom] = PEERTrue; - pingRooms[StagingRoom] = PEERFalse; - crossPingRooms[TitleRoom] = PEERFalse; - crossPingRooms[GroupRoom] = PEERFalse; - crossPingRooms[StagingRoom] = PEERTrue; - - // Set the title. - ///////////////// - if(!peerSetTitle(m_peer, "gmtest", "HA6zkS", "gmtest", "HA6zkS", 15, pingRooms, crossPingRooms)) - { - GSMessageBoxOk(UnicodeString(L"Error setting title"), UnicodeString(L"Error setting title"), NULL); - peerShutdown(m_peer); - m_peer = NULL; - return; - } - - //EnableLoginControls( FALSE ); - m_loginTimeout = timeGetTime() + m_loginTimeoutPeriod; - if (!loginName.isEmpty() && !email.isEmpty() && !password.isEmpty()) - { - m_usingProfiles = true; - loginProfile(loginName, password, email); - } - else - { - m_usingProfiles = false; - loginQuick(loginName); - } -} diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Chat.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Chat.cpp deleted file mode 100644 index 69e7b659790..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Chat.cpp +++ /dev/null @@ -1,339 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: Chat.cpp ////////////////////////////////////////////////////// -// Generals GameSpy chat-related code -// Author: Matthew D. Campbell, July 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/AudioEventRTS.h" -#include "Common/INI.h" -#include "GameClient/GameText.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/LanguageFilter.h" -#include "GameClient/GameWindowManager.h" -#include "GameNetwork/GameSpy/PeerDefsImplementation.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameClient/InGameUI.h" -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -#define OFFSET(x) (sizeof(Int) * (x)) -static const FieldParse GameSpyColorFieldParse[] = -{ - - { "Default", INI::parseColorInt, NULL, OFFSET(GSCOLOR_DEFAULT) }, - { "CurrentRoom", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CURRENTROOM) }, - { "ChatRoom", INI::parseColorInt, NULL, OFFSET(GSCOLOR_ROOM) }, - { "Game", INI::parseColorInt, NULL, OFFSET(GSCOLOR_GAME) }, - { "GameFull", INI::parseColorInt, NULL, OFFSET(GSCOLOR_GAME_FULL) }, - { "GameCRCMismatch", INI::parseColorInt, NULL, OFFSET(GSCOLOR_GAME_CRCMISMATCH) }, - { "PlayerNormal", INI::parseColorInt, NULL, OFFSET(GSCOLOR_PLAYER_NORMAL) }, - { "PlayerOwner", INI::parseColorInt, NULL, OFFSET(GSCOLOR_PLAYER_OWNER) }, - { "PlayerBuddy", INI::parseColorInt, NULL, OFFSET(GSCOLOR_PLAYER_BUDDY) }, - { "PlayerSelf", INI::parseColorInt, NULL, OFFSET(GSCOLOR_PLAYER_SELF) }, - { "PlayerIgnored", INI::parseColorInt, NULL, OFFSET(GSCOLOR_PLAYER_IGNORED) }, - { "ChatNormal", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_NORMAL) }, - { "ChatEmote", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_EMOTE) }, - { "ChatOwner", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_OWNER) }, - { "ChatOwnerEmote", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_OWNER_EMOTE) }, - { "ChatPriv", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_PRIVATE) }, - { "ChatPrivEmote", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_PRIVATE_EMOTE) }, - { "ChatPrivOwner", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_PRIVATE_OWNER) }, - { "ChatPrivOwnerEmote", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_PRIVATE_OWNER_EMOTE) }, - { "ChatBuddy", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_BUDDY) }, - { "ChatSelf", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_SELF) }, - { "AcceptTrue", INI::parseColorInt, NULL, OFFSET(GSCOLOR_ACCEPT_TRUE) }, - { "AcceptFalse", INI::parseColorInt, NULL, OFFSET(GSCOLOR_ACCEPT_FALSE) }, - { "MapSelected", INI::parseColorInt, NULL, OFFSET(GSCOLOR_MAP_SELECTED) }, - { "MapUnselected", INI::parseColorInt, NULL, OFFSET(GSCOLOR_MAP_UNSELECTED) }, - { "MOTD", INI::parseColorInt, NULL, OFFSET(GSCOLOR_MOTD) }, - { "MOTDHeading", INI::parseColorInt, NULL, OFFSET(GSCOLOR_MOTD_HEADING) }, - - { NULL, NULL, NULL, 0 } // keep this last - -}; - -void INI::parseOnlineChatColorDefinition( INI* ini ) -{ - // parse the ini definition - ini->initFromINI( GameSpyColor, GameSpyColorFieldParse ); -} - - -Color GameSpyColor[GSCOLOR_MAX] = -{ - GameMakeColor(255,255,255,255), // GSCOLOR_DEFAULT - GameMakeColor(255,255, 0,255), // GSCOLOR_CURRENTROOM - GameMakeColor(255,255,255,255), // GSCOLOR_ROOM - GameMakeColor(128,128,0,255), // GSCOLOR_GAME - GameMakeColor(128,128,128,255), // GSCOLOR_GAME_FULL - GameMakeColor(128,128,128,255), // GSCOLOR_GAME_CRCMISMATCH - GameMakeColor(255, 0, 0,255), // GSCOLOR_PLAYER_NORMAL - GameMakeColor(255, 0,255,255), // GSCOLOR_PLAYER_OWNER - GameMakeColor(255, 0,128,255), // GSCOLOR_PLAYER_BUDDY - GameMakeColor(255, 0, 0,255), // GSCOLOR_PLAYER_SELF - GameMakeColor(128,128,128,255), // GSCOLOR_PLAYER_IGNORED - GameMakeColor(255,0,0,255), // GSCOLOR_CHAT_NORMAL - GameMakeColor(255,128,0,255), // GSCOLOR_CHAT_EMOTE, - GameMakeColor(255,255,0,255), // GSCOLOR_CHAT_OWNER, - GameMakeColor(128,255,0,255), // GSCOLOR_CHAT_OWNER_EMOTE, - GameMakeColor(0,0,255,255), // GSCOLOR_CHAT_PRIVATE, - GameMakeColor(0,255,255,255), // GSCOLOR_CHAT_PRIVATE_EMOTE, - GameMakeColor(255,0,255,255), // GSCOLOR_CHAT_PRIVATE_OWNER, - GameMakeColor(255,128,255,255), // GSCOLOR_CHAT_PRIVATE_OWNER_EMOTE, - GameMakeColor(255, 0,255,255), // GSCOLOR_CHAT_BUDDY, - GameMakeColor(255, 0,128,255), // GSCOLOR_CHAT_SELF, - GameMakeColor( 0,255, 0,255), // GSCOLOR_ACCEPT_TRUE, - GameMakeColor(255, 0, 0,255), // GSCOLOR_ACCEPT_FALSE, - GameMakeColor(255,255, 0,255), // GSCOLOR_MAP_SELECTED, - GameMakeColor(255,255,255,255), // GSCOLOR_MAP_UNSELECTED, - GameMakeColor(255,255,255,255), // GSCOLOR_MOTD, - GameMakeColor(255,255, 0,255), // GSCOLOR_MOTD_HEADING, -}; - -Bool GameSpyInfo::sendChat( UnicodeString message, Bool isAction, GameWindow *playerListbox ) -{ - RoomType roomType = StagingRoom; - if (getCurrentGroupRoom()) - roomType = GroupRoom; - - PeerRequest req; - req.text = message.str(); - - message.trim(); - // Echo the user's input to the chat window - if (!message.isEmpty()) - { - if (!playerListbox) - { - // Public message - req.message.isAction = isAction; - req.peerRequestType = PeerRequest::PEERREQUEST_MESSAGEROOM; - TheGameSpyPeerMessageQueue->addRequest(req); - return false; - } - - // Get the selections (is this a private message?) - Int maxSel = GadgetListBoxGetListLength(playerListbox); - Int *selections; - GadgetListBoxGetSelected(playerListbox, (Int *)&selections); - - if (selections[0] == -1) - { - // Public message - req.message.isAction = isAction; - req.peerRequestType = PeerRequest::PEERREQUEST_MESSAGEROOM; - TheGameSpyPeerMessageQueue->addRequest(req); - return false; - } - else - { - // Private message - - // Construct a list - AsciiString names = AsciiString::TheEmptyString; - AsciiString tmp = AsciiString::TheEmptyString; - AsciiString aStr; // AsciiString buf for translating Unicode entries - names.format("%s", TheGameSpyInfo->getLocalName().str()); - for (int i=0; igetLocalName())) - { - tmp.format(",%s", aStr.str()); - names.concat(tmp); - } - } - else - { - break; - } - } - - if (!names.isEmpty()) - { - req.nick = names.str(); - req.message.isAction = isAction; - req.peerRequestType = PeerRequest::PEERREQUEST_MESSAGEPLAYER; - TheGameSpyPeerMessageQueue->addRequest(req); - } - - return true; - } - } - return false; -} - -void GameSpyInfo::addChat( AsciiString nick, Int profileID, UnicodeString msg, Bool isPublic, Bool isAction, GameWindow *win ) -{ - PlayerInfoMap::iterator it = getPlayerInfoMap()->find(nick); - if (it != getPlayerInfoMap()->end()) - { - addChat( it->second, msg, isPublic, isAction, win ); - } - else - { - } -} - -void GameSpyInfo::addChat( PlayerInfo p, UnicodeString msg, Bool isPublic, Bool isAction, GameWindow *win ) -{ - Int style; - if(isSavedIgnored(p.m_profileID) || isIgnored(p.m_name)) - return; - - Bool isOwner = p.m_flags & PEER_FLAG_OP; - Bool isBuddy = getBuddyMap()->find(p.m_profileID) != getBuddyMap()->end(); - - Bool isMe = p.m_name.compare(TheGameSpyInfo->getLocalName()) == 0; - - if(!isMe) - { - if(m_disallowAsainText) - { - const WideChar *buff = msg.str(); - Int length = msg.getLength(); - for(Int i = 0; i < length; ++i) - { - if(buff[i] >= 256) - return; - } - } - else if(m_disallowNonAsianText) - { - const WideChar *buff = msg.str(); - Int length = msg.getLength(); - Bool hasUnicode = FALSE; - for(Int i = 0; i < length; ++i) - { - if(buff[i] >= 256) - { - hasUnicode = TRUE; - break; - } - } - if(!hasUnicode) - return; - } - - if (!isPublic) - { - AudioEventRTS privMsgAudio("GUIMessageReceived"); - - if( TheAudio ) - { - TheAudio->addAudioEvent( &privMsgAudio ); - } // end if - } - } - - - if (isBuddy) - { - style = GSCOLOR_CHAT_BUDDY; - } - else if (isPublic && isAction) - { - style = (isOwner)?GSCOLOR_CHAT_OWNER_EMOTE:GSCOLOR_CHAT_EMOTE; - } - else if (isPublic) - { - style = (isOwner)?GSCOLOR_CHAT_OWNER:GSCOLOR_CHAT_NORMAL; - } - else if (isAction) - { - style = (isOwner)?GSCOLOR_CHAT_PRIVATE_OWNER_EMOTE:GSCOLOR_CHAT_PRIVATE_EMOTE; - } - else - { - style = (isOwner)?GSCOLOR_CHAT_PRIVATE_OWNER:GSCOLOR_CHAT_PRIVATE; - } - - UnicodeString name; - name.translate(p.m_name); - - // filters language -// if( TheGlobalData->m_languageFilterPref ) -// { - TheLanguageFilter->filterLine(msg); -// } - - UnicodeString fullMsg; - if (isAction) - { - fullMsg.format( L"%ls %ls", name.str(), msg.str() ); - } - else - { - fullMsg.format( L"[%ls] %ls", name.str(), msg.str() ); - } - - Int index = addText(fullMsg, GameSpyColor[style], win); - if (index >= 0) - { - GadgetListBoxSetItemData(win, (void *)p.m_profileID, index); - } -} - -Int GameSpyInfo::addText( UnicodeString message, Color c, GameWindow *win ) -{ - if (TheGameSpyGame && TheGameSpyGame->isInGame() && TheGameSpyGame->isGameInProgress()) - { - static AudioEventRTS messageFromChatSound("GUIMessageReceived"); - TheAudio->addAudioEvent(&messageFromChatSound); - - TheInGameUI->message(message); - } - - if (!win) - { - // try to pick up a registered text window - if (m_textWindows.empty()) - return -1; - - win = *(m_textWindows.begin()); - } - Int index = GadgetListBoxAddEntryText(win, message, c, -1, -1); - GadgetListBoxSetItemData(win, (void *)-1, index); - - return index; -} - -void GameSpyInfo::registerTextWindow( GameWindow *win ) -{ - m_textWindows.insert(win); -} - -void GameSpyInfo::unregisterTextWindow( GameWindow *win ) -{ - m_textWindows.erase(win); -} - diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/GSConfig.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/GSConfig.cpp deleted file mode 100644 index 60be316d5e7..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/GSConfig.cpp +++ /dev/null @@ -1,487 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: GSConfig.cpp -// Author: Matthew D. Campbell, Sept 2002 -// Description: GameSpy online config -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameState.h" -#include "GameClient/MapUtil.h" -#include "GameNetwork/GameSpy/GSConfig.h" -#include "GameNetwork/RankPointValue.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -/////////////////////////////////////////////////////////////////////////////////////// - -GameSpyConfigInterface *TheGameSpyConfig = NULL; - -class GameSpyConfig : public GameSpyConfigInterface -{ -public: - GameSpyConfig( AsciiString config ); - ~GameSpyConfig() {} - - // Pings - std::list getPingServers(void) { return m_pingServers; } - Int getNumPingRepetitions(void) { return m_pingReps; } - Int getPingTimeoutInMs(void) { return m_pingTimeout; } - virtual Int getPingCutoffGood( void ) { return m_pingCutoffGood; } - virtual Int getPingCutoffBad( void ) { return m_pingCutoffBad; } - - // QM - std::list getQMMaps(void) { return m_qmMaps; } - Int getQMBotID(void) { return m_qmBotID; } - Int getQMChannel(void) { return m_qmChannel; } - void setQMChannel(Int channel) { m_qmChannel = channel; } - - // Player Info - Int getPointsForRank(Int rank); - virtual Bool isPlayerVIP(Int id); - - virtual Bool getManglerLocation(Int index, AsciiString& host, UnsignedShort& port); - - // Ladder / Any other external parsing - AsciiString getLeftoverConfig(void) { return m_leftoverConfig; } - - // NAT Timeouts - virtual Int getTimeBetweenRetries() { return m_natRetryInterval; } - virtual Int getMaxManglerRetries() { return m_natMaxManglerRetries; } - virtual time_t getRetryInterval() { return m_natManglerRetryInterval; } - virtual time_t getKeepaliveInterval() { return m_natKeepaliveInterval; } - virtual time_t getPortTimeout() { return m_natPortTimeout; } - virtual time_t getRoundTimeout() { return m_natRoundTimeout; } - - // Custom match - virtual Bool restrictGamesToLobby() { return m_restrictGamesToLobby; } - -protected: - std::list m_pingServers; - Int m_pingReps; - Int m_pingTimeout; - Int m_pingCutoffGood; - Int m_pingCutoffBad; - - Int m_natRetryInterval; - Int m_natMaxManglerRetries; - time_t m_natManglerRetryInterval; - time_t m_natKeepaliveInterval; - time_t m_natPortTimeout; - time_t m_natRoundTimeout; - - std::vector m_manglerHosts; - std::vector m_manglerPorts; - - std::list m_qmMaps; - Int m_qmBotID; - Int m_qmChannel; - - Bool m_restrictGamesToLobby; - - std::set m_vip; // VIP people - - Int m_rankPoints[MAX_RANKS]; - - AsciiString m_leftoverConfig; -}; - -/////////////////////////////////////////////////////////////////////////////////////// - -GameSpyConfigInterface* GameSpyConfigInterface::create(AsciiString config) -{ - return NEW GameSpyConfig(config); -} - -/////////////////////////////////////////////////////////////////////////////////////// - -class SectionChecker -{ -public: - typedef std::list SectionList; - void addVar(const Bool *var) { m_bools.push_back(var); } - Bool isInSection(); -protected: - SectionList m_bools; -}; -Bool SectionChecker::isInSection() { - Bool ret = FALSE; - for (SectionList::const_iterator it = m_bools.begin(); it != m_bools.end(); ++it) - { - ret = ret || **it; - } - return ret; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -GameSpyConfig::GameSpyConfig( AsciiString config ) : -m_natRetryInterval(1000), -m_natMaxManglerRetries(25), -m_natManglerRetryInterval(300), -m_natKeepaliveInterval(15000), -m_natPortTimeout(10000), -m_natRoundTimeout(10000), -m_pingReps(1), -m_pingTimeout(1000), -m_pingCutoffGood(300), -m_pingCutoffBad(600), -m_restrictGamesToLobby(FALSE), -m_qmBotID(0), -m_qmChannel(0) -{ - m_rankPoints[0] = 0; - m_rankPoints[1] = 5; - m_rankPoints[2] = 10; - m_rankPoints[3] = 20; - m_rankPoints[4] = 50; - m_rankPoints[5] = 100; - m_rankPoints[6] = 200; - m_rankPoints[7] = 500; - m_rankPoints[8] = 1000; - m_rankPoints[9] = 2000; - - AsciiString line; - Bool inPingServers = FALSE; - Bool inPingDuration = FALSE; - Bool inQMMaps = FALSE; - Bool inQMBot = FALSE; - Bool inManglers = FALSE; - Bool inVIP = FALSE; - Bool inNAT = FALSE; - Bool inCustom = FALSE; - - SectionChecker sections; - sections.addVar(&inPingServers); - sections.addVar(&inPingDuration); - sections.addVar(&inQMMaps); - sections.addVar(&inQMBot); - sections.addVar(&inManglers); - sections.addVar(&inVIP); - sections.addVar(&inNAT); - sections.addVar(&inCustom); - - while (config.nextToken(&line, "\n")) - { - if (line.getCharAt(line.getLength()-1) == '\r') - line.removeLastChar(); // there is a trailing '\r' - - line.trim(); - - if (line.isEmpty()) - continue; - - if (!sections.isInSection() && line.compare("") == 0) - { - inPingServers = TRUE; - } - else if (inPingServers && line.compare("") == 0) - { - inPingServers = FALSE; - } - else if (!sections.isInSection() && line.compare("") == 0) - { - inPingDuration = TRUE; - } - else if (inPingDuration && line.compare("") == 0) - { - inPingDuration = FALSE; - } - else if (!sections.isInSection() && line.compare("") == 0) - { - inQMMaps = TRUE; - } - else if (inQMMaps && line.compare("") == 0) - { - inQMMaps = FALSE; - } - else if (!sections.isInSection() && line.compare("") == 0) - { - inManglers = TRUE; - } - else if (inManglers && line.compare("") == 0) - { - inManglers = FALSE; - } - else if (!sections.isInSection() && line.compare("") == 0) - { - inQMBot = TRUE; - } - else if (inQMBot && line.compare("") == 0) - { - inQMBot = FALSE; - } - else if (!sections.isInSection() && line.compare("") == 0) - { - inVIP = TRUE; - } - else if (inVIP && line.compare("") == 0) - { - inVIP = FALSE; - } - else if (!sections.isInSection() && line.compare("") == 0) - { - inNAT = TRUE; - } - else if (inNAT && line.compare("") == 0) - { - inNAT = FALSE; - } - else if (!sections.isInSection() && line.compare("") == 0) - { - inCustom = TRUE; - } - else if (inCustom && line.compare("") == 0) - { - inCustom = FALSE; - } - else if (inVIP) - { - line.toLower(); - if (line.getLength()) - { - Int val = atoi(line.str()); - if (val > 0) - m_vip.insert(val); - } - } - else if (inPingServers) - { - line.toLower(); - m_pingServers.push_back(line); - } - else if (inPingDuration) - { - line.toLower(); - AsciiString key, val; - if (line.nextToken(&key, " =")) - { - if (key == "reps") - { - if (line.nextToken(&val, " =")) - { - m_pingReps = atoi(val.str()); - } - } - else if (key == "timeout") - { - if (line.nextToken(&val, " =")) - { - m_pingTimeout = atoi(val.str()); - } - } - else if (key == "low") - { - if (line.nextToken(&val, " =")) - { - m_pingCutoffGood = atoi(val.str()); - } - } - else if (key == "med") - { - if (line.nextToken(&val, " =")) - { - m_pingCutoffBad = atoi(val.str()); - } - } - } - } - else if (inManglers) - { - line.trim(); - line.toLower(); - AsciiString hostStr; - AsciiString portStr; - line.nextToken(&hostStr, ":"); - line.nextToken(&portStr, ":\n\r"); - if (hostStr.isNotEmpty() && portStr.isNotEmpty()) - { - m_manglerHosts.push_back(hostStr); - m_manglerPorts.push_back(atoi(portStr.str())); - } - } - else if (inQMMaps) - { - line.toLower(); - AsciiString mapName; - mapName.format("%s\\%s\\%s.map", TheMapCache->getMapDir().str(), line.str(), line.str()); - mapName = TheGameState->portableMapPathToRealMapPath(TheGameState->realMapPathToPortableMapPath(mapName)); - mapName.toLower(); - - // [SKB: Jul 01 2003 @ 6:43pm] : - // German2 is missing some maps because of content. But, we need the m_qmMaps - // to contain same number of strings as the Retail version so that the - // QM Bot thinks that they have the same number of maps. - #if 1 - m_qmMaps.push_back(mapName); - #else - const MapMetaData *md = TheMapCache->findMap(mapName); - if (md) - { - m_qmMaps.push_back(mapName); - } - #endif - } - else if (inQMBot) - { - line.toLower(); - AsciiString key, val; - if (line.nextToken(&key, " =")) - { - if (key == "id") - { - if (line.nextToken(&val, " =")) - { - m_qmBotID = atoi(val.str()); - } - } - } - } - else if (inNAT) - { - line.toLower(); - AsciiString key, val; - if (line.nextToken(&key, " =")) - { - if (key == "retryinterval") - { - if (line.nextToken(&val, " =")) - { - m_natRetryInterval = atoi(val.str()); - } - } - else if (key == "manglerretries") - { - if (line.nextToken(&val, " =")) - { - m_natMaxManglerRetries = atoi(val.str()); - } - } - else if (key == "manglerinterval") - { - if (line.nextToken(&val, " =")) - { - m_natManglerRetryInterval = atoi(val.str()); - } - } - else if (key == "keepaliveinterval") - { - if (line.nextToken(&val, " =")) - { - m_natKeepaliveInterval = atoi(val.str()); - } - } - else if (key == "porttimeout") - { - if (line.nextToken(&val, " =")) - { - m_natPortTimeout = atoi(val.str()); - } - } - else if (key == "roundtimeout") - { - if (line.nextToken(&val, " =")) - { - m_natRoundTimeout = atoi(val.str()); - } - } - else - { - DEBUG_LOG(("Unknown key '%s' = '%s' in NAT block of GameSpy Config\n", key.str(), val.str())); - } - } - else - { - DEBUG_LOG(("Key '%s' missing val in NAT block of GameSpy Config\n", key.str())); - } - } - else if (inCustom) - { - line.toLower(); - AsciiString key, val; - if (line.nextToken(&key, " =") && line.nextToken(&val, " =")) - { - if (key == "restricted") - { - m_restrictGamesToLobby = atoi(val.str()); - } - else - { - DEBUG_LOG(("Unknown key '%s' = '%s' in Custom block of GameSpy Config\n", key.str(), val.str())); - } - } - else - { - DEBUG_LOG(("Key '%s' missing val in Custom block of GameSpy Config\n", key.str())); - } - } - else - { - m_leftoverConfig.concat(line); - m_leftoverConfig.concat('\n'); - } - } - -} - -/////////////////////////////////////////////////////////////////////////////////////// - -Int GameSpyConfig::getPointsForRank(Int rank) -{ - if (rank >= MAX_RANKS) rank = MAX_RANKS-1; - if (rank < 0) rank = 0; - return m_rankPoints[rank]; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -Bool GameSpyConfig::getManglerLocation(Int index, AsciiString& host, UnsignedShort& port) -{ - if (index < 0 || index >= m_manglerHosts.size()) - { - return FALSE; - } - - host = m_manglerHosts[index]; - port = m_manglerPorts[index]; - return TRUE; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -Bool GameSpyConfig::isPlayerVIP(Int id) -{ - std::set::const_iterator it = std::find(m_vip.begin(), m_vip.end(), id); - return it != m_vip.end(); -} - -/////////////////////////////////////////////////////////////////////////////////////// diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp deleted file mode 100644 index b7635ac0dd8..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp +++ /dev/null @@ -1,527 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: LadderDefs.cpp ////////////////////////////////////////////////////// -// Generals ladder code -// Author: Matthew D. Campbell, August 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "GameNetwork/GameSpy/ThreadUtils.h" -#include "GameNetwork/GameSpy/LadderDefs.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/GSConfig.h" -#include "Common/GameState.h" -#include "Common/File.h" -#include "Common/FileSystem.h" -#include "Common/PlayerTemplate.h" -#include "GameClient/GameText.h" -#include "GameClient/MapUtil.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -LadderList *TheLadderList = NULL; - -LadderInfo::LadderInfo() -{ - playersPerTeam = 1; - minWins = 0; - maxWins = 0; - randomMaps = TRUE; - randomFactions = TRUE; - validQM = TRUE; - validCustom = FALSE; - port = 0; - submitReplay = FALSE; - index = -1; -} - -static LadderInfo *parseLadder(AsciiString raw) -{ - DEBUG_LOG(("Looking at ladder:\n%s\n", raw.str())); - LadderInfo *lad = NULL; - AsciiString line; - while (raw.nextToken(&line, "\n")) - { - if (line.getCharAt(line.getLength()-1) == '\r') - line.removeLastChar(); // there is a trailing '\r' - - line.trim(); - - if (line.isEmpty()) - continue; - - // woohoo! got a line! - line.trim(); - if ( !lad && line.startsWith("' - line = line.str() + 7; // the "name = MultiByteToWideCharSingleLine(tokenName.str()).c_str(); - while (lad->name.getLength() > 20) - lad->name.removeLastChar(); // Per Harvard's request, ladder names are limited to 20 chars - lad->address = tokenAddr; - lad->port = atoi(tokenPort.str()); - lad->homepageURL = tokenHomepage; - } - else if ( lad && line.startsWith("Name ") ) - { - lad->name = MultiByteToWideCharSingleLine(line.str() + 5).c_str(); - } - else if ( lad && line.startsWith("Desc ") ) - { - lad->description = MultiByteToWideCharSingleLine(line.str() + 5).c_str(); - } - else if ( lad && line.startsWith("Loc ") ) - { - lad->location = MultiByteToWideCharSingleLine(line.str() + 4).c_str(); - } - else if ( lad && line.startsWith("TeamSize ") ) - { - lad->playersPerTeam = atoi(line.str() + 9); - } - else if ( lad && line.startsWith("RandomMaps ") ) - { - lad->randomMaps = atoi(line.str() + 11); - } - else if ( lad && line.startsWith("RandomFactions ") ) - { - lad->randomFactions = atoi(line.str() + 15); - } - else if ( lad && line.startsWith("Faction ") ) - { - AsciiString faction = line.str() + 8; - AsciiStringList outStringList; - ThePlayerTemplateStore->getAllSideStrings(&outStringList); - - AsciiStringList::iterator aIt = std::find(outStringList.begin(), outStringList.end(), faction); - if (aIt != outStringList.end()) - { - // valid faction - now check for dupes - aIt = std::find(lad->validFactions.begin(), lad->validFactions.end(), faction); - if (aIt == lad->validFactions.end()) - { - lad->validFactions.push_back(faction); - } - } - } - /* - else if ( lad && line.startsWith("QM ") ) - { - lad->validQM = atoi(line.str() + 3); - } - else if ( lad && line.startsWith("Custom ") ) - { - lad->validCustom = atoi(line.str() + 7); - } - */ - else if ( lad && line.startsWith("MinWins ") ) - { - lad->minWins = atoi(line.str() + 8); - } - else if ( lad && line.startsWith("MaxWins ") ) - { - lad->maxWins = atoi(line.str() + 8); - } - else if ( lad && line.startsWith("CryptedPass ") ) - { - lad->cryptedPassword = line.str() + 12; - } - else if ( lad && line.compare("") == 0 ) - { - DEBUG_LOG(("Saw a ladder: name=%ls, addr=%s:%d, players=%dv%d, pass=%s, replay=%d, homepage=%s\n", - lad->name.str(), lad->address.str(), lad->port, lad->playersPerTeam, lad->playersPerTeam, lad->cryptedPassword.str(), - lad->submitReplay, lad->homepageURL.str())); - // end of a ladder - if (lad->playersPerTeam >= 1 && lad->playersPerTeam <= MAX_SLOTS/2) - { - if (lad->validFactions.size() == 0) - { - DEBUG_LOG(("No factions specified. Using all.\n")); - lad->validFactions.push_back("America"); - lad->validFactions.push_back("China"); - lad->validFactions.push_back("GLA"); - } - else - { - AsciiStringList validFactions = lad->validFactions; - for (AsciiStringListIterator it = validFactions.begin(); it != validFactions.end(); ++it) - { - AsciiString faction = *it; - AsciiString marker; - marker.format("INI:Faction%s", faction.str()); - DEBUG_LOG(("Faction %s has marker %s corresponding to str %ls\n", faction.str(), marker.str(), TheGameText->fetch(marker).str())); - } - } - - if (lad->validMaps.size() == 0) - { - DEBUG_LOG(("No maps specified. Using all.\n")); - std::list qmMaps = TheGameSpyConfig->getQMMaps(); - for (std::list::const_iterator it = qmMaps.begin(); it != qmMaps.end(); ++it) - { - AsciiString mapName = *it; - - // check sizes on the maps before allowing them - const MapMetaData *md = TheMapCache->findMap(mapName); - if (md && md->m_numPlayers >= lad->playersPerTeam*2) - { - lad->validMaps.push_back(mapName); - } - } - } - return lad; - } - else - { - // no maps? don't play on it! - delete lad; - lad = NULL; - return NULL; - } - } - else if ( lad && line.startsWith("Map ") ) - { - // valid map - AsciiString mapName = line.str() + 4; - mapName.trim(); - if (mapName.isNotEmpty()) - { - mapName.format("%s\\%s\\%s.map", TheMapCache->getMapDir().str(), mapName.str(), mapName.str()); - mapName = TheGameState->portableMapPathToRealMapPath(TheGameState->realMapPathToPortableMapPath(mapName)); - mapName.toLower(); - std::list qmMaps = TheGameSpyConfig->getQMMaps(); - if (std::find(qmMaps.begin(), qmMaps.end(), mapName) != qmMaps.end()) - { - // check sizes on the maps before allowing them - const MapMetaData *md = TheMapCache->findMap(mapName); - if (md && md->m_numPlayers >= lad->playersPerTeam*2) - lad->validMaps.push_back(mapName); - } - } - } - else - { - // bad ladder - kill it - delete lad; - lad = NULL; - } - } - - if (lad) - { - delete lad; - lad = NULL; - } - return NULL; -} - -LadderList::LadderList() -{ - //Int profile = TheGameSpyInfo->getLocalProfileID(); - - AsciiString rawMotd = TheGameSpyConfig->getLeftoverConfig(); - AsciiString line; - Bool inLadders = FALSE; - Bool inSpecialLadders = FALSE; - Bool inLadder = FALSE; - LadderInfo *lad = NULL; - Int index = 1; - AsciiString rawLadder; - - while (rawMotd.nextToken(&line, "\n")) - { - if (line.getCharAt(line.getLength()-1) == '\r') - line.removeLastChar(); // there is a trailing '\r' - - line.trim(); - - if (line.isEmpty()) - continue; - - if (!inLadders && line.compare("") == 0) - { - inLadders = TRUE; - rawLadder.clear(); - } - else if (inLadders && line.compare("") == 0) - { - inLadders = FALSE; - } - else if (!inSpecialLadders && line.compare("") == 0) - { - inSpecialLadders = TRUE; - rawLadder.clear(); - } - else if (inSpecialLadders && line.compare("") == 0) - { - inSpecialLadders = FALSE; - } - else if (inLadders || inSpecialLadders) - { - if (line.startsWith("") == 0 && inLadder) - { - inLadder = FALSE; - rawLadder.concat(line); - rawLadder.concat('\n'); - if ((lad = parseLadder(rawLadder)) != NULL) - { - lad->index = index++; - if (inLadders) - { - DEBUG_LOG(("Adding to standard ladders\n")); - m_standardLadders.push_back(lad); - } - else - { - DEBUG_LOG(("Adding to special ladders\n")); - m_specialLadders.push_back(lad); - } - } - rawLadder.clear(); - } - else if (inLadder) - { - rawLadder.concat(line); - rawLadder.concat('\n'); - } - } - } - - // look for local ladders - loadLocalLadders(); - - DEBUG_LOG(("After looking for ladders, we have %d local, %d special && %d normal\n", m_localLadders.size(), m_specialLadders.size(), m_standardLadders.size())); -} - -LadderList::~LadderList() -{ - LadderInfoList::iterator it; - for (it = m_specialLadders.begin(); it != m_specialLadders.end(); it = m_specialLadders.begin()) - { - delete *it; - m_specialLadders.pop_front(); - } - for (it = m_standardLadders.begin(); it != m_standardLadders.end(); it = m_standardLadders.begin()) - { - delete *it; - m_standardLadders.pop_front(); - } - for (it = m_localLadders.begin(); it != m_localLadders.end(); it = m_localLadders.begin()) - { - delete *it; - m_localLadders.pop_front(); - } -} - -const LadderInfo* LadderList::findLadder( const AsciiString& addr, UnsignedShort port ) -{ - LadderInfoList::const_iterator cit; - - for (cit = m_specialLadders.begin(); cit != m_specialLadders.end(); ++cit) - { - const LadderInfo *li = *cit; - if (li->address == addr && li->port == port) - { - return li; - } - } - - for (cit = m_standardLadders.begin(); cit != m_standardLadders.end(); ++cit) - { - const LadderInfo *li = *cit; - if (li->address == addr && li->port == port) - { - return li; - } - } - - for (cit = m_localLadders.begin(); cit != m_localLadders.end(); ++cit) - { - const LadderInfo *li = *cit; - if (li->address == addr && li->port == port) - { - return li; - } - } - - return NULL; -} - -const LadderInfo* LadderList::findLadderByIndex( Int index ) -{ - if (index == 0) - return NULL; - - LadderInfoList::const_iterator cit; - - for (cit = m_specialLadders.begin(); cit != m_specialLadders.end(); ++cit) - { - const LadderInfo *li = *cit; - if (li->index == index) - { - return li; - } - } - - for (cit = m_standardLadders.begin(); cit != m_standardLadders.end(); ++cit) - { - const LadderInfo *li = *cit; - if (li->index == index) - { - return li; - } - } - - for (cit = m_localLadders.begin(); cit != m_localLadders.end(); ++cit) - { - const LadderInfo *li = *cit; - if (li->index == index) - { - return li; - } - } - - return NULL; -} - -const LadderInfoList* LadderList::getSpecialLadders( void ) -{ - return &m_specialLadders; -} - -const LadderInfoList* LadderList::getStandardLadders( void ) -{ - return &m_standardLadders; -} - -const LadderInfoList* LadderList::getLocalLadders( void ) -{ - return &m_localLadders; -} - -void LadderList::loadLocalLadders( void ) -{ - AsciiString dirname; - dirname.format("%sGeneralsOnline\\Ladders\\", TheGlobalData->getPath_UserData().str()); - FilenameList filenameList; - TheFileSystem->getFileListInDirectory(dirname, AsciiString("*.ini"), filenameList, TRUE); - - Int index = -1; - - FilenameList::iterator it = filenameList.begin(); - while (it != filenameList.end()) - { - AsciiString filename = *it; - DEBUG_LOG(("Looking at possible ladder info file '%s'\n", filename.str())); - filename.toLower(); - checkLadder( filename, index-- ); - ++it; - } -} - -void LadderList::checkLadder( AsciiString fname, Int index ) -{ - File *fp = TheFileSystem->openFile(fname.str(), File::READ | File::TEXT); - char buf[1024]; - AsciiString rawData; - if (fp) - { - Int len; - while (!fp->eof()) - { - len = fp->read(buf, 1023); - buf[len] = 0; - buf[1023] = 0; - rawData.concat(buf); - } - fp->close(); - fp = NULL; - } - - DEBUG_LOG(("Read %d bytes from '%s'\n", rawData.getLength(), fname.str())); - if (rawData.isEmpty()) - return; - - LadderInfo *li = parseLadder(rawData); - if (!li) - { - return; - } - - // sanity check - if (li->address.isEmpty()) - { - DEBUG_LOG(("Bailing because of li->address.isEmpty()\n")); - delete li; - return; - } - - if (!li->port) - { - DEBUG_LOG(("Bailing because of !li->port\n")); - delete li; - return; - } - - if (li->validMaps.size() == 0) - { - DEBUG_LOG(("Bailing because of li->validMaps.size() == 0\n")); - delete li; - return; - } - - li->index = index; - - // ladders are QM-only at this point, which kinda invalidates the whole concept of local ladders. Oh well. - li->validQM = FALSE; // no local ladders in QM - li->validCustom = FALSE; - - //for (Int i=0; i<4; ++i) - // fname.removeLastChar(); // remove .lad - //li->name = UnicodeString(MultiByteToWideCharSingleLine(fname.reverseFind('\\')+1).c_str()); - - DEBUG_LOG(("Adding local ladder %ls\n", li->name.str())); - m_localLadders.push_back(li); -} diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/LobbyUtils.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/LobbyUtils.cpp deleted file mode 100644 index 1c54e1ac6c1..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/LobbyUtils.cpp +++ /dev/null @@ -1,859 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: LobbyUtils.cpp -// Author: Matthew D. Campbell, Sept 2002 -// Description: GameSpy lobby utils -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "Common/MultiplayerSettings.h" -#include "Common/PlayerTemplate.h" -#include "Common/Version.h" -#include "GameClient/AnimateWindowManager.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/Image.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetComboBox.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/GameText.h" -#include "GameClient/MapUtil.h" -#include "GameClient/MessageBox.h" -#include "GameClient/Mouse.h" -#include "GameNetwork/GameSpyOverlay.h" - -#include "GameClient/LanguageFilter.h" -#include "GameNetwork/GameSpy/BuddyDefs.h" -#include "GameNetwork/GameSpy/LadderDefs.h" -#include "GameNetwork/GameSpy/LobbyUtils.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PersistentStorageDefs.h" -#include "GameNetwork/GameSpy/GSConfig.h" - -#include "Common/STLTypedefs.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -static enum { - COLUMN_NAME = 0, - COLUMN_MAP, - COLUMN_LADDER, - COLUMN_NUMPLAYERS, - COLUMN_PASSWORD, - COLUMN_OBSERVER, - COLUMN_PING, -}; - -static NameKeyType buttonSortAlphaID = NAMEKEY_INVALID; -static NameKeyType buttonSortPingID = NAMEKEY_INVALID; -static NameKeyType buttonSortBuddiesID = NAMEKEY_INVALID; -static NameKeyType windowSortAlphaID = NAMEKEY_INVALID; -static NameKeyType windowSortPingID = NAMEKEY_INVALID; -static NameKeyType windowSortBuddiesID = NAMEKEY_INVALID; - -static GameWindow *buttonSortAlpha = NULL; -static GameWindow *buttonSortPing = NULL; -static GameWindow *buttonSortBuddies = NULL; -static GameWindow *windowSortAlpha = NULL; -static GameWindow *windowSortPing = NULL; -static GameWindow *windowSortBuddies = NULL; - -static GameSortType theGameSortType = GAMESORT_ALPHA_ASCENDING; -static Bool sortBuddies = TRUE; -static void showSortIcons(void) -{ - if (windowSortAlpha && windowSortPing) - { - switch(theGameSortType) - { - case GAMESORT_ALPHA_ASCENDING: - windowSortAlpha->winHide(FALSE); - windowSortAlpha->winEnable(TRUE); - windowSortPing->winHide(TRUE); - break; - case GAMESORT_ALPHA_DESCENDING: - windowSortAlpha->winHide(FALSE); - windowSortAlpha->winEnable(FALSE); - windowSortPing->winHide(TRUE); - break; - case GAMESORT_PING_ASCENDING: - windowSortPing->winHide(FALSE); - windowSortPing->winEnable(TRUE); - windowSortAlpha->winHide(TRUE); - break; - case GAMESORT_PING_DESCENDING: - windowSortPing->winHide(FALSE); - windowSortPing->winEnable(FALSE); - windowSortAlpha->winHide(TRUE); - break; - } - } - - if (sortBuddies) - { - if (windowSortBuddies) - { - windowSortBuddies->winHide(FALSE); - } - } - else - { - if (windowSortBuddies) - { - windowSortBuddies->winHide(TRUE); - } - } -} -void setSortMode( GameSortType sortType ) { theGameSortType = sortType; showSortIcons(); RefreshGameListBoxes(); } -void sortByBuddies( Bool doSort ) { sortBuddies = doSort; showSortIcons(); RefreshGameListBoxes(); } - -Bool HandleSortButton( NameKeyType sortButton ) -{ - if (sortButton == buttonSortBuddiesID) - { - sortByBuddies( !sortBuddies ); - return TRUE; - } - else if (sortButton == buttonSortAlphaID) - { - if (theGameSortType == GAMESORT_ALPHA_ASCENDING) - { - setSortMode(GAMESORT_ALPHA_DESCENDING); - } - else - { - setSortMode(GAMESORT_ALPHA_ASCENDING); - } - return TRUE; - } - else if (sortButton == buttonSortPingID) - { - if (theGameSortType == GAMESORT_PING_ASCENDING) - { - setSortMode(GAMESORT_PING_DESCENDING); - } - else - { - setSortMode(GAMESORT_PING_ASCENDING); - } - return TRUE; - } - return FALSE; -} - -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentID = NAMEKEY_INVALID; -//static NameKeyType parentGameListSmallID = NAMEKEY_INVALID; -static NameKeyType parentGameListLargeID = NAMEKEY_INVALID; -static NameKeyType listboxLobbyGamesSmallID = NAMEKEY_INVALID; -static NameKeyType listboxLobbyGamesLargeID = NAMEKEY_INVALID; -//static NameKeyType listboxLobbyGameInfoID = NAMEKEY_INVALID; - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parent = NULL; -//static GameWindow *parentGameListSmall = NULL; -static GameWindow *parentGameListLarge = NULL; - //GameWindow *listboxLobbyGamesSmall = NULL; - GameWindow *listboxLobbyGamesLarge = NULL; - //GameWindow *listboxLobbyGameInfo = NULL; - -static const Image *pingImages[3] = { NULL, NULL, NULL }; - -static void gameTooltip(GameWindow *window, - WinInstanceData *instData, - UnsignedInt mouse) -{ - Int x, y, row, col; - x = LOLONGTOSHORT(mouse); - y = HILONGTOSHORT(mouse); - - GadgetListBoxGetEntryBasedOnXY(window, x, y, row, col); - - if (row == -1 || col == -1) - { - TheMouse->setCursorTooltip( UnicodeString::TheEmptyString);//TheGameText->fetch("TOOLTIP:GamesBeingFormed") ); - return; - } - - Int gameID = (Int)GadgetListBoxGetItemData(window, row, 0); - GameSpyStagingRoom *room = TheGameSpyInfo->findStagingRoomByID(gameID); - if (!room) - { - TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:UnknownGame") ); - return; - } - - if (col == COLUMN_PING) - { -#ifdef DEBUG_LOGGING - UnicodeString s; - s.format(L"Ping is %d ms (cutoffs are %d ms and %d ms\n%hs local pings\n%hs remote pings", - room->getPingAsInt(), TheGameSpyConfig->getPingCutoffGood(), TheGameSpyConfig->getPingCutoffBad(), - TheGameSpyInfo->getPingString().str(), room->getPingString().str() - ); - TheMouse->setCursorTooltip( s, 10, NULL, 2.0f ); // the text and width are the only params used. the others are the default values. -#else - TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:PingInfo"), 10, NULL, 2.0f ); // the text and width are the only params used. the others are the default values. -#endif - return; - } - if (col == COLUMN_NUMPLAYERS) - { - TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:NumberOfPlayers"), 10, NULL, 2.0f ); // the text and width are the only params used. the others are the default values. - return; - } - if (col == COLUMN_PASSWORD) - { - if (room->getHasPassword()) - { - UnicodeString checkTooltip =TheGameText->fetch("TOOTIP:Password"); - if(!checkTooltip.compare(L"Password required to joing game")) - checkTooltip.set(L"Password required to join game"); - TheMouse->setCursorTooltip( checkTooltip, 10, NULL, 2.0f ); // the text and width are the only params used. the others are the default values. - } - else - TheMouse->setCursorTooltip( UnicodeString::TheEmptyString ); - return; - } - - UnicodeString tooltip; - - UnicodeString mapName; - const MapMetaData *md = TheMapCache->findMap(room->getMap()); - if (md) - { - mapName = md->m_displayName; - } - else - { - const char *start = room->getMap().reverseFind('\\'); - if (start) - { - ++start; - } - else - { - start = room->getMap().str(); - } - mapName.translate( start ); - } - UnicodeString tmp; - tooltip.format(TheGameText->fetch("TOOLTIP:GameInfoGameName"), room->getGameName().str()); - if (room->getLadderPort() != 0) - { - const LadderInfo *linfo = TheLadderList->findLadder(room->getLadderIP(), room->getLadderPort()); - if (linfo) - { - tmp.format(TheGameText->fetch("TOOLTIP:GameInfoLadderName"), linfo->name.str()); - tooltip.concat(tmp); - } - } - if (room->getExeCRC() != TheGlobalData->m_exeCRC || room->getIniCRC() != TheGlobalData->m_iniCRC) - { - tmp.format(TheGameText->fetch("TOOLTIP:InvalidGameVersion"), mapName.str()); - tooltip.concat(tmp); - } - tmp.format(TheGameText->fetch("TOOLTIP:GameInfoMap"), mapName.str()); - tooltip.concat(tmp); - - AsciiString aPlayer; - UnicodeString player; - Int numPlayers = 0; - for (Int i=0; igetGameSpySlot(i); - if (i == 0 && (!slot || !slot->isHuman())) - { - DEBUG_CRASH(("About to tooltip a non-hosted game!\n")); - } - if (slot && slot->isHuman()) - { - tmp.format(TheGameText->fetch("TOOLTIP:GameInfoPlayer"), slot->getName().str(), slot->getWins(), slot->getLosses()); - tooltip.concat(tmp); - ++numPlayers; - } - else if (slot && slot->isAI()) - { - ++numPlayers; - switch(slot->getState()) - { - case SLOT_EASY_AI: - tooltip.concat(L'\n'); - tooltip.concat(TheGameText->fetch("GUI:EasyAI")); - break; - case SLOT_MED_AI: - tooltip.concat(L'\n'); - tooltip.concat(TheGameText->fetch("GUI:MediumAI")); - break; - case SLOT_BRUTAL_AI: - tooltip.concat(L'\n'); - tooltip.concat(TheGameText->fetch("GUI:HardAI")); - break; - } - } - } - DEBUG_ASSERTCRASH(numPlayers, ("Tooltipping a 0-player game!\n")); - - TheMouse->setCursorTooltip( tooltip, 10, NULL, 2.0f ); // the text and width are the only params used. the others are the default values. -} - -static Bool isSmall = TRUE; - -GameWindow *GetGameListBox( void ) -{ - return listboxLobbyGamesLarge; -} - -GameWindow *GetGameInfoListBox( void ) -{ - return NULL; -} - -NameKeyType GetGameListBoxID( void ) -{ - return listboxLobbyGamesLargeID; -} - -NameKeyType GetGameInfoListBoxID( void ) -{ - return NAMEKEY_INVALID; -} - -void GrabWindowInfo( void ) -{ - isSmall = TRUE; - parentID = NAMEKEY( "WOLCustomLobby.wnd:WOLLobbyMenuParent" ); - parent = TheWindowManager->winGetWindowFromId(NULL, parentID); - - pingImages[0] = TheMappedImageCollection->findImageByName("Ping03"); - pingImages[1] = TheMappedImageCollection->findImageByName("Ping02"); - pingImages[2] = TheMappedImageCollection->findImageByName("Ping01"); - DEBUG_ASSERTCRASH(pingImages[0], ("Can't find ping image!")); - DEBUG_ASSERTCRASH(pingImages[1], ("Can't find ping image!")); - DEBUG_ASSERTCRASH(pingImages[2], ("Can't find ping image!")); - -// parentGameListSmallID = NAMEKEY( "WOLCustomLobby.wnd:ParentGameListSmall" ); -// parentGameListSmall = TheWindowManager->winGetWindowFromId(NULL, parentGameListSmallID); - - parentGameListLargeID = NAMEKEY( "WOLCustomLobby.wnd:ParentGameListLarge" ); - parentGameListLarge = TheWindowManager->winGetWindowFromId(NULL, parentGameListLargeID); - - listboxLobbyGamesSmallID = NAMEKEY( "WOLCustomLobby.wnd:ListboxGames" ); -// listboxLobbyGamesSmall = TheWindowManager->winGetWindowFromId(NULL, listboxLobbyGamesSmallID); -// listboxLobbyGamesSmall->winSetTooltipFunc(gameTooltip); - - listboxLobbyGamesLargeID = NAMEKEY( "WOLCustomLobby.wnd:ListboxGamesLarge" ); - listboxLobbyGamesLarge = TheWindowManager->winGetWindowFromId(NULL, listboxLobbyGamesLargeID); - listboxLobbyGamesLarge->winSetTooltipFunc(gameTooltip); -// -// listboxLobbyGameInfoID = NAMEKEY( "WOLCustomLobby.wnd:ListboxGameInfo" ); -// listboxLobbyGameInfo = TheWindowManager->winGetWindowFromId(NULL, listboxLobbyGameInfoID); - - buttonSortAlphaID = NAMEKEY("WOLCustomLobby.wnd:ButtonSortAlpha"); - buttonSortPingID = NAMEKEY("WOLCustomLobby.wnd:ButtonSortPing"); - buttonSortBuddiesID = NAMEKEY("WOLCustomLobby.wnd:ButtonSortBuddies"); - windowSortAlphaID = NAMEKEY("WOLCustomLobby.wnd:WindowSortAlpha"); - windowSortPingID = NAMEKEY("WOLCustomLobby.wnd:WindowSortPing"); - windowSortBuddiesID = NAMEKEY("WOLCustomLobby.wnd:WindowSortBuddies"); - - buttonSortAlpha = TheWindowManager->winGetWindowFromId(parent, buttonSortAlphaID); - buttonSortPing = TheWindowManager->winGetWindowFromId(parent, buttonSortPingID); - buttonSortBuddies = TheWindowManager->winGetWindowFromId(parent, buttonSortBuddiesID); - windowSortAlpha = TheWindowManager->winGetWindowFromId(parent, windowSortAlphaID); - windowSortPing = TheWindowManager->winGetWindowFromId(parent, windowSortPingID); - windowSortBuddies = TheWindowManager->winGetWindowFromId(parent, windowSortBuddiesID); - - showSortIcons(); -} - -void ReleaseWindowInfo( void ) -{ - isSmall = TRUE; - parent = NULL; -// parentGameListSmall = NULL; - parentGameListLarge = NULL; -// listboxLobbyGamesSmall = NULL; - listboxLobbyGamesLarge = NULL; -// listboxLobbyGameInfo = NULL; - - buttonSortAlpha = NULL; - buttonSortPing = NULL; - buttonSortBuddies = NULL; - windowSortAlpha = NULL; - windowSortPing = NULL; - windowSortBuddies = NULL; -} - -typedef std::set BuddyGameSet; -static BuddyGameSet *theBuddyGames = NULL; -static void populateBuddyGames(void) -{ - BuddyInfoMap *m = TheGameSpyInfo->getBuddyMap(); - theBuddyGames = NEW BuddyGameSet; - if (!m) - { - return; - } - for (BuddyInfoMap::const_iterator bit = m->begin(); bit != m->end(); ++bit) - { - BuddyInfo info = bit->second; - if (info.m_status == GP_STAGING) - { - StagingRoomMap *srm = TheGameSpyInfo->getStagingRoomList(); - for (StagingRoomMap::iterator srmIt = srm->begin(); srmIt != srm->end(); ++srmIt) - { - GameSpyStagingRoom *game = srmIt->second; - game->cleanUpSlotPointers(); - const GameSpyGameSlot *slot = game->getGameSpySlot(0); - if (slot && slot->getName() == info.m_locationString) - { - theBuddyGames->insert(game); - break; - } - } - } - } -} - -static void clearBuddyGames(void) -{ - if (theBuddyGames) - delete theBuddyGames; - theBuddyGames = NULL; -} - -struct GameSortStruct -{ - bool operator()(GameSpyStagingRoom *g1, GameSpyStagingRoom *g2) - { - // sort CRC mismatches to the bottom - Bool g1Good = (g1->getExeCRC() != TheGlobalData->m_exeCRC || g1->getIniCRC() != TheGlobalData->m_iniCRC); - Bool g2Good = (g1->getExeCRC() != TheGlobalData->m_exeCRC || g1->getIniCRC() != TheGlobalData->m_iniCRC); - if ( g1Good ^ g2Good ) - { - return g1Good; - } - - // sort games with private ladders to the bottom - Bool g1UnknownLadder = (g1->getLadderPort() && TheLadderList->findLadder(g1->getLadderIP(), g1->getLadderPort()) == NULL); - Bool g2UnknownLadder = (g2->getLadderPort() && TheLadderList->findLadder(g2->getLadderIP(), g2->getLadderPort()) == NULL); - if ( g1UnknownLadder ^ g2UnknownLadder ) - { - return g2UnknownLadder; - } - - // sort full games to the bottom - Bool g1Full = (g1->getNumNonObserverPlayers() == g1->getMaxPlayers() || g1->getNumPlayers() == MAX_SLOTS); - Bool g2Full = (g2->getNumNonObserverPlayers() == g2->getMaxPlayers() || g2->getNumPlayers() == MAX_SLOTS); - if ( g1Full ^ g2Full ) - { - return g2Full; - } - - if (sortBuddies) - { - Bool g1HasBuddies = (theBuddyGames->find(g1) != theBuddyGames->end()); - Bool g2HasBuddies = (theBuddyGames->find(g2) != theBuddyGames->end()); - if ( g1HasBuddies ^ g2HasBuddies ) - { - return g1HasBuddies; - } - } - - switch(theGameSortType) - { - case GAMESORT_ALPHA_ASCENDING: - return wcsicmp(g1->getGameName().str(), g2->getGameName().str()) < 0; - break; - case GAMESORT_ALPHA_DESCENDING: - return wcsicmp(g1->getGameName().str(),g2->getGameName().str()) > 0; - break; - case GAMESORT_PING_ASCENDING: - return g1->getPingAsInt() < g2->getPingAsInt(); - break; - case GAMESORT_PING_DESCENDING: - return g1->getPingAsInt() > g2->getPingAsInt(); - break; - } - return false; - } -}; - -static Int insertGame( GameWindow *win, GameSpyStagingRoom *game, Bool showMap ) -{ - game->cleanUpSlotPointers(); - Color gameColor = GameSpyColor[GSCOLOR_GAME]; - if (game->getNumNonObserverPlayers() == game->getMaxPlayers() || game->getNumPlayers() == MAX_SLOTS) - { - gameColor = GameSpyColor[GSCOLOR_GAME_FULL]; - } - if (game->getExeCRC() != TheGlobalData->m_exeCRC || game->getIniCRC() != TheGlobalData->m_iniCRC) - { - gameColor = GameSpyColor[GSCOLOR_GAME_CRCMISMATCH]; - } - UnicodeString gameName = game->getGameName(); - - if(TheGameSpyInfo->getDisallowAsianText()) - { - const WideChar *buff = gameName.str(); - Int length = gameName.getLength(); - for(Int i = 0; i < length; ++i) - { - if(buff[i] >= 256) - return -1; - } - } - else if(TheGameSpyInfo->getDisallowNonAsianText()) - { - const WideChar *buff = gameName.str(); - Int length = gameName.getLength(); - Bool hasUnicode = FALSE; - for(Int i = 0; i < length; ++i) - { - if(buff[i] >= 256) - { - hasUnicode = TRUE; - break; - } - } - if(!hasUnicode) - return -1; - } - - - - Int index = GadgetListBoxAddEntryText(win, game->getGameName(), gameColor, -1, COLUMN_NAME); - GadgetListBoxSetItemData(win, (void *)game->getID(), index); - - UnicodeString s; - - if (showMap) - { - UnicodeString mapName; - const MapMetaData *md = TheMapCache->findMap(game->getMap()); - if (md) - { - mapName = md->m_displayName; - } - else - { - const char *start = game->getMap().reverseFind('\\'); - if (start) - { - ++start; - } - else - { - start = game->getMap().str(); - } - mapName.translate( start ); - } - GadgetListBoxAddEntryText(win, mapName, gameColor, index, COLUMN_MAP); - - const LadderInfo * li = TheLadderList->findLadder(game->getLadderIP(), game->getLadderPort()); - if (li) - { - GadgetListBoxAddEntryText(win, li->name, gameColor, index, COLUMN_LADDER); - } - else if (game->getLadderPort()) - { - GadgetListBoxAddEntryText(win, TheGameText->fetch("GUI:UnknownLadder"), gameColor, index, COLUMN_LADDER); - } - else - { - GadgetListBoxAddEntryText(win, TheGameText->fetch("GUI:NoLadder"), gameColor, index, COLUMN_LADDER); - } - } - else - { - GadgetListBoxAddEntryText(win, UnicodeString(L" "), gameColor, index, COLUMN_MAP); - GadgetListBoxAddEntryText(win, UnicodeString(L" "), gameColor, index, COLUMN_LADDER); - } - - s.format(L"%d/%d", game->getReportedNumPlayers(), game->getReportedMaxPlayers()); - GadgetListBoxAddEntryText(win, s, gameColor, index, COLUMN_NUMPLAYERS); - - if (game->getHasPassword()) - { - const Image *img = TheMappedImageCollection->findImageByName("Password"); - Int width = 10, height = 10; - if (img) - { - width = img->getImageWidth(); - height = img->getImageHeight(); - } - GadgetListBoxAddEntryImage(win, img, index, COLUMN_PASSWORD, width, height); - } - else - { - GadgetListBoxAddEntryText(win, UnicodeString(L" "), gameColor, index, COLUMN_PASSWORD); - } - - if (game->getAllowObservers()) - { - const Image *img = TheMappedImageCollection->findImageByName("Observer"); - GadgetListBoxAddEntryImage(win, img, index, COLUMN_OBSERVER); - } - else - { - GadgetListBoxAddEntryText(win, UnicodeString(L" "), gameColor, index, COLUMN_OBSERVER); - } - - s.format(L"%d", game->getPingAsInt()); - GadgetListBoxAddEntryText(win, s, gameColor, index, COLUMN_PING); - Int ping = game->getPingAsInt(); - Int width = 10, height = 10; - if (pingImages[0]) - { - width = pingImages[0]->getImageWidth(); - height = pingImages[0]->getImageHeight(); - } - // CLH picking an arbitrary number for our ping display - if (ping < TheGameSpyConfig->getPingCutoffGood()) - { - GadgetListBoxAddEntryImage(win, pingImages[0], index, COLUMN_PING, width, height); - } - else if (ping < TheGameSpyConfig->getPingCutoffBad()) - { - GadgetListBoxAddEntryImage(win, pingImages[1], index, COLUMN_PING, width, height); - } - else - { - GadgetListBoxAddEntryImage(win, pingImages[2], index, COLUMN_PING, width, height); - } - - return index; -} - -void RefreshGameListBox( GameWindow *win, Bool showMap ) -{ - if (!win) - return; - - // save off selection - Int selectedIndex = -1; - Int indexToSelect = -1; - Int selectedID = 0; - GadgetListBoxGetSelected(win, &selectedIndex); - if (selectedIndex != -1 ) - { - selectedID = (Int)GadgetListBoxGetItemData(win, selectedIndex); - } - int prevPos = GadgetListBoxGetTopVisibleEntry( win ); - - // empty listbox - GadgetListBoxReset(win); - - // sort our games - typedef std::multiset SortedGameList; - SortedGameList sgl; - StagingRoomMap *srm = TheGameSpyInfo->getStagingRoomList(); - populateBuddyGames(); - for (StagingRoomMap::iterator srmIt = srm->begin(); srmIt != srm->end(); ++srmIt) - { - sgl.insert(srmIt->second); - } - - // populate listbox - for (SortedGameList::iterator sglIt = sgl.begin(); sglIt != sgl.end(); ++sglIt) - { - GameSpyStagingRoom *game = *sglIt; - if (game) - { - Int index = insertGame(win, game, showMap); - if (game->getID() == selectedID) - { - indexToSelect = index; - } - } - } - - clearBuddyGames(); - - // restore selection - GadgetListBoxSetSelected(win, indexToSelect); // even for -1, so we can disable the 'Join Game' button -// if(prevPos > 10) - GadgetListBoxSetTopVisibleEntry( win, prevPos );//+ 1 - - if (indexToSelect < 0 && selectedID) - { - TheWindowManager->winSetLoneWindow(NULL); - } -} - -void RefreshGameInfoListBox( GameWindow *mainWin, GameWindow *win ) -{ -// if (!mainWin || !win) -// return; -// -// GadgetListBoxReset(win); -// -// Int selected = -1; -// GadgetListBoxGetSelected(mainWin, &selected); -// if (selected < 0) -// { -// return; -// } -// -// Int selectedID = (Int)GadgetListBoxGetItemData(mainWin, selected); -// if (selectedID < 0) -// { -// return; -// } -// -// StagingRoomMap *srm = TheGameSpyInfo->getStagingRoomList(); -// StagingRoomMap::iterator srmIt = srm->find(selectedID); -// if (srmIt != srm->end()) -// { -// GameSpyStagingRoom *theRoom = srmIt->second; -// theRoom->cleanUpSlotPointers(); -// -// // game name -//// GadgetListBoxAddEntryText(listboxLobbyGameInfo, theRoom->getGameName(), GameSpyColor[GSCOLOR_DEFAULT], -1); -// -// const LadderInfo * li = TheLadderList->findLadder(theRoom->getLadderIP(), theRoom->getLadderPort()); -// if (li) -// { -// UnicodeString tmp; -// tmp.format(TheGameText->fetch("TOOLTIP:LadderName"), li->name.str()); -// GadgetListBoxAddEntryText(listboxLobbyGameInfo, tmp, GameSpyColor[GSCOLOR_DEFAULT], -1); -// } -// else if (theRoom->getLadderPort()) -// { -// GadgetListBoxAddEntryText(listboxLobbyGameInfo, TheGameText->fetch("TOOLTIP:UnknownLadder"), GameSpyColor[GSCOLOR_DEFAULT], -1); -// } -// else -// { -// GadgetListBoxAddEntryText(listboxLobbyGameInfo, TheGameText->fetch("TOOLTIP:NoLadder"), GameSpyColor[GSCOLOR_DEFAULT], -1); -// } -// -// if (theRoom->getExeCRC() != TheGlobalData->m_exeCRC || theRoom->getIniCRC() != TheGlobalData->m_iniCRC) -// { -// GadgetListBoxAddEntryText(listboxLobbyGameInfo, TheGameText->fetch("TOOLTIP:InvalidGameVersionSingleLine"), GameSpyColor[GSCOLOR_DEFAULT], -1); -// } -// -// // map name -// UnicodeString mapName; -// const MapMetaData *md = TheMapCache->findMap(theRoom->getMap()); -// if (md) -// { -// mapName = md->m_displayName; -// } -// else -// { -// const char *start = theRoom->getMap().reverseFind('\\'); -// if (start) -// { -// ++start; -// } -// else -// { -// start = theRoom->getMap().str(); -// } -// mapName.translate( start ); -// } -// -// GadgetListBoxAddEntryText(listboxLobbyGameInfo, mapName, GameSpyColor[GSCOLOR_DEFAULT], -1); -// -// // player list (rank, win/loss, side) -// for (Int i=0; igetGameSpySlot(i); -// if (slot && slot->isHuman()) -// { -// UnicodeString theName, theRating, thePlayerTemplate; -// Int colorIdx = slot->getColor(); -// theName = slot->getName(); -// theRating.format(L" (%d-%d)", slot->getWins(), slot->getLosses()); -// const PlayerTemplate * pt = ThePlayerTemplateStore->getNthPlayerTemplate(slot->getPlayerTemplate()); -// if (pt) -// { -// thePlayerTemplate = pt->getDisplayName(); -// } -// else -// { -// thePlayerTemplate = TheGameText->fetch("GUI:Random"); -// } -// -// UnicodeString theText; -// theText.format(L"%ls - %ls - %ls", theName.str(), thePlayerTemplate.str(), theRating.str()); -// -// Int theColor = GameSpyColor[GSCOLOR_DEFAULT]; -// const MultiplayerColorDefinition *mcd = TheMultiplayerSettings->getColor(colorIdx); -// if (mcd) -// { -// theColor = mcd->getColor(); -// } -// -// GadgetListBoxAddEntryText(listboxLobbyGameInfo, theText, theColor, -1); -// } -// } -// } - -} - -void RefreshGameListBoxes( void ) -{ - GameWindow *main = GetGameListBox(); - GameWindow *info = GetGameInfoListBox(); - - RefreshGameListBox( main, (info == NULL) ); - - if (info) - { - RefreshGameInfoListBox( main, info ); - } -} - -void ToggleGameListType( void ) -{ - isSmall = !isSmall; - if(isSmall) - { - parentGameListLarge->winHide(TRUE); -// parentGameListSmall->winHide(FALSE); - } - else - { - parentGameListLarge->winHide(FALSE); -// parentGameListSmall->winHide(TRUE); - } - - RefreshGameListBoxes(); -} - diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/MainMenuUtils.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/MainMenuUtils.cpp deleted file mode 100644 index 27dc0d0a2b8..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/MainMenuUtils.cpp +++ /dev/null @@ -1,895 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: MainMenuUtils.cpp -// Author: Matthew D. Campbell, Sept 2002 -// Description: GameSpy version check, patch download, etc utils -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include - -//#include "Common/Registry.h" -#include "Common/UserPreferences.h" -#include "Common/Version.h" -#include "GameClient/GameText.h" -#include "GameClient/MessageBox.h" -#include "GameClient/Shell.h" -#include "GameLogic/ScriptEngine.h" - -#include "GameClient/ShellHooks.h" - -#include "GameSpy/ghttp/ghttp.h" - -#include "GameNetwork/DownloadManager.h" -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/MainMenuUtils.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" - -#include "WWDownload/Registry.h" -#include "WWDownload/URLBuilder.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -/////////////////////////////////////////////////////////////////////////////////////// - -static Bool checkingForPatchBeforeGameSpy = FALSE; -static Int checksLeftBeforeOnline = 0; -static Int timeThroughOnline = 0; // used to avoid having old callbacks cause problems -static Bool mustDownloadPatch = FALSE; -static Bool cantConnectBeforeOnline = FALSE; -static std::list queuedDownloads; - -static char *MOTDBuffer = NULL; -static char *configBuffer = NULL; -GameWindow *onlineCancelWindow = NULL; - -static Bool s_asyncDNSThreadDone = TRUE; -static Bool s_asyncDNSThreadSucceeded = FALSE; -static Bool s_asyncDNSLookupInProgress = FALSE; -static HANDLE s_asyncDNSThreadHandle = NULL; -enum { - LOOKUP_INPROGRESS, - LOOKUP_FAILED, - LOOKUP_SUCCEEDED, -}; - -/////////////////////////////////////////////////////////////////////////////////////// - -static void startOnline( void ); -static void reallyStartPatchCheck( void ); - -/////////////////////////////////////////////////////////////////////////////////////// - -// someone has hit a button allowing downloads to start -void StartDownloadingPatches( void ) -{ - if (queuedDownloads.empty()) - { - HandleCanceledDownload(); - return; - } - - WindowLayout *layout; - layout = TheWindowManager->winCreateLayout( AsciiString( "Menus/DownloadMenu.wnd" ) ); - layout->runInit(); - layout->hide( FALSE ); - layout->bringForward(); - HandleCanceledDownload(FALSE); - DEBUG_ASSERTCRASH(TheDownloadManager, ("No download manager!")); - if (TheDownloadManager) - { - std::list::iterator it = queuedDownloads.begin(); - while (it != queuedDownloads.end()) - { - QueuedDownload q = *it; - TheDownloadManager->queueFileForDownload(q.server, q.userName, q.password, - q.file, q.localFile, q.regKey, q.tryResume); - queuedDownloads.pop_front(); - it = queuedDownloads.begin(); - } - TheDownloadManager->downloadNextQueuedFile(); - } -} - -/////////////////////////////////////////////////////////////////////////////////////// - -// user agrees to patch before going online -static void patchBeforeOnlineCallback( void ) -{ - StartDownloadingPatches(); -} - -// user doesn't want to patch before going online -static void noPatchBeforeOnlineCallback( void ) -{ - queuedDownloads.clear(); - if (mustDownloadPatch || cantConnectBeforeOnline) - { - // go back to normal - HandleCanceledDownload(); - } - else - { - // clear out unneeded downloads and go on - startOnline(); - } -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static Bool hasWriteAccess() -{ - const char* filename = "PatchAccessTest.txt"; - - remove(filename); - - int handle = _open( filename, _O_CREAT | _O_RDWR, _S_IREAD | _S_IWRITE); - if (handle == -1) - { - return false; - } - - _close(handle); - remove(filename); - - unsigned int val; - if (!GetUnsignedIntFromRegistry("", "Version", val)) - { - return false; - } - - if (!SetUnsignedIntInRegistry("", "Version", val)) - { - return false; - } - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static void startOnline( void ) -{ - checkingForPatchBeforeGameSpy = FALSE; - - DEBUG_ASSERTCRASH(checksLeftBeforeOnline==0, ("starting online with pending callbacks")); - if (onlineCancelWindow) - { - TheWindowManager->winDestroy(onlineCancelWindow); - onlineCancelWindow = NULL; - } - - if (cantConnectBeforeOnline) - { - MessageBoxOk(TheGameText->fetch("GUI:CannotConnectToServservTitle"), - TheGameText->fetch("GUI:CannotConnectToServserv"), - noPatchBeforeOnlineCallback); - return; - } - if (queuedDownloads.size()) - { - if (!hasWriteAccess()) - { - MessageBoxOk(TheGameText->fetch("GUI:Error"), - TheGameText->fetch("GUI:MustHaveAdminRights"), - noPatchBeforeOnlineCallback); - } - else if (mustDownloadPatch) - { - MessageBoxOkCancel(TheGameText->fetch("GUI:PatchAvailable"), - TheGameText->fetch("GUI:MustPatchForOnline"), - patchBeforeOnlineCallback, noPatchBeforeOnlineCallback); - } - else - { - MessageBoxYesNo(TheGameText->fetch("GUI:PatchAvailable"), - TheGameText->fetch("GUI:CanPatchForOnline"), - patchBeforeOnlineCallback, noPatchBeforeOnlineCallback); - } - return; - } - - TheScriptEngine->signalUIInteract(TheShellHookNames[SHELL_SCRIPT_HOOK_MAIN_MENU_ONLINE_SELECTED]); - - DEBUG_ASSERTCRASH( !TheGameSpyBuddyMessageQueue, ("TheGameSpyBuddyMessageQueue exists!") ); - DEBUG_ASSERTCRASH( !TheGameSpyPeerMessageQueue, ("TheGameSpyPeerMessageQueue exists!") ); - DEBUG_ASSERTCRASH( !TheGameSpyInfo, ("TheGameSpyInfo exists!") ); - SetUpGameSpy(MOTDBuffer, configBuffer); - if (MOTDBuffer) - { - delete[] MOTDBuffer; - MOTDBuffer = NULL; - } - if (configBuffer) - { - delete[] configBuffer; - configBuffer = NULL; - } - -#ifdef ALLOW_NON_PROFILED_LOGIN - UserPreferences pref; - pref.load("GameSpyLogin.ini"); - UserPreferences::const_iterator it = pref.find("useProfiles"); - if (it != pref.end() && it->second.compareNoCase("yes") == 0) -#endif ALLOW_NON_PROFILED_LOGIN - TheShell->push( AsciiString("Menus/GameSpyLoginProfile.wnd") ); -#ifdef ALLOW_NON_PROFILED_LOGIN - else - TheShell->push( AsciiString("Menus/GameSpyLoginQuick.wnd") ); -#endif ALLOW_NON_PROFILED_LOGIN -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static void queuePatch(Bool mandatory, AsciiString downloadURL) -{ - QueuedDownload q; - Bool success = TRUE; - - AsciiString connectionType; - success &= downloadURL.nextToken(&connectionType, ":"); - - AsciiString server; - success &= downloadURL.nextToken(&server, ":/"); - - AsciiString user; - success &= downloadURL.nextToken(&user, ":@"); - - AsciiString pass; - success &= downloadURL.nextToken(&pass, "@/"); - - AsciiString filePath; - success &= downloadURL.nextToken(&filePath, ""); - - if (!success && user.isNotEmpty()) - { - // no user/pass combo - move the file into it's proper place - filePath = user; - user = ""; // LFeenanEA - Credentials removed as per Security requirements - pass = ""; - success = TRUE; - } - - AsciiString fileStr = filePath; - const char *s = filePath.reverseFind('/'); - if (s) - fileStr = s+1; - AsciiString fileName = "patches\\"; - fileName.concat(fileStr); - - DEBUG_LOG(("download URL split: %d [%s] [%s] [%s] [%s] [%s] [%s]\n", - success, connectionType.str(), server.str(), user.str(), pass.str(), - filePath.str(), fileName.str())); - - if (!success) - return; - - q.file = filePath; - q.localFile = fileName; - q.password = pass; - q.regKey = ""; - q.server = server; - q.tryResume = TRUE; - q.userName = user; - - std::list::iterator it = queuedDownloads.begin(); - while (it != queuedDownloads.end()) - { - if (it->localFile == q.localFile) - return; // don't add it if it exists already (because we can check multiple times) - ++it; - } - - queuedDownloads.push_back(q); -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static GHTTPBool motdCallback( GHTTPRequest request, GHTTPResult result, - char * buffer, GHTTPByteCount bufferLen, void * param ) -{ - Int run = (Int)param; - if (run != timeThroughOnline) - { - DEBUG_CRASH(("Old callback being called!")); - return GHTTPTrue; - } - - if (MOTDBuffer) - { - delete[] MOTDBuffer; - MOTDBuffer = NULL; - } - - MOTDBuffer = NEW char[bufferLen]; - memcpy(MOTDBuffer, buffer, bufferLen); - MOTDBuffer[bufferLen-1] = 0; - - --checksLeftBeforeOnline; - DEBUG_ASSERTCRASH(checksLeftBeforeOnline>=0, ("Too many callbacks")); - if (onlineCancelWindow && !checksLeftBeforeOnline) - { - TheWindowManager->winDestroy(onlineCancelWindow); - onlineCancelWindow = NULL; - } - - DEBUG_LOG(("------- Got MOTD before going online -------\n")); - DEBUG_LOG(("%s\n", (MOTDBuffer)?MOTDBuffer:"")); - DEBUG_LOG(("--------------------------------------------\n")); - - if (!checksLeftBeforeOnline) - startOnline(); - - return GHTTPTrue; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static GHTTPBool configCallback( GHTTPRequest request, GHTTPResult result, - char * buffer, GHTTPByteCount bufferLen, void * param ) -{ - Int run = (Int)param; - if (run != timeThroughOnline) - { - DEBUG_CRASH(("Old callback being called!")); - return GHTTPTrue; - } - - if (configBuffer) - { - delete[] configBuffer; - configBuffer = NULL; - } - - if (result != GHTTPSuccess || bufferLen < 100) - { - if (!checkingForPatchBeforeGameSpy) - return GHTTPTrue; - --checksLeftBeforeOnline; - if (onlineCancelWindow && !checksLeftBeforeOnline) - { - TheWindowManager->winDestroy(onlineCancelWindow); - onlineCancelWindow = NULL; - } - cantConnectBeforeOnline = TRUE; - if (!checksLeftBeforeOnline) - { - startOnline(); - } - return GHTTPTrue; - } - - configBuffer = NEW char[bufferLen]; - memcpy(configBuffer, buffer, bufferLen); - configBuffer[bufferLen-1] = 0; - - AsciiString fname; - fname.format("%sGeneralsOnline\\Config.txt", TheGlobalData->getPath_UserData().str()); - FILE *fp = fopen(fname.str(), "wb"); - if (fp) - { - fwrite(configBuffer, bufferLen, 1, fp); - fclose(fp); - } - - --checksLeftBeforeOnline; - DEBUG_ASSERTCRASH(checksLeftBeforeOnline>=0, ("Too many callbacks")); - if (onlineCancelWindow && !checksLeftBeforeOnline) - { - TheWindowManager->winDestroy(onlineCancelWindow); - onlineCancelWindow = NULL; - } - - DEBUG_LOG(("Got Config before going online\n")); - - if (!checksLeftBeforeOnline) - startOnline(); - - return GHTTPTrue; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static GHTTPBool configHeadCallback( GHTTPRequest request, GHTTPResult result, - char * buffer, GHTTPByteCount bufferLen, void * param ) -{ - Int run = (Int)param; - if (run != timeThroughOnline) - { - DEBUG_CRASH(("Old callback being called!")); - return GHTTPTrue; - } - - DEBUG_LOG(("HTTP head resp: res=%d, len=%d, buf=[%s]\n", result, bufferLen, buffer)); - - if (result == GHTTPSuccess) - { - DEBUG_LOG(("Headers are [%s]\n", ghttpGetHeaders( request ))); - - AsciiString headers(ghttpGetHeaders( request )); - AsciiString line; - while (headers.nextToken(&line, "\n\r")) - { - AsciiString key, val; - line.nextToken(&key, ": "); - line.nextToken(&val, ": \r\n"); - - if (key.compare("Content-Length") == 0 && val.isNotEmpty()) - { - Int serverLen = atoi(val.str()); - Int fileLen = 0; - AsciiString fname; - fname.format("%sGeneralsOnline\\Config.txt", TheGlobalData->getPath_UserData().str()); - FILE *fp = fopen(fname.str(), "rb"); - if (fp) - { - fseek(fp, 0, SEEK_END); - fileLen = ftell(fp); - fclose(fp); - } - - if (serverLen == fileLen) - { - // we don't need to download the MOTD again - --checksLeftBeforeOnline; - DEBUG_ASSERTCRASH(checksLeftBeforeOnline>=0, ("Too many callbacks")); - if (onlineCancelWindow && !checksLeftBeforeOnline) - { - TheWindowManager->winDestroy(onlineCancelWindow); - onlineCancelWindow = NULL; - } - - if (configBuffer) - { - delete[] configBuffer; - configBuffer = NULL; - } - - AsciiString fname; - fname.format("%sGeneralsOnline\\Config.txt", TheGlobalData->getPath_UserData().str()); - FILE *fp = fopen(fname.str(), "rb"); - if (fp) - { - configBuffer = NEW char[fileLen]; - fread(configBuffer, fileLen, 1, fp); - configBuffer[fileLen-1] = 0; - fclose(fp); - - DEBUG_LOG(("Got Config before going online\n")); - - if (!checksLeftBeforeOnline) - startOnline(); - - return GHTTPTrue; - } - } - } - } - } - - // we need to download the MOTD again - std::string gameURL, mapURL; - std::string configURL, motdURL; - FormatURLFromRegistry(gameURL, mapURL, configURL, motdURL); - ghttpGet( configURL.c_str(), GHTTPFalse, configCallback, param ); - - return GHTTPTrue; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static GHTTPBool gamePatchCheckCallback( GHTTPRequest request, GHTTPResult result, char * buffer, GHTTPByteCount bufferLen, void * param ) -{ - Int run = (Int)param; - if (run != timeThroughOnline) - { - DEBUG_CRASH(("Old callback being called!")); - return GHTTPTrue; - } - - --checksLeftBeforeOnline; - DEBUG_ASSERTCRASH(checksLeftBeforeOnline>=0, ("Too many callbacks")); - - DEBUG_LOG(("Result=%d, buffer=[%s], len=%d\n", result, buffer, bufferLen)); - if (result != GHTTPSuccess) - { - if (!checkingForPatchBeforeGameSpy) - return GHTTPTrue; - cantConnectBeforeOnline = TRUE; - if (!checksLeftBeforeOnline) - { - startOnline(); - } - return GHTTPTrue; - } - - AsciiString message = buffer; - AsciiString line; - while (message.nextToken(&line, "\r\n")) - { - AsciiString type, req, url; - Bool ok = TRUE; - ok &= line.nextToken(&type, " "); - ok &= line.nextToken(&req, " "); - ok &= line.nextToken(&url, " "); - if (ok && type == "patch") - { - DEBUG_LOG(("Saw a patch: %d/[%s]\n", atoi(req.str()), url.str())); - queuePatch( atoi(req.str()), url ); - if (atoi(req.str())) - { - mustDownloadPatch = TRUE; - } - } - else if (ok && type == "server") - { - } - } - - if (!checksLeftBeforeOnline) - { - startOnline(); - } - - return GHTTPTrue; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -void CancelPatchCheckCallbackAndReopenDropdown( void ) -{ - HandleCanceledDownload(); - CancelPatchCheckCallback(); -} - -void CancelPatchCheckCallback( void ) -{ - s_asyncDNSLookupInProgress = FALSE; - HandleCanceledDownload(FALSE); // don't dropdown - checkingForPatchBeforeGameSpy = FALSE; - checksLeftBeforeOnline = 0; - if (onlineCancelWindow) - { - TheWindowManager->winDestroy(onlineCancelWindow); - onlineCancelWindow = NULL; - } - queuedDownloads.clear(); - if (MOTDBuffer) - { - delete[] MOTDBuffer; - MOTDBuffer = NULL; - } - if (configBuffer) - { - delete[] configBuffer; - configBuffer = NULL; - } -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static GHTTPBool overallStatsCallback( GHTTPRequest request, GHTTPResult result, char * buffer, GHTTPByteCount bufferLen, void * param ) -{ - DEBUG_LOG(("overallStatsCallback() - Result=%d, len=%d\n", result, bufferLen)); - if (result != GHTTPSuccess) - { - return GHTTPTrue; - } - - OverallStats USA, China, GLA; - AsciiString message = buffer; - - Int state = STATS_MAX; // STATS_MAX == none - AsciiString line; - OverallStats *stats = NULL; - while (message.nextToken(&line, "\n")) - { - line.trim(); - line.toLower(); - if (strstr(line.str(), "today")) - { - state = STATS_TODAY; - } - else if (strstr(line.str(), "yesterday")) - { - state = STATS_YESTERDAY; - } - else if (strstr(line.str(), "all time")) - { - state = STATS_ALLTIME; - } - else if (strstr(line.str(), "last week")) - { - state = STATS_LASTWEEK; - } - else if (state != STATS_MAX && strstr(line.str(), "usa")) - { - stats = &USA; - } - else if (state != STATS_MAX && strstr(line.str(), "china")) - { - stats = &China; - } - else if (state != STATS_MAX && strstr(line.str(), "gla")) - { - stats = &GLA; - } - - if (stats) - { - AsciiString totalLine, winsLine, lossesLine; - message.nextToken(&totalLine, "\n"); - message.nextToken(&winsLine, "\n"); - message.nextToken(&lossesLine, "\n"); - while (totalLine.isNotEmpty() && !isdigit(totalLine.getCharAt(0))) - { - totalLine = totalLine.str()+1; - } - while (winsLine.isNotEmpty() && !isdigit(winsLine.getCharAt(0))) - { - winsLine = winsLine.str()+1; - } - while (lossesLine.isNotEmpty() && !isdigit(lossesLine.getCharAt(0))) - { - lossesLine = lossesLine.str()+1; - } - if (totalLine.isNotEmpty() && winsLine.isNotEmpty() && lossesLine.isNotEmpty()) - { - stats->wins[state] = atoi(winsLine.str()); - stats->losses[state] = atoi(lossesLine.str()); - } - - stats = NULL; - } - } - - HandleOverallStats(USA, China, GLA); - - return GHTTPTrue; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static GHTTPBool numPlayersOnlineCallback( GHTTPRequest request, GHTTPResult result, char * buffer, GHTTPByteCount bufferLen, void * param ) -{ - DEBUG_LOG(("numPlayersOnlineCallback() - Result=%d, buffer=[%s], len=%d\n", result, buffer, bufferLen)); - if (result != GHTTPSuccess) - { - return GHTTPTrue; - } - - AsciiString message = buffer; - message.trim(); - const char *s = message.reverseFind('\\'); - if (!s) - { - return GHTTPTrue; - } - - if (*s == '\\') - ++s; - - DEBUG_LOG(("Message was '%s', trimmed to '%s'=%d\n", buffer, s, atoi(s))); - HandleNumPlayersOnline(atoi(s)); - - return GHTTPTrue; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -void CheckOverallStats( void ) -{ - ghttpGet("http://gamestats.gamespy.com/ccgenerals/display.html", - GHTTPFalse, overallStatsCallback, NULL); -} - -/////////////////////////////////////////////////////////////////////////////////////// - -void CheckNumPlayersOnline( void ) -{ - ghttpGet("http://launch.gamespyarcade.com/software/launch/arcadecount2.dll?svcname=ccgenerals", - GHTTPFalse, numPlayersOnlineCallback, NULL); -} - -/////////////////////////////////////////////////////////////////////////////////////// - -DWORD WINAPI asyncGethostbynameThreadFunc( void * szName ) -{ - HOSTENT *he = gethostbyname( (const char *)szName ); - - if (he) - { - s_asyncDNSThreadSucceeded = TRUE; - } - else - { - s_asyncDNSThreadSucceeded = FALSE; - } - - s_asyncDNSThreadDone = TRUE; - return 0; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -int asyncGethostbyname(char * szName) -{ - static int stat = 0; - static unsigned long threadid; - - if( stat == 0 ) - { - /* Kick off gethostname thread */ - s_asyncDNSThreadDone = FALSE; - s_asyncDNSThreadHandle = CreateThread( NULL, 0, asyncGethostbynameThreadFunc, szName, 0, &threadid ); - - if( s_asyncDNSThreadHandle == NULL ) - { - return( LOOKUP_FAILED ); - } - stat = 1; - } - if( stat == 1 ) - { - if( s_asyncDNSThreadDone ) - { - /* Thread finished */ - stat = 0; - s_asyncDNSLookupInProgress = FALSE; - s_asyncDNSThreadHandle = NULL; - return( (s_asyncDNSThreadSucceeded)?LOOKUP_SUCCEEDED:LOOKUP_FAILED ); - } - } - - return( LOOKUP_INPROGRESS ); -} - -/////////////////////////////////////////////////////////////////////////////////////// - -// GameSpy's HTTP SDK has had at least 1 crash bug, so we're going to just bail and -// never try again if they crash us. We won't be able to get back online again (we'll -// time out) but at least we'll live. -static Bool isHttpOk = TRUE; - -void HTTPThinkWrapper( void ) -{ - if (s_asyncDNSLookupInProgress) - { - Int ret = asyncGethostbyname("servserv.generals.ea.com"); - switch(ret) - { - case LOOKUP_FAILED: - cantConnectBeforeOnline = TRUE; - startOnline(); - break; - case LOOKUP_SUCCEEDED: - reallyStartPatchCheck(); - break; - } - } - - if (isHttpOk) - { - try - { - ghttpThink(); - } - catch (...) - { - isHttpOk = FALSE; // we can't abort the login, since we might be done with the - // required checks and are fetching extras. If it is a required - // check, we'll time out normally. - } - } -} - -/////////////////////////////////////////////////////////////////////////////////////// - -void StopAsyncDNSCheck( void ) -{ - if (s_asyncDNSThreadHandle) - { -#ifdef DEBUG_CRASHING - Int res = -#endif - TerminateThread(s_asyncDNSThreadHandle,0); - DEBUG_ASSERTCRASH(res, ("Could not terminate the Async DNS Lookup thread!")); // Thread still not killed! - } - s_asyncDNSThreadHandle = NULL; - s_asyncDNSLookupInProgress = FALSE; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -void StartPatchCheck( void ) -{ - checkingForPatchBeforeGameSpy = TRUE; - cantConnectBeforeOnline = FALSE; - timeThroughOnline++; - checksLeftBeforeOnline = 0; - - onlineCancelWindow = MessageBoxCancel(TheGameText->fetch("GUI:CheckingForPatches"), - TheGameText->fetch("GUI:CheckingForPatches"), CancelPatchCheckCallbackAndReopenDropdown); - - s_asyncDNSLookupInProgress = TRUE; - Int ret = asyncGethostbyname("servserv.generals.ea.com"); - switch(ret) - { - case LOOKUP_FAILED: - cantConnectBeforeOnline = TRUE; - startOnline(); - break; - case LOOKUP_SUCCEEDED: - reallyStartPatchCheck(); - break; - } -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static void reallyStartPatchCheck( void ) -{ - checksLeftBeforeOnline = 4; - - std::string gameURL, mapURL; - std::string configURL, motdURL; - - FormatURLFromRegistry(gameURL, mapURL, configURL, motdURL); - - std::string proxy; - if (GetStringFromRegistry("", "Proxy", proxy)) - { - if (!proxy.empty()) - { - ghttpSetProxy(proxy.c_str()); - } - } - - // check for a patch first - DEBUG_LOG(("Game patch check: [%s]\n", gameURL.c_str())); - DEBUG_LOG(("Map patch check: [%s]\n", mapURL.c_str())); - DEBUG_LOG(("Config: [%s]\n", configURL.c_str())); - DEBUG_LOG(("MOTD: [%s]\n", motdURL.c_str())); - ghttpGet(gameURL.c_str(), GHTTPFalse, gamePatchCheckCallback, (void *)timeThroughOnline); - ghttpGet(mapURL.c_str(), GHTTPFalse, gamePatchCheckCallback, (void *)timeThroughOnline); - ghttpHead(configURL.c_str(), GHTTPFalse, configHeadCallback, (void *)timeThroughOnline); - ghttpGet(motdURL.c_str(), GHTTPFalse, motdCallback, (void *)timeThroughOnline); - - // check total game stats - CheckOverallStats(); - - // check the users online - CheckNumPlayersOnline(); -} - -/////////////////////////////////////////////////////////////////////////////////////// diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/PeerDefs.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/PeerDefs.cpp deleted file mode 100644 index 9f930de2908..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/PeerDefs.cpp +++ /dev/null @@ -1,938 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -// FILE: PeerDefs.cpp ////////////////////////////////////////////////////// -// Generals GameSpy Peer (chat) definitions -// Author: Matthew D. Campbell, June 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine -#include - -#include "Common/GameState.h" -#include "Common/RandomValue.h" -#include "Common/IgnorePreferences.h" -#include "Common/CustomMatchPreferences.h" -#include "Common/GameSpyMiscPreferences.h" -#include "Common/Recorder.h" -#include "Common/Player.h" -#include "Common/PlayerList.h" -#include "Common/PlayerTemplate.h" -#include "GameClient/MapUtil.h" -#include "GameClient/ShellHooks.h" -#include "GameClient/GameText.h" -#include "GameNetwork/GameSpy/LadderDefs.h" -#include "GameNetwork/GameSpy/PeerDefsImplementation.h" -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PingThread.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpy/GSConfig.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameNetwork/RankPointValue.h" -#include "GameLogic/GameLogic.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -GameSpyInfoInterface *TheGameSpyInfo = NULL; -GameSpyStagingRoom *TheGameSpyGame = NULL; -void deleteNotificationBox( void ); - -bool AsciiComparator::operator()(AsciiString s1, AsciiString s2) const -{ - return stricmp(s1.str(), s2.str()) < 0; -} - -GameSpyInfo::GameSpyInfo() -{ - reset(); - TheGameSpyGame = &m_localStagingRoom; - m_isDisconAfterGameStart = FALSE; -} - -GameSpyInfo::~GameSpyInfo() -{ - TheGameSpyGame = NULL; - reset(); -} - -void GameSpyInfo::reset( void ) -{ - m_sawFullGameList = FALSE; - m_isDisconAfterGameStart = FALSE; - m_currentGroupRoomID = 0; - clearGroupRoomList(); - clearStagingRoomList(); - m_localStagingRoomID = 0; - m_buddyRequestMap.clear(); - m_buddyMap.clear(); - m_buddyMessages.clear(); - m_joinedStagingRoom = 0; - m_isHosting = false; - m_localStagingRoomID = 0; - m_localStagingRoom.reset(); - m_gotGroupRoomList = false; - m_localName = ""; - m_localProfileID = 0; - m_maxMessagesPerUpdate = 100; - - // Added By Sadullah Nader - // Initialization missing and needed - m_disallowAsainText = FALSE; - m_disallowNonAsianText = FALSE; - m_disconReason = 0; - m_localBaseName.clear(); - m_localEmail.clear(); - m_localPasswd.clear(); - m_pingString.clear(); - m_rawConfig.clear(); - m_rawMotd.clear(); - // - - m_internalIP = m_externalIP = 0; - - m_savedIgnoreMap.clear(); - m_preorderPlayers.clear(); - - m_cachedLocalPlayerStats.reset(); - - m_additionalDisconnects = -1; -} - -Bool GameSpyInfo::didPlayerPreorder( Int profileID ) const -{ - std::set::const_iterator it = m_preorderPlayers.find(profileID); - return (it != m_preorderPlayers.end()); -} - -void GameSpyInfo::markPlayerAsPreorder( Int profileID ) -{ - m_preorderPlayers.insert(profileID); -} - -void GameSpyInfo::setLocalIPs(UnsignedInt internalIP, UnsignedInt externalIP) -{ - m_internalIP = internalIP; - m_externalIP = externalIP; -} - -void GameSpyInfo::readAdditionalDisconnects( void ) -{ - m_additionalDisconnects = GetAdditionalDisconnectsFromUserFile(m_localProfileID); - DEBUG_LOG(("GameSpyInfo::readAdditionalDisconnects() found %d disconnects.\n", m_additionalDisconnects)); -} - -Int GameSpyInfo::getAdditionalDisconnects( void ) -{ - DEBUG_LOG(("GameSpyInfo::getAdditionalDisconnects() would have returned %d. Returning 0 instead.\n", m_additionalDisconnects)); - return 0; -} - -void GameSpyInfo::clearAdditionalDisconnects( void ) -{ - m_additionalDisconnects = 0; -} - -GameSpyInfoInterface* GameSpyInfoInterface::createNewGameSpyInfoInterface( void ) -{ - return NEW GameSpyInfo; -} - -Bool GameSpyInfo::amIHost( void ) -{ - return m_isHosting; -} - -GameSpyStagingRoom* GameSpyInfo::getCurrentStagingRoom( void ) -{ - if (m_isHosting || m_joinedStagingRoom) - return &m_localStagingRoom; - - StagingRoomMap::iterator it = m_stagingRooms.find(m_joinedStagingRoom); - if (it != m_stagingRooms.end()) - return it->second; - - return NULL; -} - -void GameSpyInfo::setGameOptions( void ) -{ - if (!m_isHosting) - return; - - // set options for game lists, and UTM players in-game - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_SETGAMEOPTIONS; - req.options = GameInfoToAsciiString(&m_localStagingRoom).str(); - - Int i; - AsciiString mapName = TheGameState->realMapPathToPortableMapPath(m_localStagingRoom.getMap()); - AsciiString newMapName; - for (i=0; ifindMap(mapName); - //if (!md) - //return; // there really isn't any need to send info like this... - - req.gameOptions.numPlayers = 0; - req.gameOptions.numObservers = 0; - Int numOpenSlots = 0; - AsciiString playerInfo = ""; - for (i=0; igetGameSpySlot(i); - req.gameOptsPlayerNames[i] = ""; - if (!slot->isOccupied()) - { - if (slot->isOpen()) - ++numOpenSlots; - } - else - { - AsciiString playerName; - if (slot->isHuman()) - { - playerName.translate(slot->getName()); - req.gameOptsPlayerNames[i] = playerName.str(); - PlayerInfoMap::iterator it = m_playerInfoMap.find(playerName); - if (it != m_playerInfoMap.end()) - { - wins = it->second.m_wins; - losses = it->second.m_losses; - profileID = it->second.m_profileID; - } - req.gameOptions.wins[req.gameOptions.numObservers+req.gameOptions.numPlayers] = wins; - req.gameOptions.losses[req.gameOptions.numObservers+req.gameOptions.numPlayers] = losses; - req.gameOptions.profileID[req.gameOptions.numObservers+req.gameOptions.numPlayers] = profileID; - req.gameOptions.faction[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getPlayerTemplate(); - req.gameOptions.color[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getColor(); - if (slot->getPlayerTemplate() == PLAYERTEMPLATE_OBSERVER) - { - ++req.gameOptions.numObservers; - } - else - { - ++req.gameOptions.numPlayers; - } - } - else if (slot->isAI()) - { - // add in AI players - switch (slot->getState()) - { - case SLOT_EASY_AI: - playerName = "CE"; - break; - case SLOT_MED_AI: - playerName = "CM"; - break; - case SLOT_BRUTAL_AI: - playerName = "CH"; - break; - } - req.gameOptsPlayerNames[i] = playerName.str(); // name is unused - we go off of the profileID - req.gameOptions.wins[req.gameOptions.numObservers+req.gameOptions.numPlayers] = 0; - req.gameOptions.losses[req.gameOptions.numObservers+req.gameOptions.numPlayers] = 0; - req.gameOptions.profileID[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getState(); - req.gameOptions.faction[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getPlayerTemplate(); - req.gameOptions.color[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getColor(); - ++req.gameOptions.numPlayers; - } - } - } - req.gameOptions.maxPlayers = numOpenSlots + req.gameOptions.numPlayers + req.gameOptions.numObservers; - TheGameSpyPeerMessageQueue->addRequest(req); - - req.peerRequestType = PeerRequest::PEERREQUEST_UTMROOM; - req.UTM.isStagingRoom = TRUE; - req.id = "Pings/"; - AsciiString pings; - for (i=0; igetGameSpySlot(i); - if (slot && slot->isHuman()) - { - pings.concat(slot->getPingString()); - } - else - { - pings.concat("0"); - } - } - req.options = pings.str(); - TheGameSpyPeerMessageQueue->addRequest(req); -} - -Bool GameSpyInfo::isBuddy( Int id ) -{ - return m_buddyMap.find(id) != m_buddyMap.end(); -} - -void GameSpyInfo::addGroupRoom( GameSpyGroupRoom room ) -{ - if (room.m_groupID == 0) - { - m_gotGroupRoomList = TRUE; - - GroupRoomMap::iterator iter; - - // figure out how many good strings we've got - std::vector names; - Int numRooms = 0; - for (iter = getGroupRoomList()->begin(); iter != getGroupRoomList()->end(); ++iter) - { - GameSpyGroupRoom room = iter->second; - if (room.m_groupID != TheGameSpyConfig->getQMChannel()) - { - ++numRooms; - - AsciiString groupLabel; - groupLabel.format("GUI:%s", room.m_name.str()); - - Bool exists = FALSE; - UnicodeString groupName = TheGameText->fetch(groupLabel, &exists); - if (exists) - { - names.push_back(groupName); - } - } - } - - if (!names.empty() && names.size() != numRooms) - { - // didn't get all names. fix up - Int nameIndex = 0; - Int timesThrough = 1; // start with USA Lobby 1 - for (iter = TheGameSpyInfo->getGroupRoomList()->begin(); iter != TheGameSpyInfo->getGroupRoomList()->end(); ++iter) - { - GameSpyGroupRoom room = iter->second; - if (room.m_groupID != TheGameSpyConfig->getQMChannel()) - { - room.m_translatedName.format(L"%ls %d", names[nameIndex].str(), timesThrough); - nameIndex = (nameIndex+1)%names.size(); - m_groupRooms[room.m_groupID] = room; - if (!nameIndex) - { - // we've looped through the name list already. increment the timesThrough counter - ++timesThrough; - } - } - } - } - } - else - { - DEBUG_LOG(("Adding group room %d (%s)\n", room.m_groupID, room.m_name.str())); - AsciiString groupLabel; - groupLabel.format("GUI:%s", room.m_name.str()); - room.m_translatedName = TheGameText->fetch(groupLabel); - m_groupRooms[room.m_groupID] = room; - if ( !stricmp("quickmatch", room.m_name.str()) ) - { - DEBUG_LOG(("Group room %d (%s) is the QuickMatch room\n", room.m_groupID, room.m_name.str())); - TheGameSpyConfig->setQMChannel(room.m_groupID); - } - } -} - -void GameSpyInfo::joinGroupRoom( Int groupID ) -{ - if (groupID > 0) - { - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_JOINGROUPROOM; - req.groupRoom.id = groupID; - TheGameSpyPeerMessageQueue->addRequest(req); - m_playerInfoMap.clear(); - } -} - -void GameSpyInfo::leaveGroupRoom( void ) -{ - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_LEAVEGROUPROOM; - TheGameSpyPeerMessageQueue->addRequest(req); - setCurrentGroupRoom(0); - m_playerInfoMap.clear(); -} - -void GameSpyInfo::joinBestGroupRoom( void ) -{ - if (m_currentGroupRoomID) - { - DEBUG_LOG(("Bailing from GameSpyInfo::joinBestGroupRoom() - we were already in a room\n")); - m_currentGroupRoomID = 0; - return; - } - - if (m_groupRooms.size()) - { - int minID = -1; - int minPlayers = 1000; - GroupRoomMap::iterator iter = m_groupRooms.begin(); - while (iter != m_groupRooms.end()) - { - GameSpyGroupRoom room = iter->second; - DEBUG_LOG(("Group room %d: %s (%d, %d, %d, %d)\n", room.m_groupID, room.m_name.str(), room.m_numWaiting, room.m_maxWaiting, - room.m_numGames, room.m_numPlaying)); - - if (TheGameSpyConfig->getQMChannel() != room.m_groupID && minPlayers > 25 && room.m_numWaiting < minPlayers) - { - minID = room.m_groupID; - minPlayers = room.m_numWaiting; - } - - ++iter; - } - - if (minID > 0) - { - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_JOINGROUPROOM; - req.groupRoom.id = minID; - TheGameSpyPeerMessageQueue->addRequest(req); - m_playerInfoMap.clear(); - } - else - { - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSGroupRoomJoinFail"), NULL); - } - } - else - { - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSGroupRoomJoinFail"), NULL); - } -} - -void GameSpyInfo::updatePlayerInfo( PlayerInfo pi, AsciiString oldNick ) -{ - if (!oldNick.isEmpty()) - playerLeftGroupRoom(oldNick); - - m_playerInfoMap[pi.m_name] = pi; - - if (pi.m_preorder != 0) - markPlayerAsPreorder(pi.m_profileID); -} - -void GameSpyInfo::playerLeftGroupRoom( AsciiString nick ) -{ - PlayerInfoMap::iterator it = m_playerInfoMap.find(nick); - if (it != m_playerInfoMap.end()) - { - m_playerInfoMap.erase(it); - } -} - -void GameSpyInfo::clearStagingRoomList( void ) -{ - Int numRoomsRemoved = 0; - m_sawFullGameList = FALSE; - m_stagingRoomsDirty = FALSE; - - StagingRoomMap::iterator it = m_stagingRooms.begin(); - while (it != m_stagingRooms.end()) - { - ++numRoomsRemoved; - - delete it->second; - m_stagingRooms.erase(it); - it = m_stagingRooms.begin(); - } - if (numRoomsRemoved > 0) - { - //m_stagingRoomsDirty = true; // only consider ourselves dirty if we actually removed some games. - } -} - -void GameSpyInfo::addStagingRoom( GameSpyStagingRoom room ) -{ - removeStagingRoom(room); - GameSpyStagingRoom *newRoom = NEW GameSpyStagingRoom; - *newRoom = room; - newRoom->cleanUpSlotPointers(); - m_stagingRooms[room.getID()] = newRoom; - m_stagingRoomsDirty = m_sawFullGameList; -} - -void GameSpyInfo::updateStagingRoom( GameSpyStagingRoom room ) -{ - addStagingRoom(room); -} - -void GameSpyInfo::removeStagingRoom( GameSpyStagingRoom room ) -{ - StagingRoomMap::iterator it = m_stagingRooms.find(room.getID()); - if (it != m_stagingRooms.end()) - { - delete it->second; - m_stagingRooms.erase(it); - - m_stagingRoomsDirty = m_sawFullGameList; - } -} - -Bool GameSpyInfo::hasStagingRoomListChanged( void ) -{ - Bool val = m_stagingRoomsDirty; - m_stagingRoomsDirty = false; - return val; -} - -GameSpyStagingRoom* GameSpyInfo::findStagingRoomByID( Int id ) -{ - StagingRoomMap::iterator it = m_stagingRooms.find(id); - if (it != m_stagingRooms.end()) - return it->second; - - return NULL; -} - -void GameSpyInfo::leaveStagingRoom( void ) -{ - m_localStagingRoomID = 0; - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_LEAVESTAGINGROOM; - TheGameSpyPeerMessageQueue->addRequest(req); - m_playerInfoMap.clear(); - m_joinedStagingRoom = FALSE; - m_isHosting = FALSE; -} - -void GameSpyInfo::markAsStagingRoomHost( void ) -{ - m_localStagingRoomID = 0; - m_joinedStagingRoom = FALSE; m_isHosting = TRUE; - m_localStagingRoom.reset(); - m_localStagingRoom.enterGame(); - m_localStagingRoom.setSeed(GetTickCount()); - - GameSlot newSlot; - UnicodeString uName; - uName.translate(m_localName); - newSlot.setState(SLOT_PLAYER, uName); - - m_localStagingRoom.setLocalIP(m_externalIP); - newSlot.setIP(m_externalIP); - - m_localStagingRoom.setSlot(0,newSlot); - m_localStagingRoom.setLocalName(m_localName); - - TheMapCache->updateCache(); - m_localStagingRoom.setMap(getDefaultMap(TRUE)); - m_localStagingRoom.adjustSlotsForMap(); // close slots that the map can't hold. BGC -} - -void GameSpyInfo::markAsStagingRoomJoiner( Int game ) -{ - m_localStagingRoomID = game; - m_joinedStagingRoom = TRUE; m_isHosting = FALSE; - m_localStagingRoom.reset(); - m_localStagingRoom.enterGame(); - StagingRoomMap::iterator it = m_stagingRooms.find(game); - if (it != m_stagingRooms.end()) - { - GameSpyStagingRoom *info = it->second; - info->cleanUpSlotPointers(); - AsciiString options = GameInfoToAsciiString(info); -#ifdef DEBUG_CRASHING - Bool res = -#endif - ParseAsciiStringToGameInfo(&m_localStagingRoom, options); - DEBUG_ASSERTCRASH(res, ("Could not parse game info \"%s\"", options.str())); - m_localStagingRoom.setInGame(); - m_localStagingRoom.setLocalName(m_localName); - m_localStagingRoom.setExeCRC(info->getExeCRC()); - m_localStagingRoom.setIniCRC(info->getIniCRC()); - m_localStagingRoom.setAllowObservers(info->getAllowObservers()); - m_localStagingRoom.setHasPassword(info->getHasPassword()); - m_localStagingRoom.setGameName(info->getGameName()); - DEBUG_LOG(("Joining game: host is %ls\n", m_localStagingRoom.getConstSlot(0)->getName().str())); - } -} - -void GameSpyInfo::setMOTD( const AsciiString& motd ) -{ - m_rawMotd = motd; -} - -const AsciiString& GameSpyInfo::getMOTD( void ) -{ - return m_rawMotd; -} - -void GameSpyInfo::setConfig( const AsciiString& config ) -{ - m_rawConfig = config; -} - -const AsciiString& GameSpyInfo::getConfig( void ) -{ - return m_rawConfig; -} - -// -------------------------------------------------------------- -void SetUpGameSpy( const char *motdBuffer, const char *configBuffer ) -{ - if (!motdBuffer) - motdBuffer = ""; - if (!configBuffer) - configBuffer = ""; - TearDownGameSpy(); - - AsciiString dir = TheGlobalData->getPath_UserData(); - CreateDirectory(dir.str(), NULL); - dir.format("%sGeneralsOnline", TheGlobalData->getPath_UserData().str()); - CreateDirectory(dir.str(), NULL); - dir.format("%sGeneralsOnline\\Ladders", TheGlobalData->getPath_UserData().str()); - CreateDirectory(dir.str(), NULL); - - TheGameSpyBuddyMessageQueue = GameSpyBuddyMessageQueueInterface::createNewMessageQueue(); - TheGameSpyBuddyMessageQueue->startThread(); - - TheGameSpyPeerMessageQueue = GameSpyPeerMessageQueueInterface::createNewMessageQueue(); - TheGameSpyPeerMessageQueue->startThread(); - - TheGameSpyPSMessageQueue = GameSpyPSMessageQueueInterface::createNewMessageQueue(); - TheGameSpyPSMessageQueue->startThread(); - - /* - TheGameSpyGame = NEW GameSpyStagingRoom; - */ - - TheGameSpyInfo = GameSpyInfoInterface::createNewGameSpyInfoInterface(); - TheGameSpyInfo->setMOTD(motdBuffer); - TheGameSpyInfo->setConfig(configBuffer); - - CustomMatchPreferences pref; - TheGameSpyInfo->setDisallowAsianText(pref.getDisallowAsianText()); - TheGameSpyInfo->setDisallowNonAsianText( pref.getDisallowNonAsianText()); - - - TheGameSpyConfig = GameSpyConfigInterface::create(configBuffer); - - TheLadderList = NEW LadderList; - - ThePinger = PingerInterface::createNewPingerInterface(); - ThePinger->startThreads(); - - TheRankPointValues = NEW RankPoints; -} - -void TearDownGameSpy( void ) -{ - // save off cached stats - if (TheGameSpyInfo && TheGameSpyInfo->getLocalProfileID()) - { -// /* This was done on the score screen, so there is no need to do it now. -// * - PSPlayerStats localPSStats = TheGameSpyPSMessageQueue->findPlayerStatsByID(TheGameSpyInfo->getLocalProfileID()); - if (localPSStats.id != 0) - { - GameSpyMiscPreferences mPref; - mPref.setCachedStats(GameSpyPSMessageQueueInterface::formatPlayerKVPairs(localPSStats).c_str()); - mPref.write(); - } -// */ - } - - // End our threads before we kill off the singletons they reference. No crashy-crash for you! - if (TheGameSpyPSMessageQueue) - TheGameSpyPSMessageQueue->endThread(); - if (TheGameSpyBuddyMessageQueue) - TheGameSpyBuddyMessageQueue->endThread(); - if (TheGameSpyPeerMessageQueue) - TheGameSpyPeerMessageQueue->endThread(); - if (ThePinger) - ThePinger->endThreads(); - - if(TheRankPointValues) - { - delete TheRankPointValues; - TheRankPointValues = NULL; - } - if (TheGameSpyPSMessageQueue) - { - delete TheGameSpyPSMessageQueue; - TheGameSpyPSMessageQueue = NULL; - } - - if (TheGameSpyBuddyMessageQueue) - { - delete TheGameSpyBuddyMessageQueue; - TheGameSpyBuddyMessageQueue = NULL; - } - - if (TheGameSpyPeerMessageQueue) - { - delete TheGameSpyPeerMessageQueue; - TheGameSpyPeerMessageQueue = NULL; - } - - if (TheGameSpyInfo) - { - if (TheGameSpyInfo->getInternalIP()) - { - // we've logged in before. mark us as logging out. - SignalUIInteraction(SHELL_SCRIPT_HOOK_GENERALS_ONLINE_LOGOUT); - } - delete TheGameSpyInfo; - TheGameSpyInfo = NULL; - } - - if (ThePinger) - { - delete ThePinger; - ThePinger = NULL; - } - - if (TheLadderList) - { - delete TheLadderList; - TheLadderList = NULL; - } - - if (TheGameSpyConfig) - { - delete TheGameSpyConfig; - TheGameSpyConfig = NULL; - } - - // make sure the notification box doesn't exist - deleteNotificationBox(); -} - - -void GameSpyInfo::addToIgnoreList( AsciiString nick ) -{ - m_ignoreList.insert(nick); -} - -void GameSpyInfo::removeFromIgnoreList( AsciiString nick ) -{ - m_ignoreList.erase(nick); -} - -Bool GameSpyInfo::isIgnored( AsciiString nick ) -{ - return m_ignoreList.find(nick) != m_ignoreList.end(); -} - -IgnoreList GameSpyInfo::returnIgnoreList( void ) -{ - return m_ignoreList; -} - -void GameSpyInfo::addToSavedIgnoreList( Int profileID, AsciiString nick) -{ - m_savedIgnoreMap[profileID] = nick; - IgnorePreferences pref; - pref.setIgnore(nick, profileID, true); - pref.write(); -} - -void GameSpyInfo::removeFromSavedIgnoreList( Int profileID ) -{ - m_savedIgnoreMap.erase(profileID); - IgnorePreferences pref; - pref.setIgnore(AsciiString::TheEmptyString, profileID, false); - pref.write(); -} - -Bool GameSpyInfo::isSavedIgnored( Int profileID ) -{ - return m_savedIgnoreMap.find(profileID) != m_savedIgnoreMap.end(); -} - -SavedIgnoreMap GameSpyInfo::returnSavedIgnoreList( void ) -{ - return m_savedIgnoreMap; -} - -static Int grabHexInt(const char *s) -{ - char tmp[5] = "0xff"; - tmp[2] = s[0]; - tmp[3] = s[1]; - Int b = strtol(tmp, NULL, 16); - return b; -} - -Int GameSpyInfo::getPingValue( const AsciiString& otherPing ) -{ - if (m_pingString.getLength() != otherPing.getLength()) - { - return TheGameSpyConfig->getPingTimeoutInMs(); - } - - if (m_pingString.getLength() % 2 != 0) - { - return TheGameSpyConfig->getPingTimeoutInMs(); - } - - Int best = 255+255; - const char *myStr = m_pingString.str(); - const char *otherStr = otherPing.str(); - - while (*myStr) - { - Int myVal = grabHexInt(myStr); - Int otherVal = grabHexInt(otherStr); - Int val = myVal + otherVal; - best = (val < best) ? val : best; - myStr += 2; - otherStr += 2; - } - - return best * TheGameSpyConfig->getPingTimeoutInMs() / (255+255); -} - -Bool PlayerInfo::isIgnored( void ) -{ - return (m_profileID)?TheGameSpyInfo->isSavedIgnored(m_profileID):TheGameSpyInfo->isIgnored(m_name); -} - -void GameSpyInfo::loadSavedIgnoreList( void ) -{ - m_savedIgnoreMap.clear(); - IgnorePreferences prefs; - m_savedIgnoreMap = prefs.getIgnores(); -} - -void GameSpyInfo::setDisallowAsianText( Bool val ) -{ - m_disallowAsainText = val; -} - -void GameSpyInfo::setDisallowNonAsianText( Bool val ) -{ - m_disallowNonAsianText = val; -} - -Bool GameSpyInfo::getDisallowAsianText( void ) -{ - return m_disallowAsainText; -} -Bool GameSpyInfo::getDisallowNonAsianText(void ) -{ - return m_disallowNonAsianText; -} - -void GameSpyInfo::setMaxMessagesPerUpdate( Int num ) -{ - m_maxMessagesPerUpdate = num; -} - -Int GameSpyInfo::getMaxMessagesPerUpdate( void ) -{ - return m_maxMessagesPerUpdate; -} - -/**This function is used to force an update of player's gamespy stats with an additional -disconnection. This is used upon starting a new game so that if user disconnects prior -to finishing game, the disconnection stays on the server. If he completes the game, we -remove this extra disconnection inside of populatePlayerInfo() on the ScoreScreen. This -seems like the only secure way to handle this issue since users can abort the process -before we can detect/log disconnections.*/ -void GameSpyInfo::updateAdditionalGameSpyDisconnections(Int count) -{ - if (TheRecorder->isMultiplayer() && TheGameLogic->isInInternetGame()) - { - Int localID = TheGameSpyInfo->getLocalProfileID(); - PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(localID); - - Player *player=ThePlayerList->getLocalPlayer(); - - Int ptIdx; - const PlayerTemplate *myTemplate = player->getPlayerTemplate(); - DEBUG_LOG(("myTemplate = %X(%s)\n", myTemplate, myTemplate->getName().str())); - for (ptIdx = 0; ptIdx < ThePlayerTemplateStore->getPlayerTemplateCount(); ++ptIdx) - { - const PlayerTemplate *nthTemplate = ThePlayerTemplateStore->getNthPlayerTemplate(ptIdx); - DEBUG_LOG(("nthTemplate = %X(%s)\n", nthTemplate, nthTemplate->getName().str())); - if (nthTemplate == myTemplate) - { - break; - } - } - - Bool anyAI = FALSE; - for (Int i=0; igetConstSlot(i); - - if (slot->isAI()) - { - anyAI = TRUE; - } - } - - //Check for cases where we're not tracking stats. - if (anyAI || stats.id == 0 || myTemplate->isObserver() || player->getPlayerType() != PLAYER_HUMAN || player->isPlayerObserver()) - return; - - Int disCons=stats.discons[ptIdx]; - disCons += count; - if (disCons < 0) - { DEBUG_LOG(("updateAdditionalGameSpyDisconnections() - disconnection count below zero\n")); - return; //something is wrong here - } - stats.discons[ptIdx] = disCons; //add an additional disconnection to their stats. - - //Add an additional disconnection to player stats. - PSRequest req; - - req.requestType = PSRequest::PSREQUEST_UPDATEPLAYERSTATS; - req.email = TheGameSpyInfo->getLocalEmail().str(); - req.nick = TheGameSpyInfo->getLocalBaseName().str(); - req.password = TheGameSpyInfo->getLocalPassword().str(); - req.player = stats; - req.addDesync = FALSE; - req.addDiscon = FALSE; - req.lastHouse = ptIdx; - - TheGameSpyPSMessageQueue->addRequest(req); - TheGameSpyPSMessageQueue->trackPlayerStats(stats); - - // force an update of our shtuff - PSResponse newResp; - newResp.responseType = PSResponse::PSRESPONSE_PLAYERSTATS; - newResp.player = stats; - TheGameSpyPSMessageQueue->addResponse(newResp); - - // cache our stuff for easy reading next time - GameSpyMiscPreferences mPref; - mPref.setCachedStats(GameSpyPSMessageQueueInterface::formatPlayerKVPairs(stats).c_str()); - mPref.write(); - } -} diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/StagingRoomGameInfo.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/StagingRoomGameInfo.cpp deleted file mode 100644 index 19452faae11..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/StagingRoomGameInfo.cpp +++ /dev/null @@ -1,896 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: StagingRoomGameInfo.cpp ////////////////////////////////////////////////////// -// Generals GameSpy GameInfo-related code -// Author: Matthew D. Campbell, July 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameState.h" -#include "Common/Player.h" -#include "Common/PlayerList.h" -#include "Common/PlayerTemplate.h" -#include "Common/RandomValue.h" -#include "Common/ScoreKeeper.h" -#include "GameClient/GameText.h" -#include "GameClient/MapUtil.h" -#include "GameClient/Shell.h" -#include "GameLogic/GameLogic.h" -#include "GameLogic/VictoryConditions.h" -#include "GameNetwork/FileTransfer.h" -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpy/ThreadUtils.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameNetwork/NAT.h" -#include "GameNetwork/NetworkInterface.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -// GameSpyGameSlot ------------------------------------------- - -GameSpyGameSlot::GameSpyGameSlot() -{ - GameSlot(); - m_gameSpyLogin.clear(); - m_gameSpyLocale.clear(); - m_profileID = 0; - m_wins = 0; - m_losses = 0; - m_rankPoints = 0; - m_favoriteSide = 0; - m_pingInt = 0; - // Added By Sadullah Nader - // Initializations missing and needed - m_profileID = 0; - m_pingStr.clear(); -} - -// Helper Functions ---------------------------------------- -/* -** Function definitions for the MIB-II entry points. -*/ - -BOOL (__stdcall *SnmpExtensionInitPtr)(IN DWORD dwUpTimeReference, OUT HANDLE *phSubagentTrapEvent, OUT AsnObjectIdentifier *pFirstSupportedRegion); -BOOL (__stdcall *SnmpExtensionQueryPtr)(IN BYTE bPduType, IN OUT RFC1157VarBindList *pVarBindList, OUT AsnInteger32 *pErrorStatus, OUT AsnInteger32 *pErrorIndex); -LPVOID (__stdcall *SnmpUtilMemAllocPtr)(IN DWORD bytes); -VOID (__stdcall *SnmpUtilMemFreePtr)(IN LPVOID pMem); - -typedef struct tConnInfoStruct { - unsigned int State; - unsigned long LocalIP; - unsigned short LocalPort; - unsigned long RemoteIP; - unsigned short RemotePort; -} ConnInfoStruct; - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) -#endif - -/*********************************************************************************************** - * Get_Local_Chat_Connection_Address -- Which address are we using to talk to the chat server? * - * * - * * - * * - * INPUT: Ptr to address to return local address * * - * * - * OUTPUT: True if success * - * * - * WARNINGS: None * - * * - * HISTORY: * - * 10/27/00 3:24PM ST : Created * - *=============================================================================================*/ -Bool GetLocalChatConnectionAddress(AsciiString serverName, UnsignedShort serverPort, UnsignedInt& localIP) -{ - //return false; - /* - ** Local defines. - */ - enum { - CLOSED = 1, - LISTENING, - SYN_SENT, - SEN_RECEIVED, - ESTABLISHED, - FIN_WAIT, - FIN_WAIT2, - CLOSE_WAIT, - LAST_ACK, - CLOSING, - TIME_WAIT, - DELETE_TCB - }; - - enum { - tcpConnState = 1, - tcpConnLocalAddress, - tcpConnLocalPort, - tcpConnRemAddress, - tcpConnRemPort - }; - - - /* - ** Locals. - */ - unsigned char serverAddress[4]; - unsigned char remoteAddress[4]; - HANDLE trap_handle; - AsnObjectIdentifier first_supported_region; - std::vector connectionVector; - int last_field; - int index; - AsnInteger error_status; - AsnInteger error_index; - int conn_entry_type_index; - int conn_entry_type; - Bool found; - - /* - ** Statics. - */ - static char _conn_state[][32] = { - "?", - "CLOSED", - "LISTENING", - "SYN_SENT", - "SEN_RECEIVED", - "ESTABLISHED", - "FIN_WAIT", - "FIN_WAIT2", - "CLOSE_WAIT", - "LAST_ACK", - "CLOSING", - "TIME_WAIT", - "DELETE_TCB" - }; - - DEBUG_LOG(("Finding local address used to talk to the chat server\n")); - DEBUG_LOG(("Current chat server name is %s\n", serverName.str())); - DEBUG_LOG(("Chat server port is %d\n", serverPort)); - - /* - ** Get the address of the chat server. - */ - DEBUG_LOG( ("About to call gethostbyname\n")); - struct hostent *host_info = gethostbyname(serverName.str()); - - if (!host_info) { - DEBUG_LOG( ("gethostbyname failed! Error code %d\n", WSAGetLastError())); - return(false); - } - - memcpy(serverAddress, &host_info->h_addr_list[0][0], 4); - unsigned long temp = *((unsigned long*)(&serverAddress[0])); - temp = ntohl(temp); - *((unsigned long*)(&serverAddress[0])) = temp; - - DEBUG_LOG(("Host address is %d.%d.%d.%d\n", serverAddress[3], serverAddress[2], serverAddress[1], serverAddress[0])); - - /* - ** Load the MIB-II SNMP DLL. - */ - DEBUG_LOG(("About to load INETMIB1.DLL\n")); - - HINSTANCE mib_ii_dll = LoadLibrary("inetmib1.dll"); - if (mib_ii_dll == NULL) { - DEBUG_LOG(("Failed to load INETMIB1.DLL\n")); - return(false); - } - - DEBUG_LOG(("About to load SNMPAPI.DLL\n")); - - HINSTANCE snmpapi_dll = LoadLibrary("snmpapi.dll"); - if (snmpapi_dll == NULL) { - DEBUG_LOG(("Failed to load SNMPAPI.DLL\n")); - FreeLibrary(mib_ii_dll); - return(false); - } - - /* - ** Get the function pointers into the .dll - */ - SnmpExtensionInitPtr = (int (__stdcall *)(unsigned long,void ** ,AsnObjectIdentifier *)) GetProcAddress(mib_ii_dll, "SnmpExtensionInit"); - SnmpExtensionQueryPtr = (int (__stdcall *)(unsigned char,SnmpVarBindList *,long *,long *)) GetProcAddress(mib_ii_dll, "SnmpExtensionQuery"); - SnmpUtilMemAllocPtr = (void *(__stdcall *)(unsigned long)) GetProcAddress(snmpapi_dll, "SnmpUtilMemAlloc"); - SnmpUtilMemFreePtr = (void (__stdcall *)(void *)) GetProcAddress(snmpapi_dll, "SnmpUtilMemFree"); - if (SnmpExtensionInitPtr == NULL || SnmpExtensionQueryPtr == NULL || SnmpUtilMemAllocPtr == NULL || SnmpUtilMemFreePtr == NULL) { - DEBUG_LOG(("Failed to get proc addresses for linked functions\n")); - FreeLibrary(snmpapi_dll); - FreeLibrary(mib_ii_dll); - return(false); - } - - - RFC1157VarBindList *bind_list_ptr = (RFC1157VarBindList *) SnmpUtilMemAllocPtr(sizeof(RFC1157VarBindList)); - RFC1157VarBind *bind_ptr = (RFC1157VarBind *) SnmpUtilMemAllocPtr(sizeof(RFC1157VarBind)); - - /* - ** OK, here we go. Try to initialise the .dll - */ - DEBUG_LOG(("About to init INETMIB1.DLL\n")); - int ok = SnmpExtensionInitPtr(GetCurrentTime(), &trap_handle, &first_supported_region); - - if (!ok) { - /* - ** Aw crap. - */ - DEBUG_LOG(("Failed to init the .dll\n")); - SnmpUtilMemFreePtr(bind_list_ptr); - SnmpUtilMemFreePtr(bind_ptr); - FreeLibrary(snmpapi_dll); - FreeLibrary(mib_ii_dll); - return(false); - } - - /* - ** Name of mib_ii object we want to query. See RFC 1213. - ** - ** iso.org.dod.internet.mgmt.mib-2.tcp.tcpConnTable.TcpConnEntry.tcpConnState - ** 1 3 6 1 2 1 6 13 1 1 - */ - unsigned int mib_ii_name[] = {1,3,6,1,2,1,6,13,1,1}; - unsigned int *mib_ii_name_ptr = (unsigned int *) SnmpUtilMemAllocPtr(sizeof(mib_ii_name)); - memcpy(mib_ii_name_ptr, mib_ii_name, sizeof(mib_ii_name)); - - /* - ** Get the index of the conn entry data. - */ - conn_entry_type_index = ARRAY_SIZE(mib_ii_name) - 1; - - /* - ** Set up the bind list. - */ - bind_ptr->name.idLength = ARRAY_SIZE(mib_ii_name); - bind_ptr->name.ids = mib_ii_name; - bind_list_ptr->list = bind_ptr; - bind_list_ptr->len = 1; - - - /* - ** We start with the tcpConnLocalAddress field. - */ - last_field = 1; - - /* - ** First connection. - */ - index = 0; - - /* - ** Suck out that tcp connection info.... - */ - while (true) { - - if (!SnmpExtensionQueryPtr(SNMP_PDU_GETNEXT, bind_list_ptr, &error_status, &error_index)) { - //if (!SnmpExtensionQueryPtr(ASN_RFC1157_GETNEXTREQUEST, bind_list_ptr, &error_status, &error_index)) { - DEBUG_LOG(("SnmpExtensionQuery returned false\n")); - SnmpUtilMemFreePtr(bind_list_ptr); - SnmpUtilMemFreePtr(bind_ptr); - FreeLibrary(snmpapi_dll); - FreeLibrary(mib_ii_dll); - return(false); - } - - /* - ** If this is something new we aren't looking for then we are done. - */ - if (bind_ptr->name.idLength < ARRAY_SIZE(mib_ii_name)) { - break; - } - - /* - ** Get the type of info we are looking at. See RFC1213. - ** - ** 1 = tcpConnState - ** 2 = tcpConnLocalAddress - ** 3 = tcpConnLocalPort - ** 4 = tcpConnRemAddress - ** 5 = tcpConnRemPort - ** - ** tcpConnState is one of the following... - ** - ** 1 closed - ** 2 listen - ** 3 synSent - ** 4 synReceived - ** 5 established - ** 6 finWait1 - ** 7 finWait2 - ** 8 closeWait - ** 9 lastAck - ** 10 closing - ** 11 timeWait - ** 12 deleteTCB - */ - conn_entry_type = bind_ptr->name.ids[conn_entry_type_index]; - - if (last_field != conn_entry_type) { - index = 0; - last_field = conn_entry_type; - } - - switch (conn_entry_type) { - - /* - ** 1. First field in the entry. Need to create a new connection info struct - ** here to store this connection in. - */ - case tcpConnState: - { - ConnInfoStruct new_conn; - new_conn.State = bind_ptr->value.asnValue.number; - connectionVector.push_back(new_conn); - break; - } - - /* - ** 2. Local address field. - */ - case tcpConnLocalAddress: - DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index")); - connectionVector[index].LocalIP = *((unsigned long*)bind_ptr->value.asnValue.address.stream); - index++; - break; - - /* - ** 3. Local port field. - */ - case tcpConnLocalPort: - DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index")); - connectionVector[index].LocalPort = bind_ptr->value.asnValue.number; - //connectionVector[index]->LocalPort = ntohs(connectionVector[index]->LocalPort); - index++; - break; - - /* - ** 4. Remote address field. - */ - case tcpConnRemAddress: - DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index")); - connectionVector[index].RemoteIP = *((unsigned long*)bind_ptr->value.asnValue.address.stream); - index++; - break; - - /* - ** 5. Remote port field. - */ - case tcpConnRemPort: - DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index")); - connectionVector[index].RemotePort = bind_ptr->value.asnValue.number; - //connectionVector[index]->RemotePort = ntohs(connectionVector[index]->RemotePort); - index++; - break; - } - } - - SnmpUtilMemFreePtr(bind_list_ptr); - SnmpUtilMemFreePtr(bind_ptr); - SnmpUtilMemFreePtr(mib_ii_name_ptr); - - DEBUG_LOG(("Got %d connections in list, parsing...\n", connectionVector.size())); - - /* - ** Right, we got the lot. Lets see if any of them have the same address as the chat - ** server we think we are talking to. - */ - found = false; - for (Int i=0; igetPingValue(pingStr); -} - -// GameSpyStagingRoom ---------------------------------------- - -GameSpyStagingRoom::GameSpyStagingRoom() -{ - cleanUpSlotPointers(); - - setLocalIP(0); - m_transport = NULL; - - m_localName = "localhost"; - - m_ladderIP.clear(); - m_ladderPort = 0; -} - -void GameSpyStagingRoom::cleanUpSlotPointers( void ) -{ - for (Int i = 0; i< MAX_SLOTS; ++i) - setSlotPointer(i, &m_GameSpySlot[i]); -} - -GameSpyGameSlot * GameSpyStagingRoom::getGameSpySlot( Int index ) -{ - GameSlot *slot = getSlot(index); - DEBUG_ASSERTCRASH(slot && (slot == &(m_GameSpySlot[index])), ("Bad game slot pointer\n")); - return (GameSpyGameSlot *)slot; -} - -void GameSpyStagingRoom::init( void ) -{ - GameInfo::init(); -} - -void GameSpyStagingRoom::setPingString( AsciiString pingStr ) -{ - m_pingStr = pingStr; - m_pingInt = TheGameSpyInfo->getPingValue(pingStr); -} - -Bool GameSpyStagingRoom::amIHost( void ) const -{ - DEBUG_ASSERTCRASH(m_inGame, ("Looking for game slot while not in game")); - if (!m_inGame) - return false; - - return getConstSlot(0)->isPlayer(m_localName); -} - -void GameSpyStagingRoom::resetAccepted( void ) -{ - GameInfo::resetAccepted(); - - if (amIHost()) - { - /* - peerStateChanged(TheGameSpyChat->getPeer()); - m_hasBeenQueried = false; - DEBUG_LOG(("resetAccepted() called peerStateChange()\n")); - */ - } -} - -Int GameSpyStagingRoom::getLocalSlotNum( void ) const -{ - DEBUG_ASSERTCRASH(m_inGame, ("Looking for local game slot while not in game")); - if (!m_inGame) - return -1; - - AsciiString localName = TheGameSpyInfo->getLocalName(); - - for (Int i=0; iisPlayer(localName)) - return i; - } - return -1; -} - -void GameSpyStagingRoom::startGame(Int gameID) -{ - DEBUG_ASSERTCRASH(m_inGame, ("Starting a game while not in game")); - DEBUG_LOG(("GameSpyStagingRoom::startGame - game id = %d\n", gameID)); - DEBUG_ASSERTCRASH(m_transport == NULL, ("m_transport is not NULL when it should be")); - DEBUG_ASSERTCRASH(TheNAT == NULL, ("TheNAT is not NULL when it should be")); - - UnsignedInt localIP = TheGameSpyInfo->getInternalIP(); - setLocalIP(localIP); - - if (TheNAT != NULL) { - delete TheNAT; - TheNAT = NULL; - } - - // fill in GS-specific info - Int numHumans = 0; - for (Int i=0; igetLocalProfileID()); // hehe - we know our own. the rest, they'll tell us. - } - else - { - PlayerInfoMap *pInfoMap = TheGameSpyInfo->getPlayerInfoMap(); - PlayerInfoMap::iterator it = pInfoMap->find(gsName); - if (it != pInfoMap->end()) - { - m_GameSpySlot[i].setProfileID(it->second.m_profileID); - m_GameSpySlot[i].setLocale(it->second.m_locale); - m_GameSpySlot[i].setSlotRankPoints(it->second.m_rankPoints); - m_GameSpySlot[i].setFavoriteSide(it->second.m_side); - } - else - { - DEBUG_CRASH(("No player info for %s", gsName.str())); - } - } - } - } - -//#if defined(_DEBUG) || defined(_INTERNAL) - if (numHumans < 2) - { - launchGame(); - if (TheGameSpyInfo) - TheGameSpyInfo->leaveStagingRoom(); - } - else -//#endif defined(_DEBUG) || defined(_INTERNAL) - { - TheNAT = NEW NAT(); - TheNAT->attachSlotList(m_slot, getLocalSlotNum(), m_localIP); - TheNAT->establishConnectionPaths(); - } -} - -AsciiString GameSpyStagingRoom::generateGameSpyGameResultsPacket( void ) -{ - Int i; - Int endFrame = TheVictoryConditions->getEndFrame(); - Int localSlotNum = getLocalSlotNum(); - Int winningTeam = -1; - Int numHumans = 0; - Int numPlayers = 0; - Int numAIs = 0; - Int numTeamsAtGameEnd = 0; - Int lastTeamAtGameEnd = -1; - for (i=0; ifindPlayerWithNameKey(NAMEKEY(playerName)); - if (p) - { - ++numHumans; - if (TheVictoryConditions->hasAchievedVictory(p)) - { - winningTeam = getSlot(i)->getTeamNumber(); - } - - // check if he lasted - GameSlot *slot = getSlot(i); - if (!slot->disconnected()) - { - if (slot->getTeamNumber() != lastTeamAtGameEnd || numTeamsAtGameEnd == 0) - { - lastTeamAtGameEnd = slot->getTeamNumber(); - ++numTeamsAtGameEnd; - } - } - } - else - { - if (m_GameSpySlot[i].isAI()) - ++numAIs; - } - } - numPlayers = numHumans + numAIs; - - AsciiString mapName; - for (i=0; ifindPlayerWithNameKey(NAMEKEY(playerName)); - if (p) - { - GameSpyGameSlot *slot = &(m_GameSpySlot[i]); - AsciiString playerName = (slot->isHuman())?slot->getLoginName():"AIPlayer"; - Int gsPlayerID = slot->getProfileID(); - Bool disconnected = slot->disconnected(); - - AsciiString result = "loss", side = "USA"; - if (disconnected) - result = "discon"; - else if (TheNetwork->sawCRCMismatch()) - result = "desync"; - else if (TheVictoryConditions->hasAchievedVictory(p)) - result = "win"; - - side = p->getPlayerTemplate()->getSide(); - if (side == "America") - side = "USA"; - - AsciiString playerStr; - playerStr.format("\\player_%d\\%s\\pid_%d\\%d\\team_%d\\%d\\result_%d\\%s\\side_%d\\%s", - playerID, playerName.str(), playerID, gsPlayerID, playerID, slot->getTeamNumber(), - playerID, result.str(), playerID, side.str()); - results.concat(playerStr); - - ++playerID; - } - } - - return results; -} - -AsciiString GameSpyStagingRoom::generateLadderGameResultsPacket( void ) -{ - Int i; - Int endFrame = TheVictoryConditions->getEndFrame(); - Int localSlotNum = getLocalSlotNum(); - Bool sawGameEnd = (endFrame > 0); - Int winningTeam = -1; - Int numPlayers = 0; - Int numTeamsAtGameEnd = 0; - Int lastTeamAtGameEnd = -1; - Player* p[MAX_SLOTS]; - for (i=0; ifindPlayerWithNameKey(NAMEKEY(playerName)); - if (p[i]) - { - ++numPlayers; - if (TheVictoryConditions->hasAchievedVictory(p[i])) - { - winningTeam = getSlot(i)->getTeamNumber(); - } - - // check if he lasted - GameSlot *slot = getSlot(i); - if (!slot->disconnected()) - { - if (slot->getTeamNumber() != lastTeamAtGameEnd || numTeamsAtGameEnd == 0) - { - lastTeamAtGameEnd = slot->getTeamNumber(); - ++numTeamsAtGameEnd; - } - } - } - } - - AsciiString results; - results.format("seed=%d,slotNum=%d,sawDesync=%d,sawGameEnd=%d,winningTeam=%d,disconEnd=%d,duration=%d,numPlayers=%d,isQM=%d,map=%s", - getSeed(), localSlotNum, TheNetwork->sawCRCMismatch(), sawGameEnd, winningTeam, (numTeamsAtGameEnd < 2), - endFrame, numPlayers, m_isQM, TheGameState->realMapPathToPortableMapPath(getMap()).str()); - - AsciiString tempStr; - tempStr.format(",ladderIP=%s,ladderPort=%d", getLadderIP().str(), getLadderPort()); - results.concat(tempStr); - - Int playerID = 0; - for (i=0; igetScoreKeeper(); - AsciiString playerName = slot->getLoginName(); - Int gsPlayerID = slot->getProfileID(); - PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(gsPlayerID); - Int fps = TheNetwork->getAverageFPS(); - Int unitsKilled = keeper->getTotalUnitsDestroyed(); - Int unitsLost = keeper->getTotalUnitsLost(); - Int unitsBuilt = keeper->getTotalUnitsBuilt(); - Int buildingsKilled = keeper->getTotalBuildingsDestroyed(); - Int buildingsLost = keeper->getTotalBuildingsLost(); - Int buildingsBuilt = keeper->getTotalBuildingsBuilt(); - Int earnings = keeper->getTotalMoneyEarned(); - Int techCaptured = keeper->getTotalTechBuildingsCaptured(); - Bool disconnected = slot->disconnected(); - - AsciiString playerStr; - playerStr.format(",player%d=%s,playerID%d=%d,locale%d=%d", - playerID, playerName.str(), playerID, gsPlayerID, playerID, stats.locale); - results.concat(playerStr); - playerStr.format(",unitsKilled%d=%d,unitsLost%d=%d,unitsBuilt%d=%d", - playerID, unitsKilled, playerID, unitsLost, playerID, unitsBuilt); - results.concat(playerStr); - playerStr.format(",buildingsKilled%d=%d,buildingsLost%d=%d,buildingsBuilt%d=%d", - playerID, buildingsKilled, playerID, buildingsLost, playerID, buildingsBuilt); - results.concat(playerStr); - playerStr.format(",fps%d=%d,cash%d=%d,capturedTech%d=%d,discon%d=%d,side%d=%s,team%d=%d", - playerID, fps, playerID, earnings, playerID, techCaptured, playerID, disconnected, playerID, p[i]->getPlayerTemplate()->getSide().str(), playerID, slot->getTeamNumber()); - results.concat(playerStr); - - ++playerID; - } - } - - // Add a trailing size value (so the server can ensure it got the entire packet) - results.concat(",size="); - int resultsLen = results.getLength()+10; - AsciiString tail; - tail.format("%10.10d", resultsLen); - results.concat(tail); - - return results; -} - -void GameSpyStagingRoom::launchGame( void ) -{ - setGameInProgress(TRUE); - - for (Int i=0; iisHuman()) - { - if (TheGameSpyInfo->didPlayerPreorder(slot->getProfileID())) - markPlayerAsPreorder(i); - } - } - - // Set up the game network - AsciiString user; - AsciiString userList; - DEBUG_ASSERTCRASH(TheNetwork == NULL, ("For some reason TheNetwork isn't NULL at the start of this game. Better look into that.")); - - if (TheNetwork != NULL) { - delete TheNetwork; - TheNetwork = NULL; - } - - // Time to initialize TheNetwork for this game. - TheNetwork = NetworkInterface::createNetwork(); - TheNetwork->init(); - - TheNetwork->setLocalAddress(getLocalIP(), (TheNAT)?TheNAT->getSlotPort(getLocalSlotNum()):8888); - if (TheNAT) - TheNetwork->attachTransport(TheNAT->getTransport()); - else - TheNetwork->initTransport(); - - TheNetwork->parseUserList(this); - - - if (TheGameLogic->isInGame()) { - TheGameLogic->clearGameData(); - } - - Bool filesOk = DoAnyMapTransfers(this); - - // see if we really have the map. if not, back out. - TheMapCache->updateCache(); - if (!filesOk || TheMapCache->findMap(getMap()) == NULL) - { - DEBUG_LOG(("After transfer, we didn't really have the map. Bailing...\n")); - if (TheNetwork != NULL) { - delete TheNetwork; - TheNetwork = NULL; - } - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:CouldNotTransferMap")); - - void PopBackToLobby( void ); - PopBackToLobby(); - return; - } - - - // shutdown the top, but do not pop it off the stack -// TheShell->hideShell(); - // setup the Global Data with the Map and Seed - TheWritableGlobalData->m_pendingFile = TheGameSpyGame->getMap(); - - // send a message to the logic for a new game - GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_NEW_GAME ); - msg->appendIntegerArgument(GAME_INTERNET); - - TheWritableGlobalData->m_useFpsLimit = false; - - // Set the random seed - InitGameLogicRandom( getSeed() ); - DEBUG_LOG(("InitGameLogicRandom( %d )\n", getSeed())); - - // mark us as "Loading" in the buddy list - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_SETSTATUS; - req.arg.status.status = GP_PLAYING; - strcpy(req.arg.status.statusString, "Loading"); - sprintf(req.arg.status.locationString, "%s", WideCharStringToMultiByte(TheGameSpyGame->getGameName().str()).c_str()); - TheGameSpyBuddyMessageQueue->addRequest(req); - - if (TheNAT != NULL) { - delete TheNAT; - TheNAT = NULL; - } -} - -void GameSpyStagingRoom::reset(void) -{ -#ifdef DEBUG_LOGGING - if (this == TheGameSpyGame) - { - WindowLayout *theLayout = TheShell->findScreenByFilename("Menus/GameSpyGameOptionsMenu.wnd"); - if (theLayout) - { - DEBUG_LOG(("Resetting TheGameSpyGame on the game options menu!\n")); - } - } -#endif - GameInfo::reset(); -} diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/BuddyThread.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/BuddyThread.cpp deleted file mode 100644 index 410dbeed1db..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/BuddyThread.cpp +++ /dev/null @@ -1,681 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: BuddyThread.cpp ////////////////////////////////////////////////////// -// GameSpy Presence & Messaging (Buddy) thread -// This thread communicates with GameSpy's buddy server -// and talks through a message queue with the rest of -// the game. -// Author: Matthew D. Campbell, June 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpy/ThreadUtils.h" - -#include "Common/StackDump.h" - -#include "mutex.h" -#include "thread.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -//------------------------------------------------------------------------- - -typedef std::queue RequestQueue; -typedef std::queue ResponseQueue; -class BuddyThreadClass; - -class GameSpyBuddyMessageQueue : public GameSpyBuddyMessageQueueInterface -{ -public: - virtual ~GameSpyBuddyMessageQueue(); - GameSpyBuddyMessageQueue(); - virtual void startThread( void ); - virtual void endThread( void ); - virtual Bool isThreadRunning( void ); - virtual Bool isConnected( void ); - virtual Bool isConnecting( void ); - - virtual void addRequest( const BuddyRequest& req ); - virtual Bool getRequest( BuddyRequest& req ); - - virtual void addResponse( const BuddyResponse& resp ); - virtual Bool getResponse( BuddyResponse& resp ); - - virtual GPProfile getLocalProfileID( void ); - - BuddyThreadClass* getThread( void ); - -private: - MutexClass m_requestMutex; - MutexClass m_responseMutex; - RequestQueue m_requests; - ResponseQueue m_responses; - BuddyThreadClass *m_thread; -}; - -GameSpyBuddyMessageQueueInterface* GameSpyBuddyMessageQueueInterface::createNewMessageQueue( void ) -{ - return NEW GameSpyBuddyMessageQueue; -} - -GameSpyBuddyMessageQueueInterface *TheGameSpyBuddyMessageQueue; -#define MESSAGE_QUEUE ((GameSpyBuddyMessageQueue *)TheGameSpyBuddyMessageQueue) - -//------------------------------------------------------------------------- - -class BuddyThreadClass : public ThreadClass -{ - -public: - BuddyThreadClass() : ThreadClass() { m_isNewAccount = m_isdeleting = m_isConnecting = m_isConnected = false; m_profileID = 0; m_lastErrorCode = 0; } - - void Thread_Function(); - - void errorCallback( GPConnection *con, GPErrorArg *arg ); - void messageCallback( GPConnection *con, GPRecvBuddyMessageArg *arg ); - void connectCallback( GPConnection *con, GPConnectResponseArg *arg ); - void requestCallback( GPConnection *con, GPRecvBuddyRequestArg *arg ); - void statusCallback( GPConnection *con, GPRecvBuddyStatusArg *arg ); - - Bool isConnecting( void ) { return m_isConnecting; } - Bool isConnected( void ) { return m_isConnected; } - - GPProfile getLocalProfileID( void ) { return m_profileID; } - -private: - Bool m_isNewAccount; - Bool m_isConnecting; - Bool m_isConnected; - GPProfile m_profileID; - Int m_lastErrorCode; - Bool m_isdeleting; - std::string m_nick, m_email, m_pass; -}; - -static enum CallbackType -{ - CALLBACK_CONNECT, - CALLBACK_ERROR, - CALLBACK_RECVMESSAGE, - CALLBACK_RECVREQUEST, - CALLBACK_RECVSTATUS, - CALLBACK_MAX -}; - -void callbackWrapper( GPConnection *con, void *arg, void *param ) -{ - CallbackType info = (CallbackType)(Int)param; - BuddyThreadClass *thread = MESSAGE_QUEUE->getThread() ? MESSAGE_QUEUE->getThread() : NULL /*(TheGameSpyBuddyMessageQueue)?TheGameSpyBuddyMessageQueue->getThread():NULL*/; - if (!thread) - return; - - switch (info) - { - case CALLBACK_CONNECT: - thread->connectCallback( con, (GPConnectResponseArg *)arg ); - break; - case CALLBACK_ERROR: - thread->errorCallback( con, (GPErrorArg *)arg ); - break; - case CALLBACK_RECVMESSAGE: - thread->messageCallback( con, (GPRecvBuddyMessageArg *)arg ); - break; - case CALLBACK_RECVREQUEST: - thread->requestCallback( con, (GPRecvBuddyRequestArg *)arg ); - break; - case CALLBACK_RECVSTATUS: - thread->statusCallback( con, (GPRecvBuddyStatusArg *)arg ); - break; - } -} - -//------------------------------------------------------------------------- - -GameSpyBuddyMessageQueue::GameSpyBuddyMessageQueue() -{ - m_thread = NULL; -} - -GameSpyBuddyMessageQueue::~GameSpyBuddyMessageQueue() -{ - endThread(); -} - -void GameSpyBuddyMessageQueue::startThread( void ) -{ - if (!m_thread) - { - m_thread = NEW BuddyThreadClass; - m_thread->Execute(); - } - else - { - if (!m_thread->Is_Running()) - { - m_thread->Execute(); - } - } -} - -void GameSpyBuddyMessageQueue::endThread( void ) -{ - if (m_thread) - delete m_thread; - m_thread = NULL; -} - -Bool GameSpyBuddyMessageQueue::isThreadRunning( void ) -{ - return (m_thread) ? m_thread->Is_Running() : false; -} - -Bool GameSpyBuddyMessageQueue::isConnected( void ) -{ - return (m_thread) ? m_thread->isConnected() : false; -} - -Bool GameSpyBuddyMessageQueue::isConnecting( void ) -{ - return (m_thread) ? m_thread->isConnecting() : false; -} - -void GameSpyBuddyMessageQueue::addRequest( const BuddyRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex); - if (m.Failed()) - return; - - m_requests.push(req); -} - -Bool GameSpyBuddyMessageQueue::getRequest( BuddyRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex, 0); - if (m.Failed()) - return false; - - if (m_requests.empty()) - return false; - req = m_requests.front(); - m_requests.pop(); - return true; -} - -void GameSpyBuddyMessageQueue::addResponse( const BuddyResponse& resp ) -{ - MutexClass::LockClass m(m_responseMutex); - if (m.Failed()) - return; - - m_responses.push(resp); -} - -Bool GameSpyBuddyMessageQueue::getResponse( BuddyResponse& resp ) -{ - MutexClass::LockClass m(m_responseMutex, 0); - if (m.Failed()) - return false; - - if (m_responses.empty()) - return false; - resp = m_responses.front(); - m_responses.pop(); - return true; -} - -BuddyThreadClass* GameSpyBuddyMessageQueue::getThread( void ) -{ - return m_thread; -} - -GPProfile GameSpyBuddyMessageQueue::getLocalProfileID( void ) -{ - return (m_thread) ? m_thread->getLocalProfileID() : 0; -} - -//------------------------------------------------------------------------- - -void BuddyThreadClass::Thread_Function() -{ - try { - _set_se_translator( DumpExceptionInfo ); // Hook that allows stack trace. - GPConnection gpCon; - GPConnection *con = &gpCon; - gpInitialize( con, 675, 0, GP_PARTNERID_GAMESPY ); - m_isConnected = m_isConnecting = false; - - gpSetCallback( con, GP_ERROR, callbackWrapper, (void *)CALLBACK_ERROR ); - gpSetCallback( con, GP_RECV_BUDDY_MESSAGE, callbackWrapper, (void *)CALLBACK_RECVMESSAGE ); - gpSetCallback( con, GP_RECV_BUDDY_REQUEST, callbackWrapper, (void *)CALLBACK_RECVREQUEST ); - gpSetCallback( con, GP_RECV_BUDDY_STATUS, callbackWrapper, (void *)CALLBACK_RECVSTATUS ); - - GPEnum lastStatus = GP_OFFLINE; - std::string lastStatusString; - - BuddyRequest incomingRequest; - while ( running ) - { - // deal with requests - if (TheGameSpyBuddyMessageQueue->getRequest(incomingRequest)) - { - switch (incomingRequest.buddyRequestType) - { - case BuddyRequest::BUDDYREQUEST_LOGIN: - m_isConnecting = true; - m_nick = incomingRequest.arg.login.nick; - m_email = incomingRequest.arg.login.email; - m_pass = incomingRequest.arg.login.password; - m_isConnected = (gpConnect( con, incomingRequest.arg.login.nick, incomingRequest.arg.login.email, - incomingRequest.arg.login.password, (incomingRequest.arg.login.hasFirewall)?GP_FIREWALL:GP_NO_FIREWALL, - GP_BLOCKING, callbackWrapper, (void *)CALLBACK_CONNECT ) == GP_NO_ERROR); - m_isConnecting = false; - break; - - case BuddyRequest::BUDDYREQUEST_RELOGIN: - m_isConnecting = true; - m_isConnected = (gpConnect( con, m_nick.c_str(), m_email.c_str(), m_pass.c_str(), GP_FIREWALL, - GP_BLOCKING, callbackWrapper, (void *)CALLBACK_CONNECT ) == GP_NO_ERROR); - m_isConnecting = false; - break; - case BuddyRequest::BUDDYREQUEST_DELETEACCT: - m_isdeleting = true; - // TheSuperHackers @tweak OmniBlade API was updated since Generals released to require a callback. Passing -1 will make our wrapper ignore this. - gpDeleteProfile( con, callbackWrapper, (void *)(-1) ); - break; - case BuddyRequest::BUDDYREQUEST_LOGOUT: - m_isConnecting = m_isConnected = false; - gpDisconnect( con ); - break; - case BuddyRequest::BUDDYREQUEST_MESSAGE: - { - std::string s = WideCharStringToMultiByte( incomingRequest.arg.message.text ); - DEBUG_LOG(("Sending a buddy message to %d [%s]\n", incomingRequest.arg.message.recipient, s.c_str())); - gpSendBuddyMessage( con, incomingRequest.arg.message.recipient, s.c_str() ); - } - break; - case BuddyRequest::BUDDYREQUEST_LOGINNEW: - { - m_isConnecting = true; - m_nick = incomingRequest.arg.login.nick; - m_email = incomingRequest.arg.login.email; - m_pass = incomingRequest.arg.login.password; - m_isNewAccount = TRUE; - // TheSuperHackers @tweak OmniBlade API was updated since Generals release to require uniquenick which is the same as nick and cdkey is an empty string here. - m_isConnected = (gpConnectNewUser( con, incomingRequest.arg.login.nick, incomingRequest.arg.login.nick, incomingRequest.arg.login.email, - incomingRequest.arg.login.password, "", (incomingRequest.arg.login.hasFirewall)?GP_FIREWALL:GP_NO_FIREWALL, - GP_BLOCKING, callbackWrapper, (void *)CALLBACK_CONNECT ) == GP_NO_ERROR); - if (m_isNewAccount) // if we didn't re-login - { - gpSetInfoMask( con, GP_MASK_NONE ); // don't share info - } - m_isConnecting = false; - } - break; - case BuddyRequest::BUDDYREQUEST_ADDBUDDY: - { - std::string s = WideCharStringToMultiByte( incomingRequest.arg.addbuddy.text ); - gpSendBuddyRequest( con, incomingRequest.arg.addbuddy.id, s.c_str() ); - } - break; - case BuddyRequest::BUDDYREQUEST_DELBUDDY: - { - gpDeleteBuddy( con, incomingRequest.arg.profile.id ); - } - break; - case BuddyRequest::BUDDYREQUEST_OKADD: - { - gpAuthBuddyRequest( con, incomingRequest.arg.profile.id ); - } - break; - case BuddyRequest::BUDDYREQUEST_DENYADD: - { - gpDenyBuddyRequest( con, incomingRequest.arg.profile.id ); - } - case BuddyRequest::BUDDYREQUEST_SETSTATUS: - { - //don't blast our 'Loading' status with 'Online'. - if (lastStatus == GP_PLAYING && lastStatusString == "Loading" && incomingRequest.arg.status.status == GP_ONLINE) - break; - - DEBUG_LOG(("BUDDYREQUEST_SETSTATUS: status is now %d:%s/%s\n", - incomingRequest.arg.status.status, incomingRequest.arg.status.statusString, incomingRequest.arg.status.locationString)); - gpSetStatus( con, incomingRequest.arg.status.status, incomingRequest.arg.status.statusString, - incomingRequest.arg.status.locationString ); - lastStatus = incomingRequest.arg.status.status; - lastStatusString = incomingRequest.arg.status.statusString; - } - break; - } - } - - // update the network - GPEnum isConnected = GP_CONNECTED; - GPResult res = GP_NO_ERROR; - res = gpIsConnected( con, &isConnected ); - if ( isConnected == GP_CONNECTED && res == GP_NO_ERROR ) - gpProcess( con ); - - // end our timeslice - Switch_Thread(); - } - - gpDestroy( con ); - } catch ( ... ) { - DEBUG_CRASH(("Exception in buddy thread!")); - } -} - -void BuddyThreadClass::errorCallback( GPConnection *con, GPErrorArg *arg ) -{ - // log the error - DEBUG_LOG(("GPErrorCallback\n")); - m_lastErrorCode = arg->errorCode; - - char errorCodeString[256]; - char resultString[256]; - - #define RESULT(x) case x: strcpy(resultString, #x); break; - switch(arg->result) - { - RESULT(GP_NO_ERROR) - RESULT(GP_MEMORY_ERROR) - RESULT(GP_PARAMETER_ERROR) - RESULT(GP_NETWORK_ERROR) - RESULT(GP_SERVER_ERROR) - default: - strcpy(resultString, "Unknown result!"); - } - #undef RESULT - - #define ERRORCODE(x) case x: strcpy(errorCodeString, #x); break; - switch(arg->errorCode) - { - ERRORCODE(GP_GENERAL) - ERRORCODE(GP_PARSE) - ERRORCODE(GP_NOT_LOGGED_IN) - ERRORCODE(GP_BAD_SESSKEY) - ERRORCODE(GP_DATABASE) - ERRORCODE(GP_NETWORK) - ERRORCODE(GP_FORCED_DISCONNECT) - ERRORCODE(GP_CONNECTION_CLOSED) - ERRORCODE(GP_LOGIN) - ERRORCODE(GP_LOGIN_TIMEOUT) - ERRORCODE(GP_LOGIN_BAD_NICK) - ERRORCODE(GP_LOGIN_BAD_EMAIL) - ERRORCODE(GP_LOGIN_BAD_PASSWORD) - ERRORCODE(GP_LOGIN_BAD_PROFILE) - ERRORCODE(GP_LOGIN_PROFILE_DELETED) - ERRORCODE(GP_LOGIN_CONNECTION_FAILED) - ERRORCODE(GP_LOGIN_SERVER_AUTH_FAILED) - ERRORCODE(GP_NEWUSER) - ERRORCODE(GP_NEWUSER_BAD_NICK) - ERRORCODE(GP_NEWUSER_BAD_PASSWORD) - ERRORCODE(GP_UPDATEUI) - ERRORCODE(GP_UPDATEUI_BAD_EMAIL) - ERRORCODE(GP_NEWPROFILE) - ERRORCODE(GP_NEWPROFILE_BAD_NICK) - ERRORCODE(GP_NEWPROFILE_BAD_OLD_NICK) - ERRORCODE(GP_UPDATEPRO) - ERRORCODE(GP_UPDATEPRO_BAD_NICK) - ERRORCODE(GP_ADDBUDDY) - ERRORCODE(GP_ADDBUDDY_BAD_FROM) - ERRORCODE(GP_ADDBUDDY_BAD_NEW) - ERRORCODE(GP_ADDBUDDY_ALREADY_BUDDY) - ERRORCODE(GP_AUTHADD) - ERRORCODE(GP_AUTHADD_BAD_FROM) - ERRORCODE(GP_AUTHADD_BAD_SIG) - ERRORCODE(GP_STATUS) - ERRORCODE(GP_BM) - ERRORCODE(GP_BM_NOT_BUDDY) - ERRORCODE(GP_GETPROFILE) - ERRORCODE(GP_GETPROFILE_BAD_PROFILE) - ERRORCODE(GP_DELBUDDY) - ERRORCODE(GP_DELBUDDY_NOT_BUDDY) - ERRORCODE(GP_DELPROFILE) - ERRORCODE(GP_DELPROFILE_LAST_PROFILE) - ERRORCODE(GP_SEARCH) - ERRORCODE(GP_SEARCH_CONNECTION_FAILED) - default: - strcpy(errorCodeString, "Unknown error code!"); - } - #undef ERRORCODE - - if(arg->fatal) - { - DEBUG_LOG(( "-----------\n")); - DEBUG_LOG(( "GP FATAL ERROR\n")); - DEBUG_LOG(( "-----------\n")); - } - else - { - DEBUG_LOG(( "-----\n")); - DEBUG_LOG(( "GP ERROR\n")); - DEBUG_LOG(( "-----\n")); - } - DEBUG_LOG(( "RESULT: %s (%d)\n", resultString, arg->result)); - DEBUG_LOG(( "ERROR CODE: %s (0x%X)\n", errorCodeString, arg->errorCode)); - DEBUG_LOG(( "ERROR STRING: %s\n", arg->errorString)); - - if (arg->fatal == GP_FATAL) - { - BuddyResponse errorResponse; - errorResponse.buddyResponseType = BuddyResponse::BUDDYRESPONSE_DISCONNECT; - errorResponse.result = arg->result; - errorResponse.arg.error.errorCode = arg->errorCode; - errorResponse.arg.error.fatal = arg->fatal; - strncpy(errorResponse.arg.error.errorString, arg->errorString, MAX_BUDDY_CHAT_LEN); - errorResponse.arg.error.errorString[MAX_BUDDY_CHAT_LEN-1] = 0; - m_isConnecting = m_isConnected = false; - TheGameSpyBuddyMessageQueue->addResponse( errorResponse ); - if (m_isdeleting) - { - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_LOGOUT; - TheGameSpyPeerMessageQueue->addRequest( req ); - m_isdeleting = false; - } - } -} - -static void getNickForMessage( GPConnection *con, GPGetInfoResponseArg *arg, void *param ) -{ - BuddyResponse *resp = (BuddyResponse *)param; - strcpy(resp->arg.message.nick, arg->nick); -} - -void BuddyThreadClass::messageCallback( GPConnection *con, GPRecvBuddyMessageArg *arg ) -{ - BuddyResponse messageResponse; - messageResponse.buddyResponseType = BuddyResponse::BUDDYRESPONSE_MESSAGE; - messageResponse.profile = arg->profile; - - // get info about the person asking to be our buddy - gpGetInfo( con, arg->profile, GP_CHECK_CACHE, GP_BLOCKING, (GPCallback)getNickForMessage, &messageResponse); - - std::wstring s = MultiByteToWideCharSingleLine( arg->message ); - wcsncpy(messageResponse.arg.message.text, s.c_str(), MAX_BUDDY_CHAT_LEN); - messageResponse.arg.message.text[MAX_BUDDY_CHAT_LEN-1] = 0; - messageResponse.arg.message.date = arg->date; - DEBUG_LOG(("Got a buddy message from %d [%ls]\n", arg->profile, s.c_str())); - TheGameSpyBuddyMessageQueue->addResponse( messageResponse ); -} - -void BuddyThreadClass::connectCallback( GPConnection *con, GPConnectResponseArg *arg ) -{ - BuddyResponse loginResponse; - if (arg->result == GP_NO_ERROR) - { - loginResponse.buddyResponseType = BuddyResponse::BUDDYRESPONSE_LOGIN; - loginResponse.result = arg->result; - loginResponse.profile = arg->profile; - TheGameSpyBuddyMessageQueue->addResponse( loginResponse ); - m_profileID = arg->profile; - - if (!TheGameSpyPeerMessageQueue->isConnected() && !TheGameSpyPeerMessageQueue->isConnecting()) - { - DEBUG_LOG(("Buddy connect: trying chat connect\n")); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_LOGIN; - req.nick = m_nick; - req.password = m_pass; - req.email = m_email; - req.login.profileID = arg->profile; - TheGameSpyPeerMessageQueue->addRequest(req); - } - } - else - { - if (!TheGameSpyPeerMessageQueue->isConnected() && !TheGameSpyPeerMessageQueue->isConnecting()) - { - if (m_lastErrorCode == GP_NEWUSER_BAD_NICK) - { - m_isNewAccount = FALSE; - // they just hit 'create account' instead of 'log in'. Fix them. - DEBUG_LOG(("User Error: Create Account instead of Login. Fixing them...\n")); - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_LOGIN; - strcpy(req.arg.login.nick, m_nick.c_str()); - strcpy(req.arg.login.email, m_email.c_str()); - strcpy(req.arg.login.password, m_pass.c_str()); - req.arg.login.hasFirewall = true; - TheGameSpyBuddyMessageQueue->addRequest( req ); - return; - } - DEBUG_LOG(("Buddy connect failed (%d/%d): posting a failed chat connect\n", arg->result, m_lastErrorCode)); - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT; - resp.discon.reason = DISCONNECT_COULDNOTCONNECT; - switch (m_lastErrorCode) - { - case GP_LOGIN_TIMEOUT: - resp.discon.reason = DISCONNECT_GP_LOGIN_TIMEOUT; - break; - case GP_LOGIN_BAD_NICK: - resp.discon.reason = DISCONNECT_GP_LOGIN_BAD_NICK; - break; - case GP_LOGIN_BAD_EMAIL: - resp.discon.reason = DISCONNECT_GP_LOGIN_BAD_EMAIL; - break; - case GP_LOGIN_BAD_PASSWORD: - resp.discon.reason = DISCONNECT_GP_LOGIN_BAD_PASSWORD; - break; - case GP_LOGIN_BAD_PROFILE: - resp.discon.reason = DISCONNECT_GP_LOGIN_BAD_PROFILE; - break; - case GP_LOGIN_PROFILE_DELETED: - resp.discon.reason = DISCONNECT_GP_LOGIN_PROFILE_DELETED; - break; - case GP_LOGIN_CONNECTION_FAILED: - resp.discon.reason = DISCONNECT_GP_LOGIN_CONNECTION_FAILED; - break; - case GP_LOGIN_SERVER_AUTH_FAILED: - resp.discon.reason = DISCONNECT_GP_LOGIN_SERVER_AUTH_FAILED; - break; - case GP_NEWUSER_BAD_NICK: - resp.discon.reason = DISCONNECT_GP_NEWUSER_BAD_NICK; - break; - case GP_NEWUSER_BAD_PASSWORD: - resp.discon.reason = DISCONNECT_GP_NEWUSER_BAD_PASSWORD; - break; - case GP_NEWPROFILE_BAD_NICK: - resp.discon.reason = DISCONNECT_GP_NEWPROFILE_BAD_NICK; - break; - case GP_NEWPROFILE_BAD_OLD_NICK: - resp.discon.reason = DISCONNECT_GP_NEWPROFILE_BAD_OLD_NICK; - break; - } - TheGameSpyPeerMessageQueue->addResponse(resp); - } - } -} - -// ----------------------- - -static void getInfoResponseForRequest( GPConnection *con, GPGetInfoResponseArg *arg, void *param ) -{ - BuddyResponse *resp = (BuddyResponse *)param; - resp->profile = arg->profile; - strcpy(resp->arg.request.nick, arg->nick); - strcpy(resp->arg.request.email, arg->email); - strcpy(resp->arg.request.countrycode, arg->countrycode); -} - -void BuddyThreadClass::requestCallback( GPConnection *con, GPRecvBuddyRequestArg *arg ) -{ - BuddyResponse response; - response.buddyResponseType = BuddyResponse::BUDDYRESPONSE_REQUEST; - response.profile = arg->profile; - - // get info about the person asking to be our buddy - gpGetInfo( con, arg->profile, GP_CHECK_CACHE, GP_BLOCKING, (GPCallback)getInfoResponseForRequest, &response); - - std::wstring s = MultiByteToWideCharSingleLine( arg->reason ); - wcsncpy(response.arg.request.text, s.c_str(), GP_REASON_LEN); - response.arg.request.text[GP_REASON_LEN-1] = 0; - - TheGameSpyBuddyMessageQueue->addResponse( response ); -} - -// ----------------------- - -static void getInfoResponseForStatus(GPConnection * connection, GPGetInfoResponseArg * arg, void * param) -{ - BuddyResponse *resp = (BuddyResponse *)param; - resp->profile = arg->profile; - strcpy(resp->arg.status.nick, arg->nick); - strcpy(resp->arg.status.email, arg->email); - strcpy(resp->arg.status.countrycode, arg->countrycode); -} - -void BuddyThreadClass::statusCallback( GPConnection *con, GPRecvBuddyStatusArg *arg ) -{ - BuddyResponse response; - - // get user's name - response.buddyResponseType = BuddyResponse::BUDDYRESPONSE_STATUS; - gpGetInfo( con, arg->profile, GP_CHECK_CACHE, GP_BLOCKING, (GPCallback)getInfoResponseForStatus, &response); - - // get user's status - GPBuddyStatus status; - gpGetBuddyStatus( con, arg->index, &status ); - strcpy(response.arg.status.location, status.locationString); - strcpy(response.arg.status.statusString, status.statusString); - response.arg.status.status = status.status; - DEBUG_LOG(("Got buddy status for %d(%s) - status %d\n", status.profile, response.arg.status.nick, status.status)); - - // relay to UI - TheGameSpyBuddyMessageQueue->addResponse( response ); -} - - -//------------------------------------------------------------------------- - diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/GameResultsThread.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/GameResultsThread.cpp deleted file mode 100644 index 5b857727fe9..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/GameResultsThread.cpp +++ /dev/null @@ -1,410 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PingThread.cpp ////////////////////////////////////////////////////// -// Ping thread -// Author: Matthew D. Campbell, August 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include // This one has to be here. Prevents collisions with winsock2.h - -#include "GameNetwork/GameSpy/GameResultsThread.h" -#include "mutex.h" -#include "thread.h" - -#include "Common/StackDump.h" -#include "Common/SubsystemInterface.h" - -//------------------------------------------------------------------------- - -static const Int NumWorkerThreads = 1; - -typedef std::queue RequestQueue; -typedef std::queue ResponseQueue; -class GameResultsThreadClass; - -class GameResultsQueue : public GameResultsInterface -{ -public: - virtual ~GameResultsQueue(); - GameResultsQueue(); - - virtual void init() {} - virtual void reset() {} - virtual void update() {} - - virtual void startThreads( void ); - virtual void endThreads( void ); - virtual Bool areThreadsRunning( void ); - - virtual void addRequest( const GameResultsRequest& req ); - virtual Bool getRequest( GameResultsRequest& resp ); - - virtual void addResponse( const GameResultsResponse& resp ); - virtual Bool getResponse( GameResultsResponse& resp ); - - virtual Bool areGameResultsBeingSent( void ); - -private: - MutexClass m_requestMutex; - MutexClass m_responseMutex; - RequestQueue m_requests; - ResponseQueue m_responses; - Int m_requestCount; - Int m_responseCount; - - GameResultsThreadClass *m_workerThreads[NumWorkerThreads]; -}; - -GameResultsInterface* GameResultsInterface::createNewGameResultsInterface( void ) -{ - return NEW GameResultsQueue; -} - -GameResultsInterface *TheGameResultsQueue; - -//------------------------------------------------------------------------- - -class GameResultsThreadClass : public ThreadClass -{ - -public: - GameResultsThreadClass() : ThreadClass() {} - - void Thread_Function(); - -private: - Int sendGameResults( UnsignedInt IP, UnsignedShort port, const std::string& results ); -}; - - -//------------------------------------------------------------------------- - -GameResultsQueue::GameResultsQueue() : m_requestCount(0), m_responseCount(0) -{ - for (Int i=0; iExecute(); - } -} - -void GameResultsQueue::endThreads( void ) -{ - for (Int i=0; iIs_Running()) - return true; - } - } - return false; -} - -void GameResultsQueue::addRequest( const GameResultsRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex); - - ++m_requestCount; - m_requests.push(req); -} - -Bool GameResultsQueue::getRequest( GameResultsRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex, 0); - if (m.Failed()) - return false; - - if (m_requests.empty()) - return false; - req = m_requests.front(); - m_requests.pop(); - return true; -} - -void GameResultsQueue::addResponse( const GameResultsResponse& resp ) -{ - { - MutexClass::LockClass m(m_responseMutex); - - ++m_responseCount; - m_responses.push(resp); - } -} - -Bool GameResultsQueue::getResponse( GameResultsResponse& resp ) -{ - MutexClass::LockClass m(m_responseMutex, 0); - if (m.Failed()) - return false; - - if (m_responses.empty()) - return false; - resp = m_responses.front(); - m_responses.pop(); - return true; -} - -Bool GameResultsQueue::areGameResultsBeingSent( void ) -{ - MutexClass::LockClass m(m_requestMutex, 0); - if (m.Failed()) - return true; - - return m_requestCount > 0; -} - - -//------------------------------------------------------------------------- -// Wrap ladder results in HTTP POST -static WrapHTTP( const std::string& hostname, std::string& results ) -{ - const char HEADER[] = - "PUT / HTTP/1.1\r\n" - "Connection: Close\r\n" - "Host: %s\r\n" - "Content-Length: %d\r\n" - "\r\n"; - - char szHdr[256] = {0}; - _snprintf( szHdr, 255, HEADER, hostname.c_str(), results.length() ); - results = szHdr + results; -} //WrapHTTP - - -//------------------------------------------------------------------------- - -void GameResultsThreadClass::Thread_Function() -{ - try { - _set_se_translator( DumpExceptionInfo ); // Hook that allows stack trace. - GameResultsRequest req; - - WSADATA wsaData; - - // Fire up winsock (prob already done, but doesn't matter) - WORD wVersionRequested = MAKEWORD(1, 1); - WSAStartup( wVersionRequested, &wsaData ); - - while ( running ) - { - // deal with requests - if (TheGameResultsQueue && TheGameResultsQueue->getRequest(req)) - { - // resolve the hostname - const char *hostnameBuffer = req.hostname.c_str(); - UnsignedInt IP = 0xFFFFFFFF; - if (isdigit(hostnameBuffer[0])) - { - IP = inet_addr(hostnameBuffer); - in_addr hostNode; - hostNode.s_addr = IP; - DEBUG_LOG(("sending game results to %s - IP = %s\n", hostnameBuffer, inet_ntoa(hostNode) )); - } - else - { - HOSTENT *hostStruct; - in_addr *hostNode; - hostStruct = gethostbyname(hostnameBuffer); - if (hostStruct == NULL) - { - DEBUG_LOG(("sending game results to %s - host lookup failed\n", hostnameBuffer)); - - // Even though this failed to resolve IP, still need to send a - // callback. - IP = 0xFFFFFFFF; // flag for IP resolve failed - } - hostNode = (in_addr *) hostStruct->h_addr; - IP = hostNode->s_addr; - DEBUG_LOG(("sending game results to %s IP = %s\n", hostnameBuffer, inet_ntoa(*hostNode) )); - } - - int result = sendGameResults( IP, req.port, req.results ); - GameResultsResponse resp; - resp.hostname = req.hostname; - resp.port = req.port; - resp.sentOk = (result == req.results.length()); - - } - - // end our timeslice - Switch_Thread(); - } - - WSACleanup(); - } catch ( ... ) { - DEBUG_CRASH(("Exception in results thread!")); - } -} - -//------------------------------------------------------------------------- - -#define CASE(x) case (x): return #x; - -static const char *getWSAErrorString( Int error ) -{ - switch (error) - { - CASE(WSABASEERR) - CASE(WSAEINTR) - CASE(WSAEBADF) - CASE(WSAEACCES) - CASE(WSAEFAULT) - CASE(WSAEINVAL) - CASE(WSAEMFILE) - CASE(WSAEWOULDBLOCK) - CASE(WSAEINPROGRESS) - CASE(WSAEALREADY) - CASE(WSAENOTSOCK) - CASE(WSAEDESTADDRREQ) - CASE(WSAEMSGSIZE) - CASE(WSAEPROTOTYPE) - CASE(WSAENOPROTOOPT) - CASE(WSAEPROTONOSUPPORT) - CASE(WSAESOCKTNOSUPPORT) - CASE(WSAEOPNOTSUPP) - CASE(WSAEPFNOSUPPORT) - CASE(WSAEAFNOSUPPORT) - CASE(WSAEADDRINUSE) - CASE(WSAEADDRNOTAVAIL) - CASE(WSAENETDOWN) - CASE(WSAENETUNREACH) - CASE(WSAENETRESET) - CASE(WSAECONNABORTED) - CASE(WSAECONNRESET) - CASE(WSAENOBUFS) - CASE(WSAEISCONN) - CASE(WSAENOTCONN) - CASE(WSAESHUTDOWN) - CASE(WSAETOOMANYREFS) - CASE(WSAETIMEDOUT) - CASE(WSAECONNREFUSED) - CASE(WSAELOOP) - CASE(WSAENAMETOOLONG) - CASE(WSAEHOSTDOWN) - CASE(WSAEHOSTUNREACH) - CASE(WSAENOTEMPTY) - CASE(WSAEPROCLIM) - CASE(WSAEUSERS) - CASE(WSAEDQUOT) - CASE(WSAESTALE) - CASE(WSAEREMOTE) - CASE(WSAEDISCON) - CASE(WSASYSNOTREADY) - CASE(WSAVERNOTSUPPORTED) - CASE(WSANOTINITIALISED) - CASE(WSAHOST_NOT_FOUND) - CASE(WSATRY_AGAIN) - CASE(WSANO_RECOVERY) - CASE(WSANO_DATA) - default: - return "Not a Winsock error"; - } -} - -#undef CASE - -//------------------------------------------------------------------------- - -Int GameResultsThreadClass::sendGameResults( UnsignedInt IP, UnsignedShort port, const std::string& results ) -{ - int error = 0; - - // create the socket - Int sock = socket( AF_INET, SOCK_STREAM, 0 ); - if (sock < 0) - { - DEBUG_LOG(("GameResultsThreadClass::sendGameResults() - socket() returned %d(%s)\n", sock, getWSAErrorString(sock))); - return sock; - } - - // fill in address info - struct sockaddr_in sockAddr; - memset( &sockAddr, 0, sizeof( sockAddr ) ); - sockAddr.sin_family = AF_INET; - sockAddr.sin_addr.s_addr = IP; - sockAddr.sin_port = htons(port); - - // Start the connection process.... - if( connect( sock, (struct sockaddr *)&sockAddr, sizeof( sockAddr ) ) == -1 ) - { - error = WSAGetLastError(); - DEBUG_LOG(("GameResultsThreadClass::sendGameResults() - connect() returned %d(%s)\n", error, getWSAErrorString(error))); - if( ( error == WSAEWOULDBLOCK ) || ( error == WSAEINVAL ) || ( error == WSAEALREADY ) ) - { - return( -1 ); - } - - if( error != WSAEISCONN ) - { - closesocket( sock ); - return( -1 ); - } - } - - if (send( sock, results.c_str(), results.length(), 0 ) == SOCKET_ERROR) - { - error = WSAGetLastError(); - DEBUG_LOG(("GameResultsThreadClass::sendGameResults() - send() returned %d(%s)\n", error, getWSAErrorString(error))); - closesocket(sock); - return WSAGetLastError(); - } - - closesocket(sock); - - return results.length(); -} - - -//------------------------------------------------------------------------- diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PeerThread.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PeerThread.cpp deleted file mode 100644 index 28e6785d6a8..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PeerThread.cpp +++ /dev/null @@ -1,2966 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PeerThread.cpp ////////////////////////////////////////////////////// -// GameSpy Peer (chat) thread -// This thread communicates with GameSpy's chat server -// and talks through a message queue with the rest of -// the game. -// Author: Matthew D. Campbell, June 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/Registry.h" -#include "Common/StackDump.h" -#include "Common/UserPreferences.h" -#include "Common/Version.h" -#include "GameNetwork/IPEnumeration.h" -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpy/ThreadUtils.h" - -#include "strtok_r.h" -#include "mutex.h" -#include "thread.h" - -#include "Common/MiniLog.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -// enable this for trying to track down why SBServers are losing their keyvals -MDC 2/20/2003 -#undef SERVER_DEBUGGING -#ifdef SERVER_DEBUGGING -void CheckServers(PEER peer); -#endif // SERVER_DEBUGGING - -#ifdef DEBUG_LOGGING -//#define PING_TEST -static LogClass s_pingLog("Ping.txt"); -#define PING_LOG(x) s_pingLog.log x -#else // DEBUG_LOGGING -#define PING_LOG(x) {} -#endif // DEBUG_LOGGING - -#ifdef DEBUG_LOGGING -static LogClass s_stateChangedLog("StateChanged.txt"); - -#define STATECHANGED_LOG(x) s_stateChangedLog.log x - -#else // DEBUG_LOGGING - -#define STATECHANGED_LOG(x) {} - -#endif // DEBUG_LOGGING - -// we should always be using broadcast keys from now on. Remove the old code sometime when -// we're not in a rush, ok? -// -MDC 2/14/2003 -#define USE_BROADCAST_KEYS - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -int isThreadHosting = 0; -static UnsignedInt s_lastStateChangedHeartbeat = 0; -static Bool s_wantStateChangedHeartbeat = FALSE; -static UnsignedInt s_heartbeatInterval = 10000; - -static SOCKET qr2Sock = INVALID_SOCKET; - -enum -{ - EXECRC_KEY = NUM_RESERVED_KEYS + 1, - INICRC_KEY, - PW_KEY, - OBS_KEY, - LADIP_KEY, - LADPORT_KEY, - PINGSTR_KEY, - NUMPLAYER_KEY, - MAXPLAYER_KEY, - NUMOBS_KEY, - NAME__KEY, - FACTION__KEY, - COLOR__KEY, - WINS__KEY, - LOSSES__KEY -}; - -#define EXECRC_STR "exeCRC" -#define INICRC_STR "iniCRC" -#define PW_STR "pw" -#define OBS_STR "obs" -#define LADIP_STR "ladIP" -#define LADPORT_STR "ladPort" -#define PINGSTR_STR "pings" -#define NUMPLAYER_STR "numRealPlayers" -#define MAXPLAYER_STR "maxRealPlayers" -#define NUMOBS_STR "numObservers" -#define NAME__STR "name" -#define FACTION__STR "faction" -#define COLOR__STR "color" -#define WINS__STR "wins" -#define LOSSES__STR "losses" - -//------------------------------------------------------------------------- - -typedef std::queue RequestQueue; -typedef std::queue ResponseQueue; -class PeerThreadClass; - -class GameSpyPeerMessageQueue : public GameSpyPeerMessageQueueInterface -{ -public: - virtual ~GameSpyPeerMessageQueue(); - GameSpyPeerMessageQueue(); - virtual void startThread( void ); - virtual void endThread( void ); - virtual Bool isThreadRunning( void ); - virtual Bool isConnected( void ); - virtual Bool isConnecting( void ); - - virtual void addRequest( const PeerRequest& req ); - virtual Bool getRequest( PeerRequest& req ); - - virtual void addResponse( const PeerResponse& resp ); - virtual Bool getResponse( PeerResponse& resp ); - - virtual SerialAuthResult getSerialAuthResult( void ) { return m_serialAuth; } - void setSerialAuthResult( SerialAuthResult result ) { m_serialAuth = result; } - - PeerThreadClass* getThread( void ); - -private: - MutexClass m_requestMutex; - MutexClass m_responseMutex; - RequestQueue m_requests; - ResponseQueue m_responses; - PeerThreadClass *m_thread; - - SerialAuthResult m_serialAuth; -}; - -GameSpyPeerMessageQueueInterface* GameSpyPeerMessageQueueInterface::createNewMessageQueue( void ) -{ - return NEW GameSpyPeerMessageQueue; -} - -GameSpyPeerMessageQueueInterface *TheGameSpyPeerMessageQueue; -#define MESSAGE_QUEUE ((GameSpyPeerMessageQueue *)TheGameSpyPeerMessageQueue) - -//------------------------------------------------------------------------- - -class PeerThreadClass : public ThreadClass -{ - -public: - PeerThreadClass() : ThreadClass() - { - //Added By Sadullah Nader - //Initializations inserted - m_roomJoined = m_allowObservers = m_hasPassword = FALSE; - m_exeCRC = m_iniCRC = 0; - m_gameVersion = 0; - m_ladderPort = 0; - m_localRoomID = 0; - m_maxPlayers = 0; - m_numObservers = 0; - m_maxPlayers = 0; - m_qmGroupRoom = 0; - m_sawEndOfEnumPlayers = m_sawMatchbot = FALSE; - m_sawCompleteGameList = FALSE; - // - m_isConnecting = m_isConnected = false; - m_groupRoomID = m_profileID = 0; - m_nextStagingServer = 1; m_stagingServers.clear(); - m_pingStr = ""; m_mapName = ""; m_ladderIP = ""; m_isHosting = false; - for (Int i=0; i PlayerStatMap; - PlayerStatMap m_groupRoomStats; - PlayerStatMap m_stagingRoomStats; - std::string packStatKey(const char *nick, const char *key); -#endif // USE_BROADCAST_KEYS - - // game-hosting info for GOA callbacks - Bool m_isHosting; - Bool m_hasPassword; - std::string m_mapName; - std::string m_playerNames[MAX_SLOTS]; - UnsignedInt m_exeCRC; - UnsignedInt m_iniCRC; - UnsignedInt m_gameVersion; - Bool m_allowObservers; - std::string m_pingStr; - std::string m_ladderIP; - UnsignedShort m_ladderPort; - Int m_playerWins[MAX_SLOTS]; - Int m_playerLosses[MAX_SLOTS]; - Int m_playerProfileID[MAX_SLOTS]; - Int m_playerColors[MAX_SLOTS]; - Int m_playerFactions[MAX_SLOTS]; - Int m_numPlayers; - Int m_maxPlayers; - Int m_numObservers; - - Int m_nextStagingServer; - std::map m_stagingServers; - std::wstring m_localStagingServerName; - Int m_localRoomID; - - void doQuickMatch( PEER peer ); - QMStatus m_qmStatus; - PeerRequest m_qmInfo; - Bool m_roomJoined; - Int m_qmGroupRoom; - Bool m_sawEndOfEnumPlayers; - Bool m_sawMatchbot; - std::string m_matchbotName; -}; - -#ifdef USE_BROADCAST_KEYS -const char* PeerThreadClass::s_keys[6] = { "b_locale", "b_wins", "b_losses", "b_points", "b_side", "b_pre" }; -char PeerThreadClass::s_valueBuffers[6][20] = { "", "", "", "", "", "" }; -const char* PeerThreadClass::s_values[6] = { s_valueBuffers[0], s_valueBuffers[1], s_valueBuffers[2], - s_valueBuffers[3], s_valueBuffers[4], s_valueBuffers[5]}; - -void PeerThreadClass::trackStatsForPlayer(RoomType roomType, const char *nick, const char *key, const char *val) -{ - switch (roomType) - { - case GroupRoom: - m_groupRoomStats[packStatKey(nick, key)] = atoi(val); - break; - case StagingRoom: - m_stagingRoomStats[packStatKey(nick, key)] = atoi(val); - break; - } -} - -std::string PeerThreadClass::packStatKey(const char *nick, const char *key) -{ - std::string s = nick; - s.append(key); - return s; -} - -int PeerThreadClass::lookupStatForPlayer(RoomType roomType, const char *nick, const char *key) -{ - std::string fullKey = packStatKey(nick, key); - PlayerStatMap::const_iterator it; - switch (roomType) - { - case GroupRoom: - it = m_groupRoomStats.find(fullKey); - if (it != m_groupRoomStats.end()) - return it->second; - break; - case StagingRoom: - it = m_stagingRoomStats.find(fullKey); - if (it != m_stagingRoomStats.end()) - return it->second; - break; - } - return 0; -} - -void PeerThreadClass::clearPlayerStats(RoomType roomType) -{ - switch (roomType) - { - case GroupRoom: - m_groupRoomStats.clear(); - break; - case StagingRoom: - m_stagingRoomStats.clear(); - break; - } -} - -void PeerThreadClass::pushStatsToRoom(PEER peer) -{ - DEBUG_LOG(("PeerThreadClass::pushStatsToRoom(): stats are %s=%s,%s=%s,%s=%s,%s=%s,%s=%s,%s=%s\n", - s_keys[0], s_values[0], - s_keys[1], s_values[1], - s_keys[2], s_values[2], - s_keys[3], s_values[3], - s_keys[4], s_values[4], - s_keys[5], s_values[5])); - peerSetRoomKeys(peer, GroupRoom, m_loginName.c_str(), 6, s_keys, s_values); - peerSetRoomKeys(peer, StagingRoom, m_loginName.c_str(), 6, s_keys, s_values); -} - -void getRoomKeysCallback(PEER peer, PEERBool success, RoomType roomType, const char *nick, int num, char **keys, char **values, void *param); -void PeerThreadClass::getStatsFromRoom(PEER peer, RoomType roomType) -{ - peerGetRoomKeys(peer, GroupRoom, "*", NumKeys, s_keys, getRoomKeysCallback, this, PEERFalse); -} -#endif // USE_BROADCAST_KEYS - -Int PeerThreadClass::addServerToMap( SBServer server ) -{ - Int val = m_nextStagingServer++; - m_stagingServers[val] = server; - return val; -} - -Int PeerThreadClass::removeServerFromMap( SBServer server ) -{ - for (std::map::iterator it = m_stagingServers.begin(); it != m_stagingServers.end(); ++it) - { - if (it->second == server) - { - Int val = it->first; - m_stagingServers.erase(it); - return val; - } - } - - return 0; -} - -void PeerThreadClass::clearServers( void ) -{ - m_stagingServers.clear(); -} - -SBServer PeerThreadClass::findServerByID( Int id ) -{ - std::map::iterator it = m_stagingServers.find(id); - if (it != m_stagingServers.end()) - { - SBServer server = it->second; - if (server && !server->keyvals) - { - DEBUG_CRASH(("Referencing a missing server!")); - return 0; - } - return it->second; - } - return 0; -} - -Int PeerThreadClass::findServer( SBServer server ) -{ - char tmp[10] = ""; - const char *newName = SBServerGetStringValue(server, "gamename", tmp); - UnsignedInt newPrivateIP = SBServerGetPrivateInetAddress(server); - UnsignedShort newPrivatePort = SBServerGetPrivateQueryPort(server); - UnsignedInt newPublicIP = SBServerGetPublicInetAddress(server); - - SBServer serverToRemove = NULL; - - for (std::map::iterator it = m_stagingServers.begin(); it != m_stagingServers.end(); ++it) - { - if (it->second == server) - { - return it->first; - } - else - { - const char *oldName = SBServerGetStringValue(it->second, "gamename", tmp); - UnsignedInt oldPrivateIP = SBServerGetPrivateInetAddress(it->second); - UnsignedShort oldPrivatePort = SBServerGetPrivateQueryPort(it->second); - UnsignedInt oldPublicIP = SBServerGetPublicInetAddress(it->second); - if (!strcmp(oldName, newName) && - oldPrivateIP == newPrivateIP && - oldPublicIP == newPublicIP && - oldPrivatePort == newPrivatePort) - { - serverToRemove = it->second; - } - } - } - - if (serverToRemove) - { - // this is the same as another game - it has just migrated to another port. Remove the old and replace it. - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_STAGINGROOM; - resp.stagingRoom.id = removeServerFromMap( serverToRemove ); - resp.stagingRoom.action = PEER_REMOVE; - resp.stagingRoom.isStaging = TRUE; - resp.stagingRoom.percentComplete = -1; - TheGameSpyPeerMessageQueue->addResponse(resp); - } - - return addServerToMap(server); -} - -static enum CallbackType -{ - CALLBACK_CONNECT, - CALLBACK_ERROR, - CALLBACK_RECVMESSAGE, - CALLBACK_RECVREQUEST, - CALLBACK_RECVSTATUS, - CALLBACK_MAX -}; - -void connectCallbackWrapper( PEER peer, PEERBool success, int failureReason, void *param ) -{ -#ifdef SERVER_DEBUGGING - DEBUG_LOG(("In connectCallbackWrapper()\n")); - CheckServers(peer); -#endif // SERVER_DEBUGGING - if (param != NULL) - { - ((PeerThreadClass *)param)->connectCallback( peer, success ); - } -} - -void nickErrorCallbackWrapper( PEER peer, Int type, const char *nick, int numSuggestedNicks, const gsi_char** suggestedNicks, void *param ) -{ - if (param != NULL) - { - ((PeerThreadClass *)param)->nickErrorCallback( peer, type, nick ); - } -} - -static void joinRoomCallback(PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, void *param); - -//------------------------------------------------------------------------- - -GameSpyPeerMessageQueue::GameSpyPeerMessageQueue() -{ - m_thread = NULL; - m_serialAuth = SERIAL_OK; -} - -GameSpyPeerMessageQueue::~GameSpyPeerMessageQueue() -{ - endThread(); -} - -void GameSpyPeerMessageQueue::startThread( void ) -{ - if (!m_thread) - { - m_thread = NEW PeerThreadClass; - m_thread->Execute(); - } - else - { - if (!m_thread->Is_Running()) - { - m_thread->Execute(); - } - } -} - -void GameSpyPeerMessageQueue::endThread( void ) -{ - if (m_thread) - delete m_thread; - m_thread = NULL; -} - -Bool GameSpyPeerMessageQueue::isThreadRunning( void ) -{ - return (m_thread) ? m_thread->Is_Running() : false; -} - -Bool GameSpyPeerMessageQueue::isConnected( void ) -{ - return (m_thread) ? m_thread->isConnected() : false; -} - -Bool GameSpyPeerMessageQueue::isConnecting( void ) -{ - return (m_thread) ? m_thread->isConnecting() : false; -} - -void GameSpyPeerMessageQueue::addRequest( const PeerRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex); - if (m.Failed()) - return; - - m_requests.push(req); -} - -//PeerRequest GameSpyPeerMessageQueue::getRequest( void ) -Bool GameSpyPeerMessageQueue::getRequest( PeerRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex, 0); - if (m.Failed()) - return false; - - if (m_requests.empty()) - return false; - req = m_requests.front(); - m_requests.pop(); - return true; -} - -void GameSpyPeerMessageQueue::addResponse( const PeerResponse& resp ) -{ - if (resp.nick == "(END)") - return; - - MutexClass::LockClass m(m_responseMutex); - if (m.Failed()) - return; - - m_responses.push(resp); -} - -//PeerResponse GameSpyPeerMessageQueue::getResponse( void ) -Bool GameSpyPeerMessageQueue::getResponse( PeerResponse& resp ) -{ - MutexClass::LockClass m(m_responseMutex, 0); - if (m.Failed()) - return false; - - if (m_responses.empty()) - return false; - resp = m_responses.front(); - m_responses.pop(); - return true; -} - -PeerThreadClass* GameSpyPeerMessageQueue::getThread( void ) -{ - return m_thread; -} - -//------------------------------------------------------------------------- -static void disconnectedCallback(PEER peer, const char * reason, void * param); -static void roomMessageCallback(PEER peer, RoomType roomType, const char * nick, const char * message, MessageType messageType, void * param); -static void playerMessageCallback(PEER peer, const char * nick, const char * message, MessageType messageType, void * param); -static void playerJoinedCallback(PEER peer, RoomType roomType, const char * nick, void * param); -static void playerLeftCallback(PEER peer, RoomType roomType, const char * nick, const char * reason, void * param); -static void playerChangedNickCallback(PEER peer, RoomType roomType, const char * oldNick, const char * newNick, void * param); -static void playerInfoCallback(PEER peer, RoomType roomType, const char * nick, unsigned int IP, int profileID, void * param); -static void playerFlagsChangedCallback(PEER peer, RoomType roomType, const char * nick, int oldFlags, int newFlags, void * param); -static void listingGamesCallback(PEER peer, PEERBool success, const char * name, SBServer server, PEERBool staging, int msg, Int percentListed, void * param); -static void roomUTMCallback(PEER peer, RoomType roomType, const char * nick, const char * command, const char * parameters, PEERBool authenticated, void * param); -static void playerUTMCallback(PEER peer, const char * nick, const char * command, const char * parameters, PEERBool authenticated, void * param); -static void gameStartedCallback(PEER peer, SBServer server, const char *message, void *param); -static void globalKeyChangedCallback(PEER peer, const char *nick, const char *key, const char *val, void *param); -static void roomKeyChangedCallback(PEER peer, RoomType roomType, const char *nick, const char *key, const char *val, void *param); - -// convenience function to set buddy status -static void updateBuddyStatus( GameSpyBuddyStatus status, Int groupRoom = 0, std::string gameName = "" ) -{ - if (!TheGameSpyBuddyMessageQueue) - return; - - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_SETSTATUS; - switch(status) - { - case BUDDY_OFFLINE: - req.arg.status.status = GP_OFFLINE; - strcpy(req.arg.status.statusString, "Offline"); - strcpy(req.arg.status.locationString, ""); - break; - case BUDDY_ONLINE: - req.arg.status.status = GP_ONLINE; - strcpy(req.arg.status.statusString, "Online"); - strcpy(req.arg.status.locationString, ""); - break; - case BUDDY_LOBBY: - req.arg.status.status = GP_CHATTING; - strcpy(req.arg.status.statusString, "Chatting"); - sprintf(req.arg.status.locationString, "%d", groupRoom); - break; - case BUDDY_STAGING: - req.arg.status.status = GP_STAGING; - strcpy(req.arg.status.statusString, "Staging"); - sprintf(req.arg.status.locationString, "%s", gameName.c_str()); - break; - case BUDDY_LOADING: - req.arg.status.status = GP_PLAYING; - strcpy(req.arg.status.statusString, "Loading"); - sprintf(req.arg.status.locationString, "%s", gameName.c_str()); - break; - case BUDDY_PLAYING: - req.arg.status.status = GP_PLAYING; - strcpy(req.arg.status.statusString, "Playing"); - sprintf(req.arg.status.locationString, "%s", gameName.c_str()); - break; - case BUDDY_MATCHING: - req.arg.status.status = GP_ONLINE; - strcpy(req.arg.status.statusString, "Matching"); - strcpy(req.arg.status.locationString, ""); - break; - } - DEBUG_LOG(("updateBuddyStatus %d:%s\n", req.arg.status.status, req.arg.status.statusString)); - TheGameSpyBuddyMessageQueue->addRequest(req); -} - -static void createRoomCallback(PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, void *param) -{ - Int *s = (Int *)param; - if (s) - *s = result; -} - -static const char * KeyTypeToString(qr2_key_type type) -{ - switch(type) - { - case key_server: - return "server"; - case key_player: - return "player"; - case key_team: - return "team"; - } - - return "Unkown key type"; -} - -static const char * ErrorTypeToString(qr2_error_t error) -{ - switch(error) - { - case e_qrnoerror: - return "noerror"; - case e_qrwsockerror: - return "wsockerror"; - case e_qrbinderror: - return "rbinderror"; - case e_qrdnserror: - return "dnserror"; - case e_qrconnerror: - return "connerror"; - } - - return "Unknown error type"; -} - -static void QRServerKeyCallback -( - PEER peer, - int key, - qr2_buffer_t buffer, - void * param -) -{ - //DEBUG_LOG(("QR_SERVER_KEY | %d (%s)\n", key, qr2_registered_key_list[key])); - PeerThreadClass *t = (PeerThreadClass *)param; - if (!t) - { - DEBUG_LOG(("QRServerKeyCallback: bailing because of no thread info\n")); - return; - } - - if (!t->isHosting()) - t->stopHostingAlready(peer); - -#ifdef DEBUG_LOGGING - AsciiString val = ""; -#define ADD(x) { qr2_buffer_add(buffer, x); val = x; } -#define ADDINT(x) { qr2_buffer_add_int(buffer, x); val.format("%d",x); } -#else -#define ADD(x) { qr2_buffer_add(buffer, x); } -#define ADDINT(x) { qr2_buffer_add_int(buffer, x); } -#endif - - switch(key) - { - case HOSTNAME_KEY: - ADD(t->getPlayerName(0).c_str()); - break; - case GAMEVER_KEY: - ADDINT(t->gameVersion()); - break; - case EXECRC_KEY: - ADDINT(t->exeCRC()); - break; - case INICRC_KEY: - ADDINT(t->iniCRC()); - break; - case GAMENAME_KEY: - { - std::string tmp = t->getPlayerName(0); - tmp.append(" "); - tmp.append(WideCharStringToMultiByte(t->getLocalStagingServerName().c_str())); - ADD(tmp.c_str()); - } - break; - case MAPNAME_KEY: - ADD(t->getMapName().c_str()); - break; - case PW_KEY: - ADDINT(t->hasPassword()); - break; - case OBS_KEY: - ADDINT(t->allowObservers()); - break; - case LADIP_KEY: - ADD(t->ladderIP().c_str()); - break; - case LADPORT_KEY: - ADDINT(t->ladderPort()); - break; - case PINGSTR_KEY: - ADD(t->pingStr().c_str()); - break; - case NUMPLAYER_KEY: - ADDINT(t->getNumPlayers()); - break; - case MAXPLAYER_KEY: - ADDINT(t->getMaxPlayers()); - break; - case NUMOBS_KEY: - ADDINT(t->getNumObservers()); - break; - default: - ADD(""); - //DEBUG_LOG(("QR_SERVER_KEY | %d (%s)\n", key, qr2_registered_key_list[key])); - break; - } - - DEBUG_LOG(("QR_SERVER_KEY | %d (%s) = [%s]\n", key, qr2_registered_key_list[key], val.str())); -} - -static void QRPlayerKeyCallback -( - PEER peer, - int key, - int index, - qr2_buffer_t buffer, - void * param -) -{ - //DEBUG_LOG(("QR_PLAYER_KEY | %d | %d (%s)\n", key, index, qr2_registered_key_list[key])); - PeerThreadClass *t = (PeerThreadClass *)param; - if (!t) - { - DEBUG_LOG(("QRPlayerKeyCallback: bailing because of no thread info\n")); - return; - } - - if (!t->isHosting()) - t->stopHostingAlready(peer); - -#undef ADD -#undef ADDINT -#ifdef DEBUG_LOGGING - AsciiString val = ""; -#define ADD(x) { qr2_buffer_add(buffer, x); val = x; } -#define ADDINT(x) { qr2_buffer_add_int(buffer, x); val.format("%d",x); } -#else -#define ADD(x) { qr2_buffer_add(buffer, x); } -#define ADDINT(x) { qr2_buffer_add_int(buffer, x); } -#endif - - switch(key) - { - case NAME__KEY: - ADD(t->getPlayerName(index).c_str()); - break; - case WINS__KEY: - ADDINT(t->getPlayerWins(index)); - break; - case LOSSES__KEY: - ADDINT(t->getPlayerLosses(index)); - break; - case PID__KEY: - ADDINT(t->getPlayerProfileID(index)); - break; - case FACTION__KEY: - ADDINT(t->getPlayerLosses(index)); - break; - case COLOR__KEY: - ADDINT(t->getPlayerLosses(index)); - break; - default: - ADD(""); - //DEBUG_LOG(("QR_PLAYER_KEY | %d | %d (%s)\n", key, index, qr2_registered_key_list[key])); - break; - } - - DEBUG_LOG(("QR_PLAYER_KEY | %d | %d (%s) = [%s]\n", key, index, qr2_registered_key_list[key], val.str())); -} - -static void QRTeamKeyCallback -( - PEER peer, - int key, - int index, - qr2_buffer_t buffer, - void * param -) -{ - //DEBUG_LOG(("QR_TEAM_KEY | %d | %d\n", key, index)); - - PeerThreadClass *t = (PeerThreadClass *)param; - if (!t) - { - DEBUG_LOG(("QRTeamKeyCallback: bailing because of no thread info\n")); - return; - } - if (!t->isHosting()) - t->stopHostingAlready(peer); - - // we don't report teams, so this shouldn't get called - qr2_buffer_add(buffer, ""); -} - -static void QRKeyListCallback -( - PEER peer, - qr2_key_type type, - qr2_keybuffer_t keyBuffer, - void * param -) -{ - DEBUG_LOG(("QR_KEY_LIST | %s\n", KeyTypeToString(type))); - - /* - PeerThreadClass *t = (PeerThreadClass *)param; - if (!t) - { - DEBUG_LOG(("QRKeyListCallback: bailing because of no thread info\n")); - return; - } - if (!t->isHosting()) - t->stopHostingAlready(peer); - */ - - // register the keys we use - switch(type) - { - case key_server: - qr2_keybuffer_add(keyBuffer, HOSTNAME_KEY); - qr2_keybuffer_add(keyBuffer, GAMEVER_KEY); - //qr2_keybuffer_add(keyBuffer, GAMENAME_KEY); - qr2_keybuffer_add(keyBuffer, MAPNAME_KEY); - qr2_keybuffer_add(keyBuffer, EXECRC_KEY); - qr2_keybuffer_add(keyBuffer, INICRC_KEY); - qr2_keybuffer_add(keyBuffer, PW_KEY); - qr2_keybuffer_add(keyBuffer, OBS_KEY); - qr2_keybuffer_add(keyBuffer, LADIP_KEY); - qr2_keybuffer_add(keyBuffer, LADPORT_KEY); - qr2_keybuffer_add(keyBuffer, PINGSTR_KEY); - qr2_keybuffer_add(keyBuffer, NUMPLAYER_KEY); - qr2_keybuffer_add(keyBuffer, MAXPLAYER_KEY); - qr2_keybuffer_add(keyBuffer, NUMOBS_KEY); - break; - case key_player: - qr2_keybuffer_add(keyBuffer, NAME__KEY); - qr2_keybuffer_add(keyBuffer, WINS__KEY); - qr2_keybuffer_add(keyBuffer, LOSSES__KEY); - qr2_keybuffer_add(keyBuffer, PID__KEY); - qr2_keybuffer_add(keyBuffer, FACTION__KEY); - qr2_keybuffer_add(keyBuffer, COLOR__KEY); - break; - case key_team: - // no custom team keys - break; - } -} - -static int QRCountCallback -( - PEER peer, - qr2_key_type type, - void * param -) -{ - PeerThreadClass *t = (PeerThreadClass *)param; - if (!t) - { - DEBUG_LOG(("QRCountCallback: bailing because of no thread info\n")); - return 0; - } - if (!t->isHosting()) - t->stopHostingAlready(peer); - - if(type == key_player) - { - DEBUG_LOG(("QR_COUNT | %s = %d\n", KeyTypeToString(type), t->getNumPlayers() + t->getNumObservers())); - return t->getNumPlayers() + t->getNumObservers(); - } - else if(type == key_team) - { - DEBUG_LOG(("QR_COUNT | %s = %d\n", KeyTypeToString(type), 0)); - return 0; - } - - DEBUG_LOG(("QR_COUNT | %s = %d\n", KeyTypeToString(type), 0)); - return 0; -} - -void PeerThreadClass::stopHostingAlready(PEER peer) -{ - isThreadHosting = 0; // debugging - s_lastStateChangedHeartbeat = 0; - s_wantStateChangedHeartbeat = FALSE; - peerStopGame(peer); - if (qr2Sock != INVALID_SOCKET) - { - closesocket(qr2Sock); - qr2Sock = INVALID_SOCKET; - } -} - -static void QRAddErrorCallback -( - PEER peer, - qr2_error_t error, - char * errorString, - void * param -) -{ - DEBUG_LOG(("QR_ADD_ERROR | %s | %s\n", ErrorTypeToString(error), errorString)); - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_FAILEDTOHOST; - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -static void QRNatNegotiateCallback -( - PEER peer, - int cookie, - void * param -) -{ - DEBUG_LOG(("QR_NAT_NEGOTIATE | 0x%08X\n", cookie)); -} - -static void KickedCallback -( - PEER peer, - RoomType roomType, - const char * nick, - const char * reason, - void * param -) -{ - DEBUG_LOG(("Kicked from %d by %s: \"%s\"\n", roomType, nick, reason)); -} - -static void NewPlayerListCallback -( - PEER peer, - RoomType roomType, - void * param -) -{ - DEBUG_LOG(("NewPlayerListCallback\n")); -} - -static void AuthenticateCDKeyCallback -( - PEER peer, - int result, - const char * message, - void * param -) -{ - DEBUG_LOG(("CD Key Result: %s (%d) %X\n", message, result, param)); -#ifdef SERVER_DEBUGGING - CheckServers(peer); -#endif // SERVER_DEBUGGING - SerialAuthResult *val = (SerialAuthResult *)param; - if (val) - { - if (result >= 1) - { - *val = SERIAL_OK; - } - else - { - *val = SERIAL_AUTHFAILED; - } - } -#ifdef SERVER_DEBUGGING - CheckServers(peer); -#endif // SERVER_DEBUGGING -} - -static SerialAuthResult doCDKeyAuthentication( PEER peer ) -{ - SerialAuthResult retval = SERIAL_NONEXISTENT; - if (!peer) - return retval; - - AsciiString s = ""; - if (GetStringFromRegistry("\\ergc", "", s) && s.isNotEmpty()) - { -#ifdef SERVER_DEBUGGING - DEBUG_LOG(("Before peerAuthenticateCDKey()\n")); - CheckServers(peer); -#endif // SERVER_DEBUGGING - peerAuthenticateCDKey(peer, s.str(), AuthenticateCDKeyCallback, &retval, PEERTrue); -#ifdef SERVER_DEBUGGING - DEBUG_LOG(("After peerAuthenticateCDKey()\n")); - CheckServers(peer); -#endif // SERVER_DEBUGGING - } - - if (retval == SERIAL_OK) - { - PSRequest req; - req.requestType = PSRequest::PSREQUEST_READCDKEYSTATS; - req.cdkey = s.str(); - TheGameSpyPSMessageQueue->addRequest(req); - } - - return retval; -} - -#define INBUF_LEN 256 -void checkQR2Queries( PEER peer, SOCKET sock ) -{ - static char indata[INBUF_LEN]; - struct sockaddr_in saddr; - int saddrlen = sizeof(struct sockaddr_in); - fd_set set; - struct timeval timeout = {0,0}; - int error; - - FD_ZERO ( &set ); - FD_SET ( sock, &set ); - - while (1) - { - error = select(FD_SETSIZE, &set, NULL, NULL, &timeout); - if (SOCKET_ERROR == error || 0 == error) - return; - //else we have data - error = recvfrom(sock, indata, INBUF_LEN - 1, 0, (struct sockaddr *)&saddr, &saddrlen); - if (error != SOCKET_ERROR) - { - indata[error] = '\0'; - peerParseQuery( peer, indata, error, (sockaddr *)&saddr ); - } - } -} - -static UnsignedInt localIP = 0; - -void PeerThreadClass::Thread_Function() -{ - try { - _set_se_translator( DumpExceptionInfo ); // Hook that allows stack trace. - - PEER peer; - - // Setup the callbacks. - /////////////////////// - PEERCallbacks callbacks; - memset(&callbacks, 0, sizeof(PEERCallbacks)); - callbacks.disconnected = disconnectedCallback; - //callbacks.readyChanged = readyChangedCallback; - callbacks.roomMessage = roomMessageCallback; - callbacks.playerMessage = playerMessageCallback; - callbacks.gameStarted = gameStartedCallback; - callbacks.playerJoined = playerJoinedCallback; - callbacks.playerLeft = playerLeftCallback; - callbacks.playerChangedNick = playerChangedNickCallback; - callbacks.playerFlagsChanged = playerFlagsChangedCallback; - callbacks.playerInfo = playerInfoCallback; - callbacks.roomUTM = roomUTMCallback; - callbacks.playerUTM = playerUTMCallback; - callbacks.globalKeyChanged = globalKeyChangedCallback; - callbacks.roomKeyChanged = roomKeyChangedCallback; - - callbacks.qrServerKey = QRServerKeyCallback; - callbacks.qrPlayerKey = QRPlayerKeyCallback; - callbacks.qrTeamKey = QRTeamKeyCallback; - callbacks.qrKeyList = QRKeyListCallback; - callbacks.qrCount = QRCountCallback; - callbacks.qrAddError = QRAddErrorCallback; - callbacks.qrNatNegotiateCallback = QRNatNegotiateCallback; - - callbacks.kicked = KickedCallback; - callbacks.newPlayerList = NewPlayerListCallback; - - callbacks.param = this; - - m_qmGroupRoom = 0; - - peer = peerInitialize( &callbacks ); - DEBUG_ASSERTCRASH( peer != NULL, ("NULL peer!") ); - m_isConnected = m_isConnecting = false; - - qr2_register_key(EXECRC_KEY, EXECRC_STR); - qr2_register_key(INICRC_KEY, INICRC_STR); - qr2_register_key(PW_KEY, PW_STR); - qr2_register_key(OBS_KEY, OBS_STR); - qr2_register_key(LADIP_KEY, LADIP_STR); - qr2_register_key(LADPORT_KEY, LADPORT_STR); - qr2_register_key(PINGSTR_KEY, PINGSTR_STR); - qr2_register_key(NUMOBS_KEY, NUMOBS_STR); - qr2_register_key(NUMPLAYER_KEY, NUMPLAYER_STR); - qr2_register_key(MAXPLAYER_KEY, MAXPLAYER_STR); - qr2_register_key(NAME__KEY, NAME__STR "_"); - qr2_register_key(WINS__KEY, WINS__STR "_"); - qr2_register_key(LOSSES__KEY, LOSSES__STR "_"); - qr2_register_key(FACTION__KEY, FACTION__STR "_"); - qr2_register_key(COLOR__KEY, COLOR__STR "_"); - - const Int NumKeys = 14; - unsigned char allKeysArray[NumKeys] = { - /* - PID__KEY, - NAME__KEY, - WINS__KEY, - LOSSES__KEY, - FACTION__KEY, - COLOR__KEY, - */ - MAPNAME_KEY, - GAMEVER_KEY, - GAMENAME_KEY, - EXECRC_KEY, - INICRC_KEY, - PW_KEY, - OBS_KEY, - LADIP_KEY, - LADPORT_KEY, - PINGSTR_KEY, - NUMOBS_KEY, - NUMPLAYER_KEY, - MAXPLAYER_KEY, - HOSTNAME_KEY - }; - - /* - const char *allKeys = "\\pid_\\mapname\\gamever\\gamename" \ - "\\" EXECRC_STR "\\" INICRC_STR \ - "\\" PW_STR "\\" OBS_STR "\\" LADIP_STR "\\" LADPORT_STR \ - "\\" PINGSTR_STR "\\" NUMOBS_STR \ - "\\" NUMPLAYER_STR "\\" MAXPLAYER_STR \ - "\\" NAME__STR "_" "\\" WINS__STR "_" "\\" LOSSES__STR "_" "\\" FACTION__STR "_" "\\" COLOR__STR "_"; - */ - - const char * key = "username"; - peerSetRoomWatchKeys(peer, StagingRoom, 1, &key, PEERTrue); - peerSetRoomWatchKeys(peer, GroupRoom, 1, &key, PEERTrue); - - m_localRoomID = 0; - m_localStagingServerName = L""; - - m_qmStatus = QM_IDLE; - - // Setup which rooms to do pings and cross-pings in. - //////////////////////////////////////////////////// - PEERBool pingRooms[NumRooms]; - PEERBool crossPingRooms[NumRooms]; - pingRooms[TitleRoom] = PEERFalse; - pingRooms[GroupRoom] = PEERFalse; - pingRooms[StagingRoom] = PEERFalse; - crossPingRooms[TitleRoom] = PEERFalse; - crossPingRooms[GroupRoom] = PEERFalse; - crossPingRooms[StagingRoom] = PEERFalse; - - /********* - First step, set our game authentication info - We could do: - strcpy(gcd_gamename,"ccgenerals"); - strcpy(gcd_secret_key,"h5T2f6"); - or - strcpy(gcd_gamename,"ccgeneralsb"); - strcpy(gcd_secret_key,"g3T9s2"); - ...but this is more secure: - **********/ - char gameName[12]; - char secretKey[7]; - /** - gameName[0]='c';gameName[1]='c';gameName[2]='g';gameName[3]='e'; - gameName[4]='n';gameName[5]='e';gameName[6]='r';gameName[7]='a'; - gameName[8]='l';gameName[9]='s';gameName[10]='b';gameName[11]='\0'; - secretKey[0]='g';secretKey[1]='3';secretKey[2]='T';secretKey[3]='9'; - secretKey[4]='s';secretKey[5]='2';secretKey[6]='\0'; - /**/ - gameName[0]='c';gameName[1]='c';gameName[2]='g';gameName[3]='e'; - gameName[4]='n';gameName[5]='e';gameName[6]='r';gameName[7]='a'; - gameName[8]='l';gameName[9]='s';gameName[10]='\0'; - secretKey[0]='h';secretKey[1]='5';secretKey[2]='T';secretKey[3]='2'; - secretKey[4]='f';secretKey[5]='6';secretKey[6]='\0'; - /**/ - - // Set the title. - ///////////////// - if(!peerSetTitle( peer , gameName, secretKey, gameName, secretKey, GetRegistryVersion(), 30, PEERTrue, pingRooms, crossPingRooms)) - { - DEBUG_CRASH(("Error setting title")); - peerShutdown( peer ); - peer = NULL; - return; - } - - OptionPreferences pref; - UnsignedInt preferredIP = INADDR_ANY; - UnsignedInt selectedIP = pref.getOnlineIPAddress(); - DEBUG_LOG(("Looking for IP %X\n", selectedIP)); - IPEnumeration IPs; - EnumeratedIP *IPlist = IPs.getAddresses(); - while (IPlist) - { - DEBUG_LOG(("Looking at IP %s\n", IPlist->getIPstring().str())); - if (selectedIP == IPlist->getIP()) - { - preferredIP = IPlist->getIP(); - DEBUG_LOG(("Connecting to GameSpy chat server via IP address %8.8X\n", preferredIP)); - break; - } - IPlist = IPlist->getNext(); - } - //chatSetLocalIP(preferredIP); - - UnsignedInt preferredQRPort = 0; - AsciiString selectedQRPort = pref["GameSpyQRPort"]; - if (selectedQRPort.isNotEmpty()) - { - preferredQRPort = atoi(selectedQRPort.str()); - } - - PeerRequest incomingRequest; - while ( running ) - { - // deal with requests - if (TheGameSpyPeerMessageQueue->getRequest(incomingRequest)) - { - DEBUG_LOG(("TheGameSpyPeerMessageQueue->getRequest() got request of type %d\n", incomingRequest.peerRequestType)); - switch (incomingRequest.peerRequestType) - { - case PeerRequest::PEERREQUEST_LOGIN: - { - m_isConnecting = true; - m_originalName = incomingRequest.nick; - m_loginName = incomingRequest.nick; - m_profileID = incomingRequest.login.profileID; - m_password = incomingRequest.password; - m_email = incomingRequest.email; - peerConnect( peer, incomingRequest.nick.c_str(), incomingRequest.login.profileID, nickErrorCallbackWrapper, connectCallbackWrapper, this, PEERTrue ); -#ifdef SERVER_DEBUGGING - DEBUG_LOG(("After peerConnect()\n")); - CheckServers(peer); -#endif // SERVER_DEBUGGING - if (m_isConnected) - { - SerialAuthResult ret = doCDKeyAuthentication( peer ); - if (ret != SERIAL_OK) - { - m_isConnecting = m_isConnected = false; - MESSAGE_QUEUE->setSerialAuthResult( ret ); - peerDisconnect( peer ); - } - } - m_isConnecting = false; - - // check our connection - //if (m_isConnected) - //{ - // GetLocalChatConnectionAddress("peerchat.gamespy.com", 6667, localIP); - //} - } - - break; - - case PeerRequest::PEERREQUEST_LOGOUT: - m_isConnecting = m_isConnected = false; - peerDisconnect( peer ); - break; - - case PeerRequest::PEERREQUEST_JOINGROUPROOM: - m_groupRoomID = incomingRequest.groupRoom.id; - isThreadHosting = 0; // debugging - s_lastStateChangedHeartbeat = 0; - s_wantStateChangedHeartbeat = FALSE; - peerStopGame( peer ); - peerLeaveRoom( peer, GroupRoom, NULL ); - peerLeaveRoom( peer, StagingRoom, NULL ); - if (qr2Sock != INVALID_SOCKET) - { - closesocket(qr2Sock); - qr2Sock = INVALID_SOCKET; - } - m_isHosting = false; - m_localRoomID = m_groupRoomID; - DEBUG_LOG(("Requesting to join room %d in thread %X\n", m_localRoomID, this)); - peerJoinGroupRoom( peer, incomingRequest.groupRoom.id, joinRoomCallback, (void *)this, PEERTrue ); - break; - - case PeerRequest::PEERREQUEST_LEAVEGROUPROOM: - m_groupRoomID = 0; - updateBuddyStatus( BUDDY_ONLINE ); - peerLeaveRoom( peer, GroupRoom, NULL ); - peerLeaveRoom( peer, StagingRoom, NULL ); m_isHosting = false; - break; - - case PeerRequest::PEERREQUEST_JOINSTAGINGROOM: - { - m_groupRoomID = 0; - updateBuddyStatus( BUDDY_ONLINE ); - peerLeaveRoom( peer, GroupRoom, NULL ); - peerLeaveRoom( peer, StagingRoom, NULL ); m_isHosting = false; - SBServer server = findServerByID(incomingRequest.stagingRoom.id); - m_localStagingServerName = incomingRequest.text; - DEBUG_LOG(("Setting m_localStagingServerName to [%ls]\n", m_localStagingServerName.c_str())); - m_localRoomID = incomingRequest.stagingRoom.id; - DEBUG_LOG(("Requesting to join room %d\n", m_localRoomID)); - if (server) - { - peerJoinStagingRoom( peer, server, incomingRequest.password.c_str(), joinRoomCallback, (void *)this, PEERTrue ); - } - else - { - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_JOINSTAGINGROOM; - resp.joinStagingRoom.id = incomingRequest.stagingRoom.id; - resp.joinStagingRoom.ok = FALSE; - resp.joinStagingRoom.result = PEERJoinFailed; - TheGameSpyPeerMessageQueue->addResponse(resp); - } - } - break; - - case PeerRequest::PEERREQUEST_LEAVESTAGINGROOM: - m_groupRoomID = 0; - updateBuddyStatus( BUDDY_ONLINE ); - peerLeaveRoom( peer, GroupRoom, NULL ); - peerLeaveRoom( peer, StagingRoom, NULL ); - isThreadHosting = 0; // debugging - s_lastStateChangedHeartbeat = 0; - s_wantStateChangedHeartbeat = FALSE; - if (m_isHosting) - { - peerStopGame( peer ); - if (qr2Sock != INVALID_SOCKET) - { - closesocket(qr2Sock); - qr2Sock = INVALID_SOCKET; - } - m_isHosting = false; - } - break; - - case PeerRequest::PEERREQUEST_MESSAGEPLAYER: - { - std::string s = WideCharStringToMultiByte(incomingRequest.text.c_str()); - peerMessagePlayer( peer, incomingRequest.nick.c_str(), s.c_str(), (incomingRequest.message.isAction)?ActionMessage:NormalMessage ); - } - break; - - case PeerRequest::PEERREQUEST_MESSAGEROOM: - { - std::string s = WideCharStringToMultiByte(incomingRequest.text.c_str()); - peerMessageRoom( peer, (m_groupRoomID)?GroupRoom:StagingRoom, s.c_str(), (incomingRequest.message.isAction)?ActionMessage:NormalMessage ); - } - break; - - case PeerRequest::PEERREQUEST_PUSHSTATS: - { - DEBUG_LOG(("PEERREQUEST_PUSHSTATS: stats are %d,%d,%d,%d,%d,%d\n", - incomingRequest.statsToPush.locale, incomingRequest.statsToPush.wins, incomingRequest.statsToPush.losses, incomingRequest.statsToPush.rankPoints, incomingRequest.statsToPush.side, incomingRequest.statsToPush.preorder)); - - // Testing alternate way to push stats -#ifdef USE_BROADCAST_KEYS - _snprintf(s_valueBuffers[0], 20, "%d", incomingRequest.statsToPush.locale); - _snprintf(s_valueBuffers[1], 20, "%d", incomingRequest.statsToPush.wins); - _snprintf(s_valueBuffers[2], 20, "%d", incomingRequest.statsToPush.losses); - _snprintf(s_valueBuffers[3], 20, "%d", incomingRequest.statsToPush.rankPoints); - _snprintf(s_valueBuffers[4], 20, "%d", incomingRequest.statsToPush.side); - _snprintf(s_valueBuffers[5], 20, "%d", incomingRequest.statsToPush.preorder); - pushStatsToRoom(peer); -#else - const char *keys[6] = { "locale", "wins", "losses", "points", "side", "pre" }; - char valueStrings[6][20]; - char *values[6] = { valueStrings[0], valueStrings[1], valueStrings[2], - valueStrings[3], valueStrings[4], valueStrings[5]}; - _snprintf(values[0], 20, "%d", incomingRequest.statsToPush.locale); - _snprintf(values[1], 20, "%d", incomingRequest.statsToPush.wins); - _snprintf(values[2], 20, "%d", incomingRequest.statsToPush.losses); - _snprintf(values[3], 20, "%d", incomingRequest.statsToPush.rankPoints); - _snprintf(values[4], 20, "%d", incomingRequest.statsToPush.side); - _snprintf(values[5], 20, "%d", incomingRequest.statsToPush.preorder); - peerSetGlobalKeys(peer, 6, (const char **)keys, (const char **)values); - peerSetGlobalWatchKeys(peer, GroupRoom, 0, NULL, PEERFalse); - peerSetGlobalWatchKeys(peer, StagingRoom, 0, NULL, PEERFalse); - peerSetGlobalWatchKeys(peer, GroupRoom, 6, keys, PEERTrue); - peerSetGlobalWatchKeys(peer, StagingRoom, 6, keys, PEERTrue); -#endif - } - break; - - case PeerRequest::PEERREQUEST_SETGAMEOPTIONS: - { - m_mapName = incomingRequest.gameOptsMapName; - m_numPlayers = incomingRequest.gameOptions.numPlayers; - m_numObservers = incomingRequest.gameOptions.numObservers; - m_maxPlayers = incomingRequest.gameOptions.maxPlayers; - DEBUG_LOG(("peerStateChanged(): Marking game options state as changed - %d players, %d observers\n", m_numPlayers, m_numObservers)); - for (Int i=0; iaddResponse(resp); - - if (res != PEERJoinSuccess && res != PEERAlreadyInRoom) - { - m_localRoomID = oldGroupID; - DEBUG_LOG(("Requesting to join room %d\n", m_localRoomID)); - if (incomingRequest.stagingRoomCreation.restrictGameList) - { - peerLeaveRoom( peer, StagingRoom, NULL ); - } - else - { - peerJoinGroupRoom( peer, oldGroupID, joinRoomCallback, (void *)this, PEERTrue ); - } - m_isHosting = FALSE; - m_localStagingServerName = L""; - m_playerNames[0] = ""; - } - else - { - if (incomingRequest.stagingRoomCreation.restrictGameList) - { - peerLeaveRoom( peer, GroupRoom, NULL ); - } - isThreadHosting = 1; // debugging - s_lastStateChangedHeartbeat = timeGetTime(); // wait the full interval before updating state - s_wantStateChangedHeartbeat = FALSE; - m_isHosting = TRUE; - m_allowObservers = incomingRequest.stagingRoomCreation.allowObservers; - m_mapName = ""; - for (Int i=0; i 0) - m_hasPassword = true; - else - m_hasPassword = false; - m_playerNames[0] = m_loginName; - m_exeCRC = incomingRequest.stagingRoomCreation.exeCRC; - m_iniCRC = incomingRequest.stagingRoomCreation.iniCRC; - m_gameVersion = incomingRequest.stagingRoomCreation.gameVersion; - m_localStagingServerName = incomingRequest.text; - m_ladderIP = incomingRequest.ladderIP; - m_pingStr = incomingRequest.hostPingStr; - m_ladderPort = incomingRequest.stagingRoomCreation.ladPort; - -#ifdef USE_BROADCAST_KEYS - pushStatsToRoom(peer); -#endif // USE_BROADCAST_KEYS - - DEBUG_LOG(("Setting m_localStagingServerName to [%ls]\n", m_localStagingServerName.c_str())); - updateBuddyStatus( BUDDY_STAGING, 0, WideCharStringToMultiByte(m_localStagingServerName.c_str()) ); - } - } - break; - - case PeerRequest::PEERREQUEST_STARTGAMELIST: - { - m_sawCompleteGameList = FALSE; - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_STAGINGROOM; - resp.stagingRoom.action = PEER_CLEAR; - resp.stagingRoom.isStaging = TRUE; - resp.stagingRoom.percentComplete = 0; - clearServers(); - TheGameSpyPeerMessageQueue->addResponse(resp); - peerStartListingGames( peer, allKeysArray, NumKeys, (incomingRequest.gameList.restrictGameList?"~":NULL), listingGamesCallback, this ); - } - break; - - case PeerRequest::PEERREQUEST_STOPGAMELIST: - { - peerStopListingGames( peer ); - } - break; - - case PeerRequest::PEERREQUEST_STARTGAME: - { - peerStartGame( peer, NULL, PEER_STOP_REPORTING); - } - break; - - case PeerRequest::PEERREQUEST_UTMPLAYER: - { - if (incomingRequest.nick.length() > 0) - { - peerUTMPlayer( peer, incomingRequest.nick.c_str(), incomingRequest.id.c_str(), incomingRequest.options.c_str(), PEERFalse ); - } - } - break; - - case PeerRequest::PEERREQUEST_UTMROOM: - { - peerUTMRoom( peer, (incomingRequest.UTM.isStagingRoom)?StagingRoom:GroupRoom, incomingRequest.id.c_str(), incomingRequest.options.c_str(), PEERFalse ); - } - break; - - case PeerRequest::PEERREQUEST_STARTQUICKMATCH: - { - m_qmInfo = incomingRequest; - doQuickMatch( peer ); - } - break; - - } - } - - if (isThreadHosting && s_wantStateChangedHeartbeat) - { - UnsignedInt now = timeGetTime(); - if (now > s_lastStateChangedHeartbeat + s_heartbeatInterval) - { - s_lastStateChangedHeartbeat = now; - s_wantStateChangedHeartbeat = FALSE; - peerStateChanged( peer ); - -#ifdef DEBUG_LOGGING - static UnsignedInt prev = 0; - UnsignedInt now = timeGetTime(); - UnsignedInt diff = now - prev; - prev = now; -#endif - STATECHANGED_LOG(("peerStateChanged() at time %d (difference of %d ms)\n", now, diff)); - } - } - - // update the network - PEERBool isConnected = PEERTrue; - isConnected = peerIsConnected( peer ); - if ( isConnected == PEERTrue ) - { - if (qr2Sock != INVALID_SOCKET) - { - // check hosting activity - checkQR2Queries( peer, qr2Sock ); - } - peerThink( peer ); - } - - // end our timeslice - Switch_Thread(); - } - - DEBUG_LOG(("voluntarily ending peer thread %d\n", running)); - peerShutdown( peer ); - - } catch ( ... ) { - DEBUG_CRASH(("Exception in peer thread!")); - - try { - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT; - resp.discon.reason = DISCONNECT_LOSTCON; - TheGameSpyPeerMessageQueue->addResponse(resp); - } - catch (...) - { - } - } -} - -static void qmProfileIDCallback( PEER peer, PEERBool success, const char *nick, int profileID, void *param ) -{ - Int *i = (Int *)param; - if (!i || !success || !nick) - return; - - *i = profileID; -} - -static Int matchbotProfileID = 0; -void quickmatchEnumPlayersCallback( PEER peer, PEERBool success, RoomType roomType, int index, const char * nick, int flags, void * param ) -{ - PeerThreadClass *t = (PeerThreadClass *)param; - if (!t || !success || nick == NULL || nick[0] == '\0') - { - t->sawEndOfEnumPlayers(); - return; - } - - Int id = 0; - peerGetPlayerProfileID(peer, nick, qmProfileIDCallback, &id, PEERTrue); - DEBUG_LOG(("Saw player %s with id %d (looking for %d)\n", nick, id, matchbotProfileID)); - if (id == matchbotProfileID) - { - t->sawMatchbot(nick); - } - - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERJOIN; - resp.nick = nick; - resp.player.roomType = roomType; - resp.player.IP = 0; - - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -void PeerThreadClass::handleQMMatch(PEER peer, Int mapIndex, Int seed, - char *playerName[MAX_SLOTS], - char *playerIP[MAX_SLOTS], - char *playerSide[MAX_SLOTS], - char *playerColor[MAX_SLOTS], - char *playerNAT[MAX_SLOTS]) -{ - if (m_qmStatus == QM_WORKING) - { - m_qmStatus = QM_MATCHED; - peerLeaveRoom(peer, GroupRoom, ""); - - for (Int i=0; iaddResponse(resp); - } -} - -void PeerThreadClass::doQuickMatch( PEER peer ) -{ - m_qmStatus = QM_JOININGQMCHANNEL; - Bool done = false; - matchbotProfileID = m_qmInfo.QM.botID; - setQMGroupRoom( m_qmInfo.QM.roomID ); - m_sawMatchbot = false; - updateBuddyStatus( BUDDY_MATCHING ); - while (!done && running) - { - if (!peerIsConnected( peer )) - { - done = true; - } - else - { - // update the network - peerThink( peer ); - - // end our timeslice - Switch_Thread(); - - PeerRequest incomingRequest; - if (TheGameSpyPeerMessageQueue->getRequest(incomingRequest)) - { - switch (incomingRequest.peerRequestType) - { - case PeerRequest::PEERREQUEST_WIDENQUICKMATCHSEARCH: - { - if (m_qmStatus != QM_IDLE && m_qmStatus != QM_STOPPED && m_sawMatchbot) - { - peerMessagePlayer( peer, m_matchbotName.c_str(), "\\WIDEN", NormalMessage ); - } - } - break; - case PeerRequest::PEERREQUEST_STOPQUICKMATCH: - { - m_qmStatus = QM_STOPPED; - peerLeaveRoom(peer, GroupRoom, ""); - done = true; - } - break; - case PeerRequest::PEERREQUEST_LOGOUT: - { - m_qmStatus = QM_STOPPED; - peerLeaveRoom(peer, GroupRoom, ""); - done = true; - } - break; - case PeerRequest::PEERREQUEST_LEAVEGROUPROOM: - { - m_qmStatus = QM_STOPPED; - peerLeaveRoom(peer, GroupRoom, ""); - done = true; - } - break; - case PeerRequest::PEERREQUEST_UTMPLAYER: - { - peerUTMPlayer( peer, incomingRequest.nick.c_str(), incomingRequest.id.c_str(), incomingRequest.options.c_str(), PEERFalse ); - } - break; - default: - { - DEBUG_CRASH(("Unanticipated request %d to peer thread!", incomingRequest.peerRequestType)); - } - break; - } - } - - if (!done) - { - // do the next bit of QM - switch (m_qmStatus) - { - case QM_JOININGQMCHANNEL: - { - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS; - resp.qmStatus.status = QM_JOININGQMCHANNEL; - TheGameSpyPeerMessageQueue->addResponse(resp); - - m_groupRoomID = m_qmGroupRoom; - peerLeaveRoom( peer, GroupRoom, NULL ); - peerLeaveRoom( peer, StagingRoom, NULL ); m_isHosting = false; - m_localRoomID = m_groupRoomID; - m_roomJoined = false; - DEBUG_LOG(("Requesting to join room %d in thread %X\n", m_localRoomID, this)); - peerJoinGroupRoom( peer, m_localRoomID, joinRoomCallback, (void *)this, PEERTrue ); - if (m_roomJoined) - { - resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS; - resp.qmStatus.status = QM_LOOKINGFORBOT; - TheGameSpyPeerMessageQueue->addResponse(resp); - - m_qmStatus = QM_LOOKINGFORBOT; - m_sawMatchbot = false; - m_sawEndOfEnumPlayers = false; - peerEnumPlayers( peer, GroupRoom, quickmatchEnumPlayersCallback, this ); - } - else - { - resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS; - resp.qmStatus.status = QM_COULDNOTFINDBOT; - TheGameSpyPeerMessageQueue->addResponse(resp); - done = true; - m_qmStatus = QM_STOPPED; - } - } - break; - case QM_LOOKINGFORBOT: - { - if (m_sawEndOfEnumPlayers) - { - if (m_sawMatchbot) - { - char buf[64]; - buf[63] = '\0'; - std::string msg = "\\CINFO"; - _snprintf(buf, 63, "\\Widen\\%d", m_qmInfo.QM.widenTime); - msg.append(buf); - _snprintf(buf, 63, "\\LadID\\%d", m_qmInfo.QM.ladderID); - msg.append(buf); - _snprintf(buf, 63, "\\LadPass\\%d", m_qmInfo.QM.ladderPassCRC); - msg.append(buf); - _snprintf(buf, 63, "\\PointsMin\\%d", m_qmInfo.QM.minPointPercentage); - msg.append(buf); - _snprintf(buf, 63, "\\PointsMax\\%d", m_qmInfo.QM.maxPointPercentage); - msg.append(buf); - _snprintf(buf, 63, "\\Points\\%d", m_qmInfo.QM.points); - msg.append(buf); - _snprintf(buf, 63, "\\Discons\\%d", m_qmInfo.QM.discons); - msg.append(buf); - _snprintf(buf, 63, "\\DisconMax\\%d", m_qmInfo.QM.maxDiscons); - msg.append(buf); - _snprintf(buf, 63, "\\NumPlayers\\%d", m_qmInfo.QM.numPlayers); - msg.append(buf); - _snprintf(buf, 63, "\\Pings\\%s", m_qmInfo.QM.pings); - msg.append(buf); - _snprintf(buf, 63, "\\IP\\%d", ntohl(peerGetLocalIP(peer)));// not ntohl(localIP), as we need EXTERNAL address for proper NAT negotiation! - msg.append(buf); - _snprintf(buf, 63, "\\Side\\%d", m_qmInfo.QM.side); - msg.append(buf); - _snprintf(buf, 63, "\\Color\\%d", m_qmInfo.QM.color); - msg.append(buf); - _snprintf(buf, 63, "\\NAT\\%d", m_qmInfo.QM.NAT); - msg.append(buf); - _snprintf(buf, 63, "\\EXE\\%d", m_qmInfo.QM.exeCRC); - msg.append(buf); - _snprintf(buf, 63, "\\INI\\%d", m_qmInfo.QM.iniCRC); - msg.append(buf); - buf[0] = 0; - msg.append("\\Maps\\"); - for (Int i=0; iaddResponse(resp); - } - else - { - // no QM bot. Bail. - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS; - resp.qmStatus.status = QM_COULDNOTFINDBOT; - TheGameSpyPeerMessageQueue->addResponse(resp); - - m_qmStatus = QM_STOPPED; - peerLeaveRoom(peer, GroupRoom, ""); - done = true; - } - } - } - break; - case QM_WORKING: - { - } - break; - case QM_MATCHED: - { - // leave QM channel, and clean up. Our work here is done. - peerLeaveRoom( peer, GroupRoom, NULL ); - peerLeaveRoom( peer, StagingRoom, NULL ); m_isHosting = false; - - m_qmStatus = QM_STOPPED; - peerLeaveRoom(peer, GroupRoom, ""); - done = true; - } - break; - case QM_INCHANNEL: - { - } - break; - case QM_NEGOTIATINGFIREWALLS: - { - } - break; - case QM_STARTINGGAME: - { - } - break; - case QM_COULDNOTFINDCHANNEL: - { - } - break; - case QM_COULDNOTNEGOTIATEFIREWALLS: - { - } - break; - } - } - } - } - updateBuddyStatus( BUDDY_ONLINE ); -} - -static void getPlayerProfileIDCallback(PEER peer, PEERBool success, const char * nick, int profileID, void * param) -{ - if (success && param != NULL) - { - *((Int *)param) = profileID; - } -} - -static void stagingRoomPlayerEnum( PEER peer, PEERBool success, RoomType roomType, int index, const char * nick, int flags, void * param ) -{ - DEBUG_LOG(("Enum: success=%d, index=%d, nick=%s, flags=%d\n", success, index, nick, flags)); - if (!nick || !success) - return; - - Int id = 0; - peerGetPlayerProfileID(peer, nick, getPlayerProfileIDCallback, &id, PEERTrue); - DEBUG_ASSERTCRASH(id != 0, ("Failed to fetch player ID!")); - - PeerResponse *resp = (PeerResponse *)param; - if (flags & PEER_FLAG_OP) - { - resp->joinStagingRoom.isHostPresent = TRUE; - } - if (index < MAX_SLOTS) - { - resp->stagingRoomPlayerNames[index] = nick; - } - - if (id) - { - PSRequest req; - req.requestType = PSRequest::PSREQUEST_READPLAYERSTATS; - req.player.id = id; - TheGameSpyPSMessageQueue->addRequest(req); - } -} - -static void joinRoomCallback(PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, void *param) -{ - DEBUG_LOG(("JoinRoomCallback: success==%d, result==%d\n", success, result)); - PeerThreadClass *t = (PeerThreadClass *)param; - if (!t) - return; - DEBUG_LOG(("Room id was %d from thread %X\n", t->getLocalRoomID(), t)); - DEBUG_LOG(("Current staging server name is [%ls]\n", t->getLocalStagingServerName().c_str())); - DEBUG_LOG(("Room type is %d (GroupRoom=%d, StagingRoom=%d, TitleRoom=%d)\n", roomType, GroupRoom, StagingRoom, TitleRoom)); - -#ifdef USE_BROADCAST_KEYS - if (success) - { - t->pushStatsToRoom(peer); - t->getStatsFromRoom(peer, roomType); - } -#endif // USE_BROADCAST_KEYS - - switch (roomType) - { - case GroupRoom: - { -#ifdef USE_BROADCAST_KEYS - t->clearPlayerStats(GroupRoom); -#endif // USE_BROADCAST_KEYS - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_JOINGROUPROOM; - resp.joinGroupRoom.id = t->getLocalRoomID(); - resp.joinGroupRoom.ok = success; - TheGameSpyPeerMessageQueue->addResponse(resp); - t->roomJoined(success == PEERTrue); - DEBUG_LOG(("Entered group room %d, qm is %d\n", t->getLocalRoomID(), t->getQMGroupRoom())); - if ((!t->getQMGroupRoom()) || (t->getQMGroupRoom() != t->getLocalRoomID())) - { - DEBUG_LOG(("Updating buddy status\n")); - updateBuddyStatus( BUDDY_LOBBY, t->getLocalRoomID() ); - } - } - break; - case StagingRoom: - { -#ifdef USE_BROADCAST_KEYS - t->clearPlayerStats(StagingRoom); -#endif // USE_BROADCAST_KEYS - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_JOINSTAGINGROOM; - resp.joinStagingRoom.id = t->getLocalRoomID(); - resp.joinStagingRoom.ok = success; - resp.joinStagingRoom.result = result; - if (success) - { - DEBUG_LOG(("joinRoomCallback() - game name is now '%ls'\n", t->getLocalStagingServerName().c_str())); - updateBuddyStatus( BUDDY_STAGING, 0, WideCharStringToMultiByte(t->getLocalStagingServerName().c_str()) ); - } - - resp.joinStagingRoom.isHostPresent = FALSE; - DEBUG_LOG(("Enum of staging room players\n")); - peerEnumPlayers(peer, StagingRoom, stagingRoomPlayerEnum, &resp); - DEBUG_LOG(("Host %s present\n", (resp.joinStagingRoom.isHostPresent)?"is":"is not")); - - TheGameSpyPeerMessageQueue->addResponse(resp); - } - break; - } -} - -// Gets called once for each group room when listing group rooms. -// After this has been called for each group room, it will be -// called one more time with groupID==0 and name==NULL. -///////////////////////////////////////////////////////////////// -static void listGroupRoomsCallback(PEER peer, PEERBool success, - int groupID, SBServer server, - const char * name, int numWaiting, - int maxWaiting, int numGames, - int numPlaying, void * param) -{ - DEBUG_LOG(("listGroupRoomsCallback, success=%d, server=%X, groupID=%d\n", success, server, groupID)); -#ifdef SERVER_DEBUGGING - CheckServers(peer); -#endif // SERVER_DEBUGGING - PeerThreadClass *t = (PeerThreadClass *)param; - if (!t) - { - DEBUG_LOG(("No thread! Bailing!\n")); - return; - } - - if (success) - { - DEBUG_LOG(("Saw group room of %d (%s) at address %X %X\n", groupID, name, server, (server)?server->keyvals:0)); - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_GROUPROOM; - resp.groupRoom.id = groupID; - resp.groupRoom.numWaiting = numWaiting; - resp.groupRoom.maxWaiting = maxWaiting; - resp.groupRoom.numGames = numGames; - resp.groupRoom.numPlaying = numPlaying; - if (name) - { - resp.groupRoomName = name; - //t->setQMGroupRoom(groupID); - } - else - { - resp.groupRoomName.empty(); - } - TheGameSpyPeerMessageQueue->addResponse(resp); -#ifdef SERVER_DEBUGGING - CheckServers(peer); - DEBUG_LOG(("\n")); -#endif // SERVER_DEBUGGING - } - else - { - DEBUG_LOG(("Failure!\n")); - } -} - -void PeerThreadClass::connectCallback( PEER peer, PEERBool success ) -{ - PeerResponse resp; - if(!success) - { - //updateBuddyStatus( BUDDY_OFFLINE ); - resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT; - resp.discon.reason = DISCONNECT_COULDNOTCONNECT; - TheGameSpyPeerMessageQueue->addResponse(resp); - return; - } - - updateBuddyStatus( BUDDY_ONLINE ); - - m_isConnected = true; - DEBUG_LOG(("Connected as profile %d (%s)\n", m_profileID, m_loginName.c_str())); - resp.peerResponseType = PeerResponse::PEERRESPONSE_LOGIN; - resp.player.profileID = m_profileID; - resp.nick = m_loginName; - GetLocalChatConnectionAddress("peerchat.gamespy.com", 6667, localIP); - //chatSetLocalIP(localIP); - resp.player.internalIP = ntohl(localIP); - resp.player.externalIP = ntohl(peerGetLocalIP(peer)); - TheGameSpyPeerMessageQueue->addResponse(resp); - - PSRequest psReq; - psReq.requestType = PSRequest::PSREQUEST_READPLAYERSTATS; - psReq.player.id = m_profileID; - psReq.nick = m_originalName; - psReq.email = m_email; - psReq.password = m_password; - TheGameSpyPSMessageQueue->addRequest(psReq); - -#ifdef SERVER_DEBUGGING - DEBUG_LOG(("Before peerListGroupRooms()\n")); - CheckServers(peer); -#endif // SERVER_DEBUGGING - peerListGroupRooms( peer, NULL, listGroupRoomsCallback, this, PEERTrue ); -#ifdef SERVER_DEBUGGING - DEBUG_LOG(("After peerListGroupRooms()\n")); - CheckServers(peer); -#endif // SERVER_DEBUGGING -} - -void PeerThreadClass::nickErrorCallback( PEER peer, Int type, const char *nick ) -{ - if(type == PEER_IN_USE) - { - Int len = strlen(nick); - std::string nickStr = nick; - Int newVal = 0; - if (nick[len-1] == '}' && nick[len-3] == '{' && isdigit(nick[len-2])) - { - newVal = nick[len-2] - '0' + 1; - nickStr.erase(len-3, 3); - } - - DEBUG_LOG(("Nickname taken: was %s, new val = %d, new nick = %s\n", nick, newVal, nickStr.c_str())); - - if (newVal < 10) - { - nickStr.append("{"); - char tmp[2]; - tmp[0] = '0'+newVal; - tmp[1] = '\0'; - nickStr.append(tmp); - nickStr.append("}"); - // Retry the connect with a similar nick. - m_loginName = nickStr; - peerRetryWithNick(peer, nickStr.c_str()); - } - else - { - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT; - resp.discon.reason = DISCONNECT_NICKTAKEN; - TheGameSpyPeerMessageQueue->addResponse(resp); - - // Cancel the connect. - peerRetryWithNick(peer, NULL); - } - } - else - { - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT; - resp.discon.reason = DISCONNECT_BADNICK; - TheGameSpyPeerMessageQueue->addResponse(resp); - - // Cancel the connect. - peerRetryWithNick(peer, NULL); - } -} - -void disconnectedCallback(PEER peer, const char * reason, void * param) -{ - DEBUG_LOG(("disconnectedCallback(): reason was '%s'\n", reason)); - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (t) - t->markAsDisconnected(); - //updateBuddyStatus( BUDDY_OFFLINE ); - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT; - resp.discon.reason = DISCONNECT_LOSTCON; - SerialAuthResult res = TheGameSpyPeerMessageQueue->getSerialAuthResult(); - switch (res) - { - case SERIAL_NONEXISTENT: - resp.discon.reason = DISCONNECT_SERIAL_NOT_PRESENT; - break; - case SERIAL_AUTHFAILED: - resp.discon.reason = DISCONNECT_SERIAL_INVALID; - break; - case SERIAL_BANNED: - resp.discon.reason = DISCONNECT_SERIAL_BANNED; - break; - } - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -void roomMessageCallback(PEER peer, RoomType roomType, const char * nick, const char * message, MessageType messageType, void * param) -{ - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_MESSAGE; - resp.nick = nick; - resp.text = MultiByteToWideCharSingleLine(message); - resp.message.isPrivate = FALSE; - resp.message.isAction = (messageType == ActionMessage); - TheGameSpyPeerMessageQueue->addResponse(resp); - DEBUG_LOG(("Saw text [%hs] (%ls) %d chars Orig was %s (%d chars)\n", nick, resp.text.c_str(), resp.text.length(), message, strlen(message))); - - UnsignedInt IP; - peerGetPlayerInfoNoWait(peer, nick, &IP, &resp.message.profileID); - - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (t && (t->getQMStatus() != QM_IDLE && t->getQMStatus() != QM_STOPPED)) - { - if (resp.message.profileID == matchbotProfileID) - { - char *lastStr = NULL; - char *cmd = strtok_r((char *)message, " ", &lastStr); - if ( cmd && strcmp(cmd, "MBOT:POOLSIZE") == 0 ) - { - Int poolSize = 0; - - while (1) - { - char *poolStr = strtok_r(NULL, " ", &lastStr); - char *sizeStr = strtok_r(NULL, " ", &lastStr); - if (poolStr && sizeStr) - { - Int pool = atoi(poolStr); - Int size = atoi(sizeStr); - if (pool == t->getQMLadder()) - { - poolSize = size; - break; - } - } - else - break; - } - - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS; - resp.qmStatus.status = QM_POOLSIZE; - resp.qmStatus.poolSize = poolSize; - TheGameSpyPeerMessageQueue->addResponse(resp); - } - } - } -} - -void gameStartedCallback( PEER peer, SBServer server, const char *message, void *param ) -{ - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_GAMESTART; - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -void playerMessageCallback(PEER peer, const char * nick, const char * message, MessageType messageType, void * param) -{ - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_MESSAGE; - resp.nick = nick; - resp.text = MultiByteToWideCharSingleLine(message); - resp.message.isPrivate = TRUE; - resp.message.isAction = (messageType == ActionMessage); - UnsignedInt IP; - peerGetPlayerInfoNoWait(peer, nick, &IP, &resp.message.profileID); - TheGameSpyPeerMessageQueue->addResponse(resp); - - - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (t && (t->getQMStatus() != QM_IDLE && t->getQMStatus() != QM_STOPPED)) - { - if (resp.message.isPrivate && resp.message.profileID == matchbotProfileID) - { - char *lastStr = NULL; - char *cmd = strtok_r((char *)message, " ", &lastStr); - if ( cmd && strcmp(cmd, "MBOT:MATCHED") == 0 ) - { - char *mapNumStr = strtok_r(NULL, " ", &lastStr); - char *seedStr = strtok_r(NULL, " ", &lastStr); - char *playerStr[MAX_SLOTS]; - char *playerIPStr[MAX_SLOTS]; - char *playerSideStr[MAX_SLOTS]; - char *playerColorStr[MAX_SLOTS]; - char *playerNATStr[MAX_SLOTS]; - Int numPlayers = 0; - for (Int i=0; i 1) - { - // woohoo! got everything needed for a match! - DEBUG_LOG(("Saw %d-player QM match: map index = %s, seed = %s\n", numPlayers, mapNumStr, seedStr)); - t->handleQMMatch(peer, atoi(mapNumStr), atoi(seedStr), playerStr, playerIPStr, playerSideStr, playerColorStr, playerNATStr); - } - } - else if ( cmd && strcmp(cmd, "MBOT:WORKING") == 0 ) - { - Int poolSize = 0; - char *poolStr = strtok_r(NULL, " ", &lastStr); - if (poolStr) - poolSize = atoi(poolStr); - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS; - resp.qmStatus.status = QM_WORKING; - resp.qmStatus.poolSize = poolSize; - TheGameSpyPeerMessageQueue->addResponse(resp); - } - else if ( cmd && strcmp(cmd, "MBOT:WIDENINGSEARCH") == 0 ) - { - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS; - resp.qmStatus.status = QM_WIDENINGSEARCH; - TheGameSpyPeerMessageQueue->addResponse(resp); - } - } - } -} - -void roomUTMCallback(PEER peer, RoomType roomType, const char * nick, const char * command, const char * parameters, PEERBool authenticated, void * param) -{ - DEBUG_LOG(("roomUTMCallback: %s says %s = [%s]\n", nick, command, parameters)); - if (roomType != StagingRoom) - return; - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_ROOMUTM; - resp.nick = nick; - resp.command = command; - resp.commandOptions = parameters; - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -void playerUTMCallback(PEER peer, const char * nick, const char * command, const char * parameters, PEERBool authenticated, void * param) -{ - DEBUG_LOG(("playerUTMCallback: %s says %s = [%s]\n", nick, command, parameters)); - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERUTM; - resp.nick = nick; - resp.command = command; - resp.commandOptions = parameters; - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -static void getPlayerInfo(PeerThreadClass *t, PEER peer, const char *nick, Int& id, UnsignedInt& IP, - std::string& locale, Int& wins, Int& losses, Int& rankPoints, Int& side, Int& preorder, - RoomType roomType, Int& flags) -{ - if (!t || !nick) - return; - peerGetPlayerInfoNoWait(peer, nick, &IP, &id); -#ifdef USE_BROADCAST_KEYS - //locale.printf - Int localeIndex = t->lookupStatForPlayer(roomType, nick, "b_locale"); - AsciiString tmp; - tmp.format("%d", localeIndex); - locale = tmp.str(); - - wins = t->lookupStatForPlayer(roomType, nick, "b_wins"); - losses = t->lookupStatForPlayer(roomType, nick, "b_losses"); - rankPoints = t->lookupStatForPlayer(roomType, nick, "b_points"); - side = t->lookupStatForPlayer(roomType, nick, "b_side"); - preorder = t->lookupStatForPlayer(roomType, nick, "b_pre"); -#else // USE_BROADCAST_KEYS - const char *s; - s = peerGetGlobalWatchKey(peer, nick, "locale"); - locale = (s)?s:""; - s = peerGetGlobalWatchKey(peer, nick, "wins"); - wins = atoi((s)?s:""); - s = peerGetGlobalWatchKey(peer, nick, "losses"); - losses = atoi((s)?s:""); - s = peerGetGlobalWatchKey(peer, nick, "points"); - rankPoints = atoi((s)?s:""); - s = peerGetGlobalWatchKey(peer, nick, "side"); - side = atoi((s)?s:""); - s = peerGetGlobalWatchKey(peer, nick, "pre"); - preorder = atoi((s)?s:""); -#endif // USE_BROADCAST_KEYS - flags = 0; - peerGetPlayerFlags(peer, nick, roomType, &flags); - DEBUG_LOG(("getPlayerInfo(%d) - %s has locale %s, wins:%d, losses:%d, rankPoints:%d, side:%d, preorder:%d\n", - id, nick, locale.c_str(), wins, losses, rankPoints, side, preorder)); -} - -static void roomKeyChangedCallback(PEER peer, RoomType roomType, const char *nick, const char *key, const char *val, void *param) -{ -#ifdef USE_BROADCAST_KEYS - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - DEBUG_ASSERTCRASH(nick && key && val, ("Bad values %X %X %X\n", nick, key, val)); - if (!t || !nick || !key || !val) - { - DEBUG_ASSERTLOG(!nick, ("nick = %s\n", nick)); - DEBUG_ASSERTLOG(!key, ("key = %s\n", key)); - DEBUG_ASSERTLOG(!val, ("val = %s\n", val)); - return; - } - -#ifdef DEBUG_LOGGING - if (strcmp(key, "username") && strcmp(key, "b_flags")) - { - DEBUG_LOG(("roomKeyChangedCallback() - %s set %s=%s\n", nick, key, val)); - } -#endif - - t->trackStatsForPlayer(roomType, nick, key, val); - - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERINFO; - resp.nick = nick; - resp.player.roomType = roomType; - - getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP, - resp.locale, resp.player.wins, resp.player.losses, - resp.player.rankPoints, resp.player.side, resp.player.preorder, - resp.player.roomType, resp.player.flags); - TheGameSpyPeerMessageQueue->addResponse(resp); -#endif // USE_BROADCAST_KEYS -} - -#ifdef USE_BROADCAST_KEYS -void getRoomKeysCallback(PEER peer, PEERBool success, RoomType roomType, const char *nick, int num, char **keys, char **values, void *param) -{ - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - DEBUG_ASSERTCRASH(keys && values, ("bad key/value %X/%X", keys, values)); - if (!t || !nick || !num || !success || !keys || !values) - return; - - for (Int i=0; itrackStatsForPlayer(roomType, nick, keys[i], values[i]); - } - - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERINFO; - resp.nick = nick; - resp.player.roomType = roomType; - - getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP, - resp.locale, resp.player.wins, resp.player.losses, - resp.player.rankPoints, resp.player.side, resp.player.preorder, - resp.player.roomType, resp.player.flags); - TheGameSpyPeerMessageQueue->addResponse(resp); -} -#endif // USE_BROADCAST_KEYS - -static void globalKeyChangedCallback(PEER peer, const char *nick, const char *key, const char *val, void *param) -{ - if (!nick) - return; - - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (!t) - return; - - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERINFO; - resp.nick = nick; - resp.player.roomType = t->getCurrentGroupRoom()?GroupRoom:StagingRoom; - - getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP, - resp.locale, resp.player.wins, resp.player.losses, - resp.player.rankPoints, resp.player.side, resp.player.preorder, - resp.player.roomType, resp.player.flags); - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -void playerJoinedCallback(PEER peer, RoomType roomType, const char * nick, void * param) -{ - if (!nick) - return; - - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (!t) - return; - - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERJOIN; - resp.nick = nick; - resp.player.roomType = roomType; - - getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP, - resp.locale, resp.player.wins, resp.player.losses, - resp.player.rankPoints, resp.player.side, resp.player.preorder, - roomType, resp.player.flags); - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -void playerLeftCallback(PEER peer, RoomType roomType, const char * nick, const char * reason, void * param) -{ - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERLEFT; - resp.nick = nick; - resp.player.roomType = roomType; - resp.player.profileID = 0; - - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (!t) - return; - - getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP, - resp.locale, resp.player.wins, resp.player.losses, - resp.player.rankPoints, resp.player.side, resp.player.preorder, - roomType, resp.player.flags); - TheGameSpyPeerMessageQueue->addResponse(resp); - - if (t->getQMStatus() != QM_IDLE && t->getQMStatus() != QM_STOPPED) - { - if (!stricmp(t->getQMBotName().c_str(), nick)) - { - // matchbot left - bail - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS; - resp.qmStatus.status = QM_COULDNOTFINDBOT; - TheGameSpyPeerMessageQueue->addResponse(resp); - - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_STOPQUICKMATCH; - TheGameSpyPeerMessageQueue->addRequest(req); - } - } -} - -void playerChangedNickCallback(PEER peer, RoomType roomType, const char * oldNick, const char * newNick, void * param) -{ - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERCHANGEDNICK; - resp.nick = newNick; - resp.oldNick = oldNick; - resp.player.roomType = roomType; - - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (!t) - return; - - getPlayerInfo(t, peer, newNick, resp.player.profileID, resp.player.IP, - resp.locale, resp.player.wins, resp.player.losses, - resp.player.rankPoints, resp.player.side, resp.player.preorder, - roomType, resp.player.flags); - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -static void playerInfoCallback(PEER peer, RoomType roomType, const char * nick, unsigned int IP, int profileID, void * param) -{ - if (!nick) - return; - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERINFO; - resp.nick = nick; - resp.player.roomType = roomType; - - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (!t) - return; - - getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP, - resp.locale, resp.player.wins, resp.player.losses, - resp.player.rankPoints, resp.player.side, resp.player.preorder, - roomType, resp.player.flags); - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -static void playerFlagsChangedCallback(PEER peer, RoomType roomType, const char * nick, int oldFlags, int newFlags, void * param) -{ - if (!nick) - return; - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERCHANGEDFLAGS; - resp.nick = nick; - resp.player.roomType = roomType; - - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (!t) - return; - - getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP, - resp.locale, resp.player.wins, resp.player.losses, - resp.player.rankPoints, resp.player.side, resp.player.preorder, - roomType, resp.player.flags); - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -#ifdef DEBUG_LOGGING -/* -static void enumFunc(char *key, char *val, void *param) -{ - DEBUG_LOG((" [%s] = [%s]\n", key, val)); -} -*/ -#endif - -static void listingGamesCallback(PEER peer, PEERBool success, const char * name, SBServer server, PEERBool staging, int msg, Int percentListed, void * param) -{ -#ifdef DEBUG_LOGGING - AsciiString cmdStr = ""; - switch(msg) - { - case PEER_ADD: - cmdStr = "PEER_ADD"; - break; - case PEER_UPDATE: - cmdStr = "PEER_UPDATE"; - break; - case PEER_REMOVE: - cmdStr = "PEER_REMOVE"; - break; - case PEER_CLEAR: - cmdStr = "PEER_CLEAR"; - break; - case PEER_COMPLETE: - cmdStr = "PEER_COMPLETE"; - break; - } - DEBUG_LOG(("listingGamesCallback() - doing command %s on server %X\n", cmdStr.str(), server)); -#endif // DEBUG_LOGGING - - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(name, ("Game has no name!\n")); - if (!t || !success || (!name && (msg == PEER_ADD || msg == PEER_UPDATE))) - { - DEBUG_LOG(("Bailing from listingGamesCallback() - success=%d, name=%X, server=%X, msg=%X\n", success, name, server, msg)); - return; - } - if (!name) - name = "bogus"; - - if (server && (msg == PEER_ADD || msg == PEER_UPDATE)) - { - DEBUG_ASSERTCRASH(server->keyvals, ("Looking at an already-freed server for msg type %d!", msg)); - if (!server->keyvals) - { - msg = PEER_REMOVE; - } - } - - if (server && success && (msg == PEER_ADD || msg == PEER_UPDATE)) - { - DEBUG_LOG(("Game name is '%s'\n", name)); - const char *newname = SBServerGetStringValue(server, "gamename", (char *)name); - if (strcmp(newname, "ccgenerals")) - name = newname; - DEBUG_LOG(("Game name is now '%s'\n", name)); - } - - DEBUG_LOG(("listingGamesCallback - got percent complete %d\n", percentListed)); - if (percentListed == 100) - { - if (!t->getSawCompleteGameList()) - { - t->setSawCompleteGameList(TRUE); - PeerResponse completeResp; - completeResp.peerResponseType = PeerResponse::PEERRESPONSE_STAGINGROOMLISTCOMPLETE; - TheGameSpyPeerMessageQueue->addResponse(completeResp); - } - } - - AsciiString gameName = name; - AsciiString tmp = gameName; - AsciiString hostName; - tmp.nextToken(&hostName, " "); - const char *firstSpace = gameName.find(' '); - if(firstSpace) - { - gameName.set(firstSpace + 1); - //gameName.trim(); - DEBUG_LOG(("Hostname/Gamename split leaves '%s' hosting '%s'\n", hostName.str(), gameName.str())); - } - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_STAGINGROOM; - resp.stagingRoom.action = msg; - resp.stagingRoom.isStaging = staging; - resp.stagingRoom.percentComplete = percentListed; - - if (server && (msg == PEER_ADD || msg == PEER_UPDATE)) - { - Bool hasPassword = (Bool)SBServerGetIntValue(server, PW_STR, FALSE); - Bool allowObservers = (Bool)SBServerGetIntValue(server, OBS_STR, FALSE); - const char *verStr = SBServerGetStringValue(server, "gamever", "000000"); - const char *exeStr = SBServerGetStringValue(server, EXECRC_STR, "000000"); - const char *iniStr = SBServerGetStringValue(server, INICRC_STR, "000000"); - const char *ladIPStr = SBServerGetStringValue(server, LADIP_STR, "000000"); - const char *pingStr = SBServerGetStringValue(server, PINGSTR_STR, "FFFFFFFFFFFFFFFF"); - UnsignedShort ladPort = (UnsignedShort)SBServerGetIntValue(server, LADPORT_STR, 0); - UnsignedInt verVal = strtoul(verStr, NULL, 10); - UnsignedInt exeVal = strtoul(exeStr, NULL, 10); - UnsignedInt iniVal = strtoul(iniStr, NULL, 10); - resp.stagingRoom.requiresPassword = hasPassword; - resp.stagingRoom.allowObservers = allowObservers; - resp.stagingRoom.version = verVal; - resp.stagingRoom.exeCRC = exeVal; - resp.stagingRoom.iniCRC = iniVal; - resp.stagingServerLadderIP = ladIPStr; - resp.stagingServerPingString = pingStr; - resp.stagingRoom.ladderPort = ladPort; - resp.stagingRoom.numPlayers = SBServerGetIntValue(server, NUMPLAYER_STR, 0); - resp.stagingRoom.numObservers = SBServerGetIntValue(server, NUMOBS_STR, 0); - resp.stagingRoom.maxPlayers = SBServerGetIntValue(server, MAXPLAYER_STR, 8); - resp.stagingRoomMapName = SBServerGetStringValue(server, "mapname", ""); - for (Int i=0; ifindServer( server ); - DEBUG_LOG(("Add/update a 0/0 server %X (%d, %s) - requesting full update to see if that helps.\n", - server, resp.stagingRoom.id, gameName.str())); - TheGameSpyPeerMessageQueue->addRequest(req); - } - return; // don't actually try to list it. - } - } - - switch (msg) - { - case PEER_CLEAR: - t->clearServers(); - break; - case PEER_ADD: - case PEER_UPDATE: - resp.stagingRoom.id = t->findServer( server ); - DEBUG_LOG(("Add/update on server %X (%d, %s)\n", server, resp.stagingRoom.id, gameName.str())); - resp.stagingServerName = MultiByteToWideCharSingleLine( gameName.str() ); - DEBUG_LOG(("Server had basic=%d, full=%d\n", SBServerHasBasicKeys(server), SBServerHasFullKeys(server))); -#ifdef DEBUG_LOGGING - //SBServerEnumKeys(server, enumFunc, NULL); -#endif - break; - case PEER_REMOVE: - DEBUG_LOG(("Removing server %X (%d)\n", server, resp.stagingRoom.id)); - resp.stagingRoom.id = t->removeServerFromMap( server ); - break; - } - - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -//------------------------------------------------------------------------- - diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PersistentStorageThread.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PersistentStorageThread.cpp deleted file mode 100644 index 9a5df716b06..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PersistentStorageThread.cpp +++ /dev/null @@ -1,1513 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PersistentStorageThread.cpp ////////////////////////////////////////////////////// -// GameSpy Persistent Storage thread -// This thread communicates with GameSpy's persistent storage server -// and talks through a message queue with the rest of -// the game. -// Author: Matthew D. Campbell, July 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/UserPreferences.h" -#include "Common/PlayerTemplate.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" - -#include "mutex.h" -#include "thread.h" - -#include "Common/StackDump.h" -#include "Common/SubsystemInterface.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -//------------------------------------------------------------------------- - -PSRequest::PSRequest() -{ - player.reset(); - requestType = PSREQUEST_READPLAYERSTATS; - addDiscon = addDesync = FALSE; - lastHouse = -1; -} - -//------------------------------------------------------------------------- - -#define DEBUG_MAP(x) for (it = stats.x.begin(); it != stats.x.end(); ++it) \ -{ \ - if (it->second > 0) \ - { \ - DEBUG_LOG(("%s(%d): %d\n", #x, it->first, it->second)); \ - } \ -} - -static void debugDumpPlayerStats( const PSPlayerStats& stats ) -{ - DEBUG_LOG(("-----------------------------------------\n")); - DEBUG_LOG(("Tracking player stats for player %d:\n", stats.id)); - PerGeneralMap::const_iterator it; - DEBUG_MAP(wins); - DEBUG_MAP(losses); - DEBUG_MAP(games); - DEBUG_MAP(duration); - DEBUG_MAP(unitsKilled); - DEBUG_MAP(unitsLost); - DEBUG_MAP(unitsBuilt); - DEBUG_MAP(buildingsKilled); - DEBUG_MAP(buildingsLost); - DEBUG_MAP(buildingsBuilt); - DEBUG_MAP(earnings); - DEBUG_MAP(techCaptured); - DEBUG_MAP(discons); - DEBUG_MAP(desyncs); - DEBUG_MAP(surrenders); - DEBUG_MAP(gamesOf2p); - DEBUG_MAP(gamesOf3p); - DEBUG_MAP(gamesOf4p); - DEBUG_MAP(gamesOf5p); - DEBUG_MAP(gamesOf6p); - DEBUG_MAP(gamesOf7p); - DEBUG_MAP(gamesOf8p); - DEBUG_MAP(customGames); - DEBUG_MAP(QMGames); - - if (stats.locale > 0) - { - DEBUG_LOG(("Locale: %d\n", stats.locale)); - } - - if (stats.gamesAsRandom > 0) - { - DEBUG_LOG(("gamesAsRandom: %d\n", stats.gamesAsRandom)); - } - - if (stats.options.length()) - { - DEBUG_LOG(("Options: %s\n", stats.options.c_str())); - } - - if (stats.systemSpec.length()) - { - DEBUG_LOG(("systemSpec: %s\n", stats.systemSpec.c_str())); - } - - if (stats.lastFPS > 0.0f) - { - DEBUG_LOG(("lastFPS: %g\n", stats.lastFPS)); - } - - if (stats.battleHonors > 0) - { - DEBUG_LOG(("battleHonors: %x\n", stats.battleHonors)); - } - if (stats.challengeMedals > 0) - { - DEBUG_LOG(("challengeMedals: %x\n", stats.challengeMedals)); - } - if (stats.lastGeneral >= 0) - { - DEBUG_LOG(("lastGeneral: %d\n", stats.lastGeneral)); - } - if (stats.gamesInRowWithLastGeneral >= 0) - { - DEBUG_LOG(("gamesInRowWithLastGeneral: %d\n", stats.gamesInRowWithLastGeneral)); - } - if (stats.builtSCUD >= 0) - { - DEBUG_LOG(("builtSCUD: %d\n", stats.builtSCUD)); - } - if (stats.builtNuke >= 0) - { - DEBUG_LOG(("builtNuke: %d\n", stats.builtNuke)); - } - if (stats.builtParticleCannon >= 0) - { - DEBUG_LOG(("builtParticleCannon: %d\n", stats.builtParticleCannon)); - } - - if (stats.winsInARow >= 0) - { - DEBUG_LOG(("winsInARow: %d\n", stats.winsInARow)); - } - if (stats.maxWinsInARow >= 0) - { - DEBUG_LOG(("maxWinsInARow: %d\n", stats.maxWinsInARow)); - } - if (stats.disconsInARow >= 0) - { - DEBUG_LOG(("disconsInARow: %d\n", stats.disconsInARow)); - } - if (stats.maxDisconsInARow >= 0) - { - DEBUG_LOG(("maxDisconsInARow: %d\n", stats.maxDisconsInARow)); - } - if (stats.lossesInARow >= 0) - { - DEBUG_LOG(("lossesInARow: %d\n", stats.lossesInARow)); - } - if (stats.maxLossesInARow >= 0) - { - DEBUG_LOG(("maxLossesInARow: %d\n", stats.maxLossesInARow)); - } - if (stats.desyncsInARow >= 0) - { - DEBUG_LOG(("desyncsInARow: %d\n", stats.desyncsInARow)); - } - if (stats.maxDesyncsInARow >= 0) - { - DEBUG_LOG(("maxDesyncsInARow: %d\n", stats.maxDesyncsInARow)); - } - - if (stats.lastLadderPort >= 0) - { - DEBUG_LOG(("lastLadderPort: %d\n", stats.lastLadderPort)); - } - - if (stats.lastLadderHost.length()) - { - DEBUG_LOG(("lastLadderHost: %s\n", stats.lastLadderHost.c_str())); - } - - - -} - -//------------------------------------------------------------------------- - -#define INCORPORATE_MAP(x) for (it = other.x.begin(); it != other.x.end(); ++it) \ -{ \ - if (it->second > 0) \ - { \ - x[it->first] = it->second; \ - } \ -} - -void PSPlayerStats::incorporate( const PSPlayerStats& other ) -{ - PerGeneralMap::const_iterator it; - INCORPORATE_MAP(wins); - INCORPORATE_MAP(losses); - INCORPORATE_MAP(games); - INCORPORATE_MAP(duration); - INCORPORATE_MAP(unitsKilled); - INCORPORATE_MAP(unitsLost); - INCORPORATE_MAP(unitsBuilt); - INCORPORATE_MAP(buildingsKilled); - INCORPORATE_MAP(buildingsLost); - INCORPORATE_MAP(buildingsBuilt); - INCORPORATE_MAP(earnings); - INCORPORATE_MAP(techCaptured); - - //GS Clear all disconnects so that we don't retain any that were - //previously reported as 1 by updateAdditionalGameSpyDisconnections - discons.clear(); - INCORPORATE_MAP(discons); - - INCORPORATE_MAP(desyncs); - INCORPORATE_MAP(surrenders); - INCORPORATE_MAP(gamesOf2p); - INCORPORATE_MAP(gamesOf3p); - INCORPORATE_MAP(gamesOf4p); - INCORPORATE_MAP(gamesOf5p); - INCORPORATE_MAP(gamesOf6p); - INCORPORATE_MAP(gamesOf7p); - INCORPORATE_MAP(gamesOf8p); - INCORPORATE_MAP(customGames); - INCORPORATE_MAP(QMGames); - - if (other.locale > 0) - { - locale = other.locale; - } - - if (other.gamesAsRandom > 0) - { - gamesAsRandom = other.gamesAsRandom; - } - - if (other.options.length()) - { - options = other.options; - } - - if (other.systemSpec.length()) - { - systemSpec = other.systemSpec; - } - - if (other.lastFPS > 0.0f) - { - lastFPS = other.lastFPS; - } - - if (other.battleHonors > 0) - { - battleHonors |= other.battleHonors; - } - if (other.challengeMedals > 0) - { - challengeMedals |= other.challengeMedals; - } - if (other.lastGeneral >= 0) - { - lastGeneral = other.lastGeneral; - } - if (other.gamesInRowWithLastGeneral >= 0) - { - gamesInRowWithLastGeneral = other.gamesInRowWithLastGeneral; - } - if (other.builtParticleCannon >= 0) - { - builtParticleCannon = other.builtParticleCannon; - } - if (other.builtNuke >= 0) - { - builtNuke = other.builtNuke; - } - if (other.builtSCUD >= 0) - { - builtSCUD = other.builtSCUD; - } - if (other.winsInARow >= 0) - { - winsInARow = other.winsInARow; - } - if (other.maxWinsInARow >= 0) - { - maxWinsInARow = other.maxWinsInARow; - } - if (other.lossesInARow >= 0) - { - lossesInARow = other.lossesInARow; - } - if (other.maxLossesInARow >= 0) - { - maxLossesInARow = other.maxLossesInARow; - } - if (other.disconsInARow >= 0) - { - disconsInARow = other.disconsInARow; - } - if (other.maxDisconsInARow >= 0) - { - maxDisconsInARow = other.maxDisconsInARow; - } - if (other.desyncsInARow >= 0) - { - desyncsInARow = other.desyncsInARow; - } - if (other.maxDesyncsInARow >= 0) - { - maxDesyncsInARow = other.maxDesyncsInARow; - } - if (other.lastLadderPort >= 0) - { - lastLadderPort = other.lastLadderPort; - } - if (other.lastLadderHost.length()) - { - lastLadderHost = other.lastLadderHost; - } -} - -PSPlayerStats::PSPlayerStats( const PSPlayerStats& other ) -{ - incorporate(other); - id = other.id; - locale = other.locale; - gamesAsRandom = other.gamesAsRandom; - options = other.options; - systemSpec = other.systemSpec; - lastFPS = other.lastFPS; - lastGeneral = other.lastGeneral; - gamesInRowWithLastGeneral = other.gamesInRowWithLastGeneral; - builtParticleCannon = other.builtParticleCannon; - builtNuke = other.builtNuke; - builtSCUD = other.builtSCUD; - challengeMedals = other.challengeMedals; - battleHonors = other.battleHonors; - winsInARow = other.winsInARow; - maxWinsInARow = other.maxWinsInARow; - lossesInARow = other.lossesInARow; - maxLossesInARow = other.maxLossesInARow; - disconsInARow = other.disconsInARow; - maxDisconsInARow = other.maxDisconsInARow; - desyncsInARow = other.desyncsInARow; - maxDesyncsInARow = other.maxDesyncsInARow; - lastLadderHost = other.lastLadderHost; - lastLadderPort = other.lastLadderPort; -} - -//------------------------------------------------------------------------- - -typedef std::queue RequestQueue; -typedef std::queue ResponseQueue; -class PSThreadClass; - -class GameSpyPSMessageQueue : public GameSpyPSMessageQueueInterface -{ -public: - virtual ~GameSpyPSMessageQueue(); - GameSpyPSMessageQueue(); - virtual void startThread( void ); - virtual void endThread( void ); - virtual Bool isThreadRunning( void ); - - virtual void addRequest( const PSRequest& req ); - virtual Bool getRequest( PSRequest& req ); - - virtual void addResponse( const PSResponse& resp ); - virtual Bool getResponse( PSResponse& resp ); - - virtual void trackPlayerStats( PSPlayerStats stats ); - virtual PSPlayerStats findPlayerStatsByID( Int id ); - - PSThreadClass* getThread( void ); - - Int getLocalPlayerID(void) { return m_localPlayerID; } - void setLocalPlayerID(Int localPlayerID) { m_localPlayerID = localPlayerID; } - - std::string getEmail() { return m_email; } - std::string getNick() { return m_nick; } - std::string getPassword() { return m_password; } - - void setEmail(std::string email) { m_email = email; } - void setNick(std::string nick) { m_nick = nick; } - void setPassword(std::string password) { m_password = password; } - -private: - MutexClass m_requestMutex; - MutexClass m_responseMutex; - RequestQueue m_requests; - ResponseQueue m_responses; - PSThreadClass *m_thread; - Int m_localPlayerID; - - std::string m_email; - std::string m_nick; - std::string m_password; - - std::map m_playerStats; -}; - -GameSpyPSMessageQueueInterface* GameSpyPSMessageQueueInterface::createNewMessageQueue( void ) -{ - return NEW GameSpyPSMessageQueue; -} - -GameSpyPSMessageQueueInterface *TheGameSpyPSMessageQueue = NULL; -#define MESSAGE_QUEUE ((GameSpyPSMessageQueue *)TheGameSpyPSMessageQueue) - -//------------------------------------------------------------------------- - -class PSThreadClass : public ThreadClass -{ - -public: - PSThreadClass() : ThreadClass() - { - m_loginOK = m_sawLocalData = m_doneTryingToLogin = false; - m_opCount = 0; - } - - void Thread_Function(); - - void persAuthCallback( Bool val ) { m_loginOK = val; m_doneTryingToLogin = true; } - void decrOpCount( void ) { --m_opCount; } - void incrOpCount( void ) { ++m_opCount; } - Int getOpCount( void ) { return m_opCount; } - Bool sawLocalPlayerData( void ) { return m_sawLocalData; } - void gotLocalPlayerData( void ) { m_sawLocalData = TRUE; } - -private: - Bool tryConnect( void ); - Bool tryLogin( Int id, std::string nick, std::string password, std::string email ); - Bool m_loginOK; - Bool m_doneTryingToLogin; - Int m_opCount; - Bool m_sawLocalData; -}; - - -//------------------------------------------------------------------------- - -GameSpyPSMessageQueue::GameSpyPSMessageQueue() -{ - m_thread = NULL; - m_localPlayerID = 0; -} - -GameSpyPSMessageQueue::~GameSpyPSMessageQueue() -{ - endThread(); -} - -void GameSpyPSMessageQueue::startThread( void ) -{ - if (!m_thread) - { - m_thread = NEW PSThreadClass; - m_thread->Execute(); - } - else - { - if (!m_thread->Is_Running()) - { - m_thread->Execute(); - } - } -} - -void GameSpyPSMessageQueue::endThread( void ) -{ - if (m_thread) - delete m_thread; - m_thread = NULL; -} - -Bool GameSpyPSMessageQueue::isThreadRunning( void ) -{ - return (m_thread) ? m_thread->Is_Running() : false; -} - -void GameSpyPSMessageQueue::addRequest( const PSRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex); - if (m.Failed()) - return; - - m_requests.push(req); -} - -Bool GameSpyPSMessageQueue::getRequest( PSRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex, 0); - if (m.Failed()) - return false; - - if (m_requests.empty()) - return false; - req = m_requests.front(); - m_requests.pop(); - return true; -} - -void GameSpyPSMessageQueue::addResponse( const PSResponse& resp ) -{ - MutexClass::LockClass m(m_responseMutex); - if (m.Failed()) - return; - - m_responses.push(resp); -} - -Bool GameSpyPSMessageQueue::getResponse( PSResponse& resp ) -{ - MutexClass::LockClass m(m_responseMutex, 0); - if (m.Failed()) - return false; - - if (m_responses.empty()) - return false; - resp = m_responses.front(); - m_responses.pop(); - return true; -} - -PSThreadClass* GameSpyPSMessageQueue::getThread( void ) -{ - return m_thread; -} - -void GameSpyPSMessageQueue::trackPlayerStats( PSPlayerStats stats ) -{ -#ifdef DEBUG_LOGGING - debugDumpPlayerStats( stats ); - DEBUG_ASSERTCRASH(stats.id != 0, ("Tracking stats with ID of 0\n")); -#endif - PSPlayerStats newStats; - std::map::iterator it = m_playerStats.find(stats.id); - if (it != m_playerStats.end()) - { - newStats = it->second; - newStats.incorporate(stats); - m_playerStats[stats.id] = newStats; - } - else - { - m_playerStats[stats.id] = stats; - } -} - -PSPlayerStats GameSpyPSMessageQueue::findPlayerStatsByID( Int id ) -{ - std::map::iterator it = m_playerStats.find(id); - if (it != m_playerStats.end()) - { - return it->second; - } - - PSPlayerStats empty; - empty.id = 0; - return empty; -} - -//------------------------------------------------------------------------- - -Bool PSThreadClass::tryConnect( void ) -{ - Int result; - - DEBUG_LOG(("m_opCount = %d - opening connection\n", m_opCount)); - - if (IsStatsConnected()) - { - DEBUG_LOG(("connection already open!\n")); - return true; - } - - // this may block for 1-2 seconds (according to GS) so it's nice we're not in the UI thread :) - result = InitStatsConnection(0); - -#ifdef DEBUG_LOGGING - static const char *retValStrings[6] = { - "GE_NOERROR", - "GE_NOSOCKET", - "GE_NODNS", - "GE_NOCONNECT", - "GE_BUSY", - "GE_DATAERROR" - }; -#endif // DEBUG_LOGGING - - if (result != GE_NOERROR) - { - DEBUG_LOG(("InitStatsConnection() returned %d (%s)\n", result, retValStrings[result])); - return false; - } - else - { - DEBUG_LOG(("InitStatsConnection() succeeded\n")); - } - - return true; -} - -static void persAuthCallback(int localid, int profileid, int authenticated, char *errmsg, void *instance) -{ - PSThreadClass *t = (PSThreadClass *)instance; - DEBUG_LOG(("Auth callback: localid: %d profileid: %d auth: %d err: %s\n",localid, profileid, authenticated, errmsg)); - if (t) - t->persAuthCallback(authenticated != 0); -} - -Bool PSThreadClass::tryLogin( Int id, std::string nick, std::string password, std::string email ) -{ - char validate[33]; - DEBUG_LOG(("PSThreadClass::tryLogin id = %d, nick = %s, password = %s, email = %s\n", id, nick.c_str(), password.c_str(), email.c_str())); - /*********** - We'll go ahead and start the authentication, using a Presence & Messaging SDK - profileid / password. To generate the new validation token, we'll need to pass - in the password for the profile we are authenticating. - Again, if this is done in a client/server setting, with the Persistent Storage - access being done on the server, and the P&M SDK is used on the client, the - server will need to send the challenge (GetChallenge(NULL)) to the client, the - client will create the validation token using GenerateAuth, and send it - back to the server for use in PreAuthenticatePlayerPM - ***********/ - char *munkeeHack = strdup(password.c_str()); // GenerateAuth takes a char*, not a const char* :P - GenerateAuth(GetChallenge(NULL), munkeeHack, validate); - free (munkeeHack); - - /************ - After we get the validation token, we pass it and the profileid of the user - we are authenticating into PreAuthenticatePlayerPM. - We pass the same authentication callback as for the first user, but a different - localid this time. - ************/ - m_loginOK = false; - m_doneTryingToLogin = false; - PreAuthenticatePlayerPM(id, id, validate, ::persAuthCallback, this); - while (!m_doneTryingToLogin && IsStatsConnected()) - PersistThink(); - DEBUG_LOG(("Persistant Storage Login success %d\n", m_loginOK)); - return m_loginOK; -} - -static void getPersistentDataCallback(int localid, int profileid, persisttype_t type, int index, int success, time_t modified, char *data, int len, void *instance) -{ - DEBUG_LOG(("Data get callback: localid: %d profileid: %d success: %d len: %d data: %s\n",localid, profileid, success, len, data)); - PSThreadClass *t = (PSThreadClass *)instance; - if (!t) - return; - - t->decrOpCount(); - - PSResponse resp; - - if (!success) - { - resp.responseType = PSResponse::PSRESPONSE_COULDNOTCONNECT; - resp.player.id = profileid; - TheGameSpyPSMessageQueue->addResponse(resp); - if (!t->getOpCount() && !t->sawLocalPlayerData()) - { - // we haven't gotten stats for ourselves - try again - DEBUG_LOG(("Requesting retry for reading local player's stats\n")); - PSRequest req; - req.requestType = PSRequest::PSREQUEST_READPLAYERSTATS; - req.player.id = MESSAGE_QUEUE->getLocalPlayerID(); - TheGameSpyPSMessageQueue->addRequest(req); - } - return; - } - - if (profileid == MESSAGE_QUEUE->getLocalPlayerID()) - { - t->gotLocalPlayerData(); - DEBUG_LOG(("getPersistentDataCallback() - got local player info\n")); - - // check if we have discons we should update on the server - UserPreferences pref; - AsciiString userPrefFilename; - userPrefFilename.format("GeneralsOnline\\MiscPref%d.ini", MESSAGE_QUEUE->getLocalPlayerID()); - DEBUG_LOG(("using the file %s\n", userPrefFilename.str())); - pref.load(userPrefFilename); - Int addedInDesyncs2 = pref.getInt("0", 0); - DEBUG_LOG(("addedInDesyncs2 = %d\n", addedInDesyncs2)); - if (addedInDesyncs2 < 0) - addedInDesyncs2 = 10; - Int addedInDesyncs3 = pref.getInt("1", 0); - DEBUG_LOG(("addedInDesyncs3 = %d\n", addedInDesyncs3)); - if (addedInDesyncs3 < 0) - addedInDesyncs3 = 10; - Int addedInDesyncs4 = pref.getInt("2", 0); - DEBUG_LOG(("addedInDesyncs4 = %d\n", addedInDesyncs4)); - if (addedInDesyncs4 < 0) - addedInDesyncs4 = 10; - Int addedInDiscons2 = pref.getInt("3", 0); - DEBUG_LOG(("addedInDiscons2 = %d\n", addedInDiscons2)); - if (addedInDiscons2 < 0) - addedInDiscons2 = 10; - Int addedInDiscons3 = pref.getInt("4", 0); - DEBUG_LOG(("addedInDiscons3 = %d\n", addedInDiscons3)); - if (addedInDiscons3 < 0) - addedInDiscons3 = 10; - Int addedInDiscons4 = pref.getInt("5", 0); - DEBUG_LOG(("addedInDiscons4 = %d\n", addedInDiscons4)); - if (addedInDiscons4 < 0) - addedInDiscons4 = 10; - - DEBUG_LOG(("addedInDesync=%d,%d,%d, addedInDiscon=%d,%d,%d\n", - addedInDesyncs2, addedInDesyncs3, addedInDesyncs4, - addedInDiscons2, addedInDiscons3, addedInDiscons4)); - - if (addedInDesyncs2 || addedInDesyncs3 || addedInDesyncs4 || addedInDiscons2 || addedInDiscons3 || addedInDiscons4) - { - DEBUG_LOG(("We have a previous discon we can attempt to update! Bummer...\n")); - - PSRequest req; - req.requestType = PSRequest::PSREQUEST_UPDATEPLAYERSTATS; - req.email = MESSAGE_QUEUE->getEmail(); - req.nick = MESSAGE_QUEUE->getNick(); - req.password = MESSAGE_QUEUE->getPassword(); - req.player = GameSpyPSMessageQueueInterface::parsePlayerKVPairs((len)?data:""); - req.player.id = profileid; - req.addDesync = FALSE; - req.addDiscon = FALSE; - req.lastHouse = 0; - TheGameSpyPSMessageQueue->addRequest(req); - } - } - - resp.responseType = PSResponse::PSRESPONSE_PLAYERSTATS; - resp.player = GameSpyPSMessageQueueInterface::parsePlayerKVPairs((len)?data:""); - resp.player.id = profileid; - - TheGameSpyPSMessageQueue->addResponse(resp); -} - -static void setPersistentDataLocaleCallback(int localid, int profileid, persisttype_t type, int index, int success, time_t modified, void *instance) -{ - DEBUG_LOG(("Data save callback: localid: %d profileid: %d success: %d\n", localid, profileid, success)); - - PSThreadClass *t = (PSThreadClass *)instance; - if (!t) - return; - - t->decrOpCount(); -} - -static void setPersistentDataCallback(int localid, int profileid, persisttype_t type, int index, int success, time_t modified, void *instance) -{ - DEBUG_LOG(("Data save callback: localid: %d profileid: %d success: %d\n", localid, profileid, success)); - - PSThreadClass *t = (PSThreadClass *)instance; - if (!t) - return; - - if (success) - { - UserPreferences pref; - AsciiString userPrefFilename; - userPrefFilename.format("GeneralsOnline\\MiscPref%d.ini", profileid); - DEBUG_LOG(("setPersistentDataCallback - writing stats to file %s\n", userPrefFilename.str())); - pref.load(userPrefFilename); - pref.clear(); - pref.write(); - } - t->decrOpCount(); -} - -struct CDAuthInfo -{ - Bool success; - Bool done; - Int id; -}; - -void preAuthCDCallback(int localid, int profileid, int authenticated, char *errmsg, void *instance) -{ - DEBUG_LOG(("preAuthCDCallback(): profileid: %d auth: %d err: %s\n", profileid, authenticated, errmsg)); - - CDAuthInfo *authInfo = (CDAuthInfo *)instance; - authInfo->success = authenticated; - authInfo->done = TRUE; - authInfo->id = profileid; -} - -static void getPreorderCallback(int localid, int profileid, persisttype_t type, int index, int success, time_t modified, char *data, int len, void *instance) -{ - PSThreadClass *t = (PSThreadClass *)instance; - if (!t) - return; - - t->decrOpCount(); - - PSResponse resp; - - if (!success) - { - DEBUG_LOG(("Failed getPreorderCallback()\n")); - return; - } - - resp.responseType = PSResponse::PSRESPONSE_PREORDER; - resp.preorder = (data && strcmp(data, "\\preorder\\1") == 0); - DEBUG_LOG(("getPreorderCallback() - data was '%s'\n", data)); - - TheGameSpyPSMessageQueue->addResponse(resp); -} - -void PSThreadClass::Thread_Function() -{ - try { - _set_se_translator( DumpExceptionInfo ); // Hook that allows stack trace. - /********* - First step, set our game authentication info - We could do: - strcpy(gcd_gamename,"ccgenerals"); - strcpy(gcd_secret_key,"h5T2f6"); - or - strcpy(gcd_gamename,"ccgeneralsb"); - strcpy(gcd_secret_key,"g3T9s2"); - ...but this is more secure: - **********/ - /** - gcd_gamename[0]='c';gcd_gamename[1]='c';gcd_gamename[2]='g';gcd_gamename[3]='e'; - gcd_gamename[4]='n';gcd_gamename[5]='e';gcd_gamename[6]='r';gcd_gamename[7]='a'; - gcd_gamename[8]='l';gcd_gamename[9]='s';gcd_gamename[10]='b';gcd_gamename[11]='\0'; - gcd_secret_key[0]='g';gcd_secret_key[1]='3';gcd_secret_key[2]='T';gcd_secret_key[3]='9'; - gcd_secret_key[4]='s';gcd_secret_key[5]='2';gcd_secret_key[6]='\0'; - /**/ - gcd_gamename[0]='c';gcd_gamename[1]='c';gcd_gamename[2]='g';gcd_gamename[3]='e'; - gcd_gamename[4]='n';gcd_gamename[5]='e';gcd_gamename[6]='r';gcd_gamename[7]='a'; - gcd_gamename[8]='l';gcd_gamename[9]='s';gcd_gamename[10]='\0'; - gcd_secret_key[0]='h';gcd_secret_key[1]='5';gcd_secret_key[2]='T';gcd_secret_key[3]='2'; - gcd_secret_key[4]='f';gcd_secret_key[5]='6';gcd_secret_key[6]='\0'; - /**/ - - //strcpy(StatsServerHostname, "sdkdev.gamespy.com"); - - PSRequest req; - while ( running ) - { - // deal with requests - if (TheGameSpyPSMessageQueue->getRequest(req)) - { - switch (req.requestType) - { - case PSRequest::PSREQUEST_SENDGAMERESTOGAMESPY: - { - if (tryConnect()) - { - NewGame(0); -#ifdef DEBUG_LOGGING - Int res = -#endif // DEBUG_LOGGING - SendGameSnapShot(NULL, req.results.c_str(), SNAP_FINAL); - DEBUG_LOG(("Just sent game results - res was %d\n", res)); - FreeGame(NULL); - } - } - break; - case PSRequest::PSREQUEST_READPLAYERSTATS: - { - Bool initialConnection = FALSE; - if (!MESSAGE_QUEUE->getLocalPlayerID()) - { - MESSAGE_QUEUE->setLocalPlayerID(req.player.id); // first request is for ourselves - MESSAGE_QUEUE->setEmail(req.email); - MESSAGE_QUEUE->setNick(req.nick); - MESSAGE_QUEUE->setPassword(req.password); - DEBUG_LOG(("Setting email/nick/password = %s/%s/%s\n", req.email.c_str(), req.nick.c_str(), req.password.c_str())); - initialConnection = TRUE; - } - DEBUG_LOG(("Processing PSRequest::PSREQUEST_READPLAYERSTATS\n")); - if (tryConnect()) - { - DEBUG_LOG(("Successful login\n")); - incrOpCount(); - GetPersistDataValues(0, req.player.id, pd_public_rw, 0, "", getPersistentDataCallback, this); - } - else - { - DEBUG_LOG(("Unsuccessful login - retry=%d\n", initialConnection)); - PSResponse resp; - resp.responseType = PSResponse::PSRESPONSE_COULDNOTCONNECT; - resp.player.id = req.player.id; - TheGameSpyPSMessageQueue->addResponse(resp); - if (initialConnection) - { - // we haven't gotten stats for ourselves - try again - DEBUG_LOG(("Requesting retry for reading local player's stats\n")); - PSRequest req; - req.requestType = PSRequest::PSREQUEST_READPLAYERSTATS; - req.player.id = MESSAGE_QUEUE->getLocalPlayerID(); - TheGameSpyPSMessageQueue->addRequest(req); - } - } - } - break; - case PSRequest::PSREQUEST_UPDATEPLAYERLOCALE: - { - DEBUG_LOG(("Processing PSRequest::PSREQUEST_UPDATEPLAYERLOCALE\n")); - if (tryConnect() && tryLogin(req.player.id, req.nick, req.password, req.email)) - { - char kvbuf[256]; - sprintf(kvbuf, "\\locale\\%d", req.player.locale); - incrOpCount(); - SetPersistDataValues(0, req.player.id, pd_public_rw, 0, kvbuf, setPersistentDataLocaleCallback, this); - } - } - break; - case PSRequest::PSREQUEST_UPDATEPLAYERSTATS: - { - /* - ** NOTE THAT THIS IS HIGHLY DEPENDENT ON INI ORDERING FOR THE PLAYERTEMPLATES!!! - */ - DEBUG_LOG(("Processing PSRequest::PSREQUEST_UPDATEPLAYERSTATS\n")); - UserPreferences pref; - AsciiString userPrefFilename; - userPrefFilename.format("GeneralsOnline\\MiscPref%d.ini", MESSAGE_QUEUE->getLocalPlayerID()); - DEBUG_LOG(("using the file %s\n", userPrefFilename.str())); - pref.load(userPrefFilename); - Int addedInDesyncs2 = pref.getInt("0", 0); - DEBUG_LOG(("addedInDesyncs2 = %d\n", addedInDesyncs2)); - if (addedInDesyncs2 < 0) - addedInDesyncs2 = 10; - Int addedInDesyncs3 = pref.getInt("1", 0); - DEBUG_LOG(("addedInDesyncs3 = %d\n", addedInDesyncs3)); - if (addedInDesyncs3 < 0) - addedInDesyncs3 = 10; - Int addedInDesyncs4 = pref.getInt("2", 0); - DEBUG_LOG(("addedInDesyncs4 = %d\n", addedInDesyncs4)); - if (addedInDesyncs4 < 0) - addedInDesyncs4 = 10; - Int addedInDiscons2 = pref.getInt("3", 0); - DEBUG_LOG(("addedInDiscons2 = %d\n", addedInDiscons2)); - if (addedInDiscons2 < 0) - addedInDiscons2 = 10; - Int addedInDiscons3 = pref.getInt("4", 0); - DEBUG_LOG(("addedInDiscons3 = %d\n", addedInDiscons3)); - if (addedInDiscons3 < 0) - addedInDiscons3 = 10; - Int addedInDiscons4 = pref.getInt("5", 0); - DEBUG_LOG(("addedInDiscons4 = %d\n", addedInDiscons4)); - if (addedInDiscons4 < 0) - addedInDiscons4 = 10; - - DEBUG_LOG(("req.addDesync=%d, req.addDiscon=%d, addedInDesync=%d,%d,%d, addedInDiscon=%d,%d,%d\n", - req.addDesync, req.addDiscon, addedInDesyncs2, addedInDesyncs3, addedInDesyncs4, - addedInDiscons2, addedInDiscons3, addedInDiscons4)); - - if (req.addDesync || req.addDiscon) - { - AsciiString val; - if (req.lastHouse == 2) - { - val.format("%d", addedInDesyncs2 + req.addDesync); - pref["0"] = val; - val.format("%d", addedInDiscons2 + req.addDiscon); - pref["3"] = val; - DEBUG_LOG(("house 2 req.addDesync || req.addDiscon: %d %d\n", - addedInDesyncs2 + req.addDesync, addedInDiscons2 + req.addDiscon)); - } - else if (req.lastHouse == 3) - { - val.format("%d", addedInDesyncs3 + req.addDesync); - pref["1"] = val; - val.format("%d", addedInDiscons3 + req.addDiscon); - pref["4"] = val; - DEBUG_LOG(("house 3 req.addDesync || req.addDiscon: %d %d\n", - addedInDesyncs3 + req.addDesync, addedInDiscons3 + req.addDiscon)); - } - else - { - val.format("%d", addedInDesyncs4 + req.addDesync); - pref["2"] = val; - val.format("%d", addedInDiscons4 + req.addDiscon); - pref["5"] = val; - DEBUG_LOG(("house 4 req.addDesync || req.addDiscon: %d %d\n", - addedInDesyncs4 + req.addDesync, addedInDiscons4 + req.addDiscon)); - } - pref.write(); - if (req.password.size() == 0) - return; - } - if (!req.player.id) - { - DEBUG_LOG(("Bailing because ID is NULL!\n")); - return; - } - req.player.desyncs[2] += addedInDesyncs2; - req.player.games[2] += addedInDesyncs2; - req.player.discons[2] += addedInDiscons2; - req.player.games[2] += addedInDiscons2; - req.player.desyncs[3] += addedInDesyncs3; - req.player.games[3] += addedInDesyncs3; - req.player.discons[3] += addedInDiscons3; - req.player.games[3] += addedInDiscons3; - req.player.desyncs[4] += addedInDesyncs4; - req.player.games[4] += addedInDesyncs4; - req.player.discons[4] += addedInDiscons4; - req.player.games[4] += addedInDiscons4; - DEBUG_LOG(("House2: %d/%d/%d, House3: %d/%d/%d, House4: %d/%d/%d\n", - req.player.desyncs[2], req.player.discons[2], req.player.games[2], - req.player.desyncs[3], req.player.discons[3], req.player.games[3], - req.player.desyncs[4], req.player.discons[4], req.player.games[4] - )); - if (tryConnect() && tryLogin(req.player.id, req.nick, req.password, req.email)) - { - DEBUG_LOG(("Logged in!\n")); - if (TheGameSpyPSMessageQueue) - TheGameSpyPSMessageQueue->trackPlayerStats(req.player); - - char *munkeeHack = strdup(GameSpyPSMessageQueueInterface::formatPlayerKVPairs(req.player).c_str()); // GS takes a char* for some reason - incrOpCount(); - DEBUG_LOG(("Setting values %s\n", munkeeHack)); - SetPersistDataValues(0, req.player.id, pd_public_rw, 0, munkeeHack, setPersistentDataCallback, this); - free(munkeeHack); - } - else - { - DEBUG_LOG(("Cannot connect!\n")); - //if (IsStatsConnected()) - //CloseStatsConnection(); - } - } - break; - case PSRequest::PSREQUEST_READCDKEYSTATS: - { - DEBUG_LOG(("Processing PSRequest::PSREQUEST_READCDKEYSTATS\n")); - if (tryConnect()) - { - incrOpCount(); - CDAuthInfo cdAuthInfo; - cdAuthInfo.done = FALSE; - cdAuthInfo.success = FALSE; - cdAuthInfo.id = 0; - char cdkeyHash[33] = ""; - char validationToken[33] = ""; - char *munkeeHack = strdup(req.cdkey.c_str()); // GenerateAuth takes a char*, not a const char* :P - - GenerateAuth(GetChallenge(NULL), munkeeHack, validationToken); // validation token - GenerateAuth("", munkeeHack, cdkeyHash); // cdkey hash - - free (munkeeHack); - - PreAuthenticatePlayerCD( 0, "preorder", cdkeyHash, validationToken, preAuthCDCallback , &cdAuthInfo); - - while (running && IsStatsConnected() && !cdAuthInfo.done) - PersistThink(); - - DEBUG_LOG(("Looking for preorder status for %d (success=%d, done=%d) from CDKey %s with hash %s\n", - cdAuthInfo.id, cdAuthInfo.success, cdAuthInfo.done, req.cdkey.c_str(), cdkeyHash)); - if (cdAuthInfo.done && cdAuthInfo.success) - GetPersistDataValues(0, cdAuthInfo.id, pd_public_ro, 0, "\\preorder", getPreorderCallback, this); - else - decrOpCount(); - } - } - break; - } - } - - // update the network - if (IsStatsConnected()) - { - PersistThink(); - if (m_opCount <= 0) - { - DEBUG_ASSERTCRASH(m_opCount == 0, ("Negative operations pending!!!")); - DEBUG_LOG(("m_opCount = %d - closing connection\n", m_opCount)); - CloseStatsConnection(); - m_opCount = 0; - } - } - - // end our timeslice - Switch_Thread(); - } - - if (IsStatsConnected()) - CloseStatsConnection(); - } catch ( ... ) { - DEBUG_CRASH(("Exception in storage thread!")); - } -} - -//------------------------------------------------------------------------- -PSPlayerStats::PSPlayerStats( void ) -{ - reset(); -} - -void PSPlayerStats::reset( void ) -{ - id = 0; - locale = 0; - gamesAsRandom = 0; - lastFPS = 0; - lastGeneral = 0; - gamesInRowWithLastGeneral = 0; - builtNuke = 0; - builtSCUD = 0; - builtParticleCannon = 0; - challengeMedals = 0; - battleHonors = 0; - winsInARow = 0; - maxWinsInARow = 0; - lossesInARow = 0; - maxLossesInARow = 0; - disconsInARow = 0; - maxDisconsInARow = 0; - desyncsInARow = 0; - maxDesyncsInARow = 0; - lastLadderPort = 0; - - //Added By Sadullah Nader - maxQMwinsInARow = 0; - QMwinsInARow = 0; - // -} - -//------------------------------------------------------------------------- -#define CHECK(x) if (k == #x && generalMarker >= 0) { s.x[generalMarker] = atoi(v.c_str()); continue; } - -PSPlayerStats GameSpyPSMessageQueueInterface::parsePlayerKVPairs( std::string kvPairs ) -{ - PSPlayerStats s; - kvPairs.append("\\"); - - Int offset = 0; - while (1) - { - Int firstMarker = kvPairs.find_first_of('\\', offset); - if (firstMarker < 0) - break; - Int secondMarker = kvPairs.find_first_of('\\', firstMarker + 1); - if (secondMarker < 0) - break; - Int thirdMarker = kvPairs.find_first_of('\\', secondMarker + 1); - if (thirdMarker < 0) - break; - Int generalMarker = kvPairs.find_last_not_of("0123456789", secondMarker - 1); - std::string k, v, g; - if (generalMarker == secondMarker - 1) - { - k = kvPairs.substr(firstMarker + 1, secondMarker - firstMarker - 1); - generalMarker = -1; - } - else - { - k = kvPairs.substr(firstMarker + 1, generalMarker - firstMarker); - g = kvPairs.substr(generalMarker + 1, secondMarker - generalMarker - 1); - generalMarker = atoi(g.c_str()); - } - v = kvPairs.substr(secondMarker + 1, thirdMarker - secondMarker - 1); - //DEBUG_LOG(("%d [%s] [%s]\n", generalMarker, k.c_str(), v.c_str())); - offset = thirdMarker - 1; - - CHECK(wins); - CHECK(losses); - CHECK(games); - CHECK(duration); - CHECK(unitsKilled); - CHECK(unitsLost); - CHECK(unitsBuilt); - CHECK(buildingsKilled); - CHECK(buildingsLost); - CHECK(buildingsBuilt); - CHECK(earnings); - CHECK(techCaptured); - CHECK(discons); - CHECK(desyncs); - CHECK(surrenders); - CHECK(gamesOf2p); - CHECK(gamesOf3p); - CHECK(gamesOf4p); - CHECK(gamesOf5p); - CHECK(gamesOf6p); - CHECK(gamesOf7p); - CHECK(gamesOf8p); - CHECK(customGames); - CHECK(QMGames); - - if (k == "locale" && generalMarker < 0) - { - s.locale = atoi(v.c_str()); - continue; - } - - if (k == "random" && generalMarker < 0) - { - s.gamesAsRandom = atoi(v.c_str()); - continue; - } - - if (k == "options" && generalMarker < 0) - { - s.options = v; - continue; - } - - if (k == "systemSpec" && generalMarker < 0) - { - s.systemSpec = v; - continue; - } - - if (k == "fps" && generalMarker < 0) - { - s.lastFPS = atof(v.c_str()); - continue; - } - - if (k == "lastGeneral" && generalMarker < 0) - { - s.lastGeneral = atoi(v.c_str()); - continue; - } - if (k == "genInRow" && generalMarker < 0) - { - s.gamesInRowWithLastGeneral = atoi(v.c_str()); - continue; - } - if (k == "builtNuke" && generalMarker < 0) - { - s.builtNuke = atoi(v.c_str()); - continue; - } - if (k == "builtSCUD" && generalMarker < 0) - { - s.builtSCUD = atoi(v.c_str()); - continue; - } - if (k == "builtCannon" && generalMarker < 0) - { - s.builtParticleCannon = atoi(v.c_str()); - continue; - } - if (k == "challenge" && generalMarker < 0) - { - s.challengeMedals = atoi(v.c_str()); - continue; - } - if (k == "battle" && generalMarker < 0) - { - s.battleHonors = atoi(v.c_str()); - continue; - } - - if (k == "WinRow" && generalMarker < 0) - { - s.winsInARow = atoi(v.c_str()); - continue; - } - if (k == "WinRowMax" && generalMarker < 0) - { - s.maxWinsInARow = atoi(v.c_str()); - continue; - } - - if (k == "LossRow" && generalMarker < 0) - { - s.lossesInARow = atoi(v.c_str()); - continue; - } - if (k == "LossRowMax" && generalMarker < 0) - { - s.maxLossesInARow = atoi(v.c_str()); - continue; - } - - if (k == "DSRow" && generalMarker < 0) - { - s.desyncsInARow = atoi(v.c_str()); - continue; - } - if (k == "DSRowMax" && generalMarker < 0) - { - s.maxDesyncsInARow = atoi(v.c_str()); - continue; - } - - if (k == "DCRow" && generalMarker < 0) - { - s.disconsInARow = atoi(v.c_str()); - continue; - } - if (k == "DCRowMax" && generalMarker < 0) - { - s.maxDisconsInARow = atoi(v.c_str()); - continue; - } - - if (k == "ladderPort" && generalMarker < 0) - { - s.lastLadderPort = atoi(v.c_str()); - continue; - } - if (k == "ladderHost" && generalMarker < 0) - { - s.lastLadderHost = v; - continue; - } - - //DEBUG_ASSERTCRASH(generalMarker >= 0, ("Unknown KV Pair in persistent storage: [%s] = [%s]\n", k.c_str(), v.c_str())); - //DEBUG_ASSERTCRASH(generalMarker < 0, ("Unknown KV Pair in persistent storage for PlayerTemplate %d: [%s] = [%s]\n", generalMarker, k.c_str(), v.c_str())); - } - - return s; -} - -#define ITERATE_OVER(x) for (it = stats.x.begin(); it != stats.x.end(); ++it) \ -{ \ - if (it->second > 0) \ - { \ - sprintf(kvbuf, "\\" #x "%d\\%d", it->first, it->second); \ - s.append(kvbuf); \ - } \ -} - -std::string GameSpyPSMessageQueueInterface::formatPlayerKVPairs( PSPlayerStats stats ) -{ - char kvbuf[256]; - std::string s = ""; - PerGeneralMap::iterator it; - - ITERATE_OVER(wins); - ITERATE_OVER(losses); - ITERATE_OVER(games); - ITERATE_OVER(duration); - ITERATE_OVER(unitsKilled); - ITERATE_OVER(unitsLost); - ITERATE_OVER(unitsBuilt); - ITERATE_OVER(buildingsKilled); - ITERATE_OVER(buildingsLost); - ITERATE_OVER(buildingsBuilt); - ITERATE_OVER(earnings); - ITERATE_OVER(techCaptured); - - //GS Report all disconnects, even if zero, because might have been - //previously reported as 1 by updateAdditionalGameSpyDisconnections -// ITERATE_OVER(discons); - for (Int ptIdx = 0; ptIdx < ThePlayerTemplateStore->getPlayerTemplateCount(); ++ptIdx) - { -// const PlayerTemplate* pTemplate = ThePlayerTemplateStore->getNthPlayerTemplate(ptIdx); -// const GeneralPersona* pGeneral = TheChallengeGenerals->getGeneralByTemplateName(pTemplate->getName()); -// BOOL isReported = pGeneral ? pGeneral->isStartingEnabled() : FALSE; -// if( !isReported ) -// continue; //don't report unplayable templates (observer, boss, etc.) - - sprintf(kvbuf, "\\discons%d\\%d", ptIdx, stats.discons[ptIdx]); - s.append(kvbuf); - } - - ITERATE_OVER(desyncs); - ITERATE_OVER(surrenders); - ITERATE_OVER(gamesOf2p); - ITERATE_OVER(gamesOf3p); - ITERATE_OVER(gamesOf4p); - ITERATE_OVER(gamesOf5p); - ITERATE_OVER(gamesOf6p); - ITERATE_OVER(gamesOf7p); - ITERATE_OVER(gamesOf8p); - ITERATE_OVER(customGames); - ITERATE_OVER(QMGames); - - if (stats.locale > 0) - { - sprintf(kvbuf, "\\locale\\%d", stats.locale); - s.append(kvbuf); - } - - if (stats.gamesAsRandom > 0) - { - sprintf(kvbuf, "\\random\\%d", stats.gamesAsRandom); - s.append(kvbuf); - } - - if (stats.options.length()) - { - _snprintf(kvbuf, 256, "\\options\\%s", stats.options.c_str()); - kvbuf[255] = 0; - s.append(kvbuf); - } - - if (stats.systemSpec.length()) - { - _snprintf(kvbuf, 256, "\\systemSpec\\%s", stats.systemSpec.c_str()); - kvbuf[255] = 0; - s.append(kvbuf); - } - - if (stats.lastFPS > 0.0f) - { - sprintf(kvbuf, "\\fps\\%g", stats.lastFPS); - s.append(kvbuf); - } - if (stats.lastGeneral >= 0) - { - sprintf(kvbuf, "\\lastGeneral\\%d", stats.lastGeneral); - s.append(kvbuf); - } - if (stats.gamesInRowWithLastGeneral >= 0) - { - sprintf(kvbuf, "\\genInRow\\%d", stats.gamesInRowWithLastGeneral); - s.append(kvbuf); - } - if (stats.builtParticleCannon >= 0) - { - sprintf(kvbuf, "\\builtCannon\\%d", stats.builtParticleCannon); - s.append(kvbuf); - } - if (stats.builtNuke >= 0) - { - sprintf(kvbuf, "\\builtNuke\\%d", stats.builtNuke); - s.append(kvbuf); - } - if (stats.builtSCUD >= 0) - { - sprintf(kvbuf, "\\builtSCUD\\%d", stats.builtSCUD); - s.append(kvbuf); - } - if (stats.challengeMedals > 0) - { - sprintf(kvbuf, "\\challenge\\%d", stats.challengeMedals); - s.append(kvbuf); - } - if (stats.battleHonors > 0) - { - sprintf(kvbuf, "\\battle\\%d", stats.battleHonors); - s.append(kvbuf); - } - - //if (stats.winsInARow > 0) - { - sprintf(kvbuf, "\\WinRow\\%d", stats.winsInARow); - s.append(kvbuf); - } - if (stats.maxWinsInARow > 0) - { - sprintf(kvbuf, "\\WinRowMax\\%d", stats.maxWinsInARow); - s.append(kvbuf); - } - - //if (stats.lossesInARow > 0) - { - sprintf(kvbuf, "\\LossRow\\%d", stats.lossesInARow); - s.append(kvbuf); - } - if (stats.maxLossesInARow > 0) - { - sprintf(kvbuf, "\\LossRowMax\\%d", stats.maxLossesInARow); - s.append(kvbuf); - } - - //if (stats.disconsInARow > 0) - { - sprintf(kvbuf, "\\DCRow\\%d", stats.disconsInARow); - s.append(kvbuf); - } - if (stats.maxDisconsInARow > 0) - { - sprintf(kvbuf, "\\DCRowMax\\%d", stats.maxDisconsInARow); - s.append(kvbuf); - } - - //if (stats.desyncsInARow > 0) - { - sprintf(kvbuf, "\\DSRow\\%d", stats.desyncsInARow); - s.append(kvbuf); - } - if (stats.maxDesyncsInARow > 0) - { - sprintf(kvbuf, "\\DSRowMax\\%d", stats.maxDesyncsInARow); - s.append(kvbuf); - } - - if (stats.lastLadderPort > 0) - { - sprintf(kvbuf, "\\ladderPort\\%d", stats.lastLadderPort); - s.append(kvbuf); - } - if (stats.lastLadderHost.length()) - { - _snprintf(kvbuf, 256, "\\ladderHost\\%s", stats.lastLadderHost.c_str()); - kvbuf[255] = 0; - s.append(kvbuf); - } - - DEBUG_LOG(("Formatted persistent values as '%s'\n", s.c_str())); - return s; -} - -//------------------------------------------------------------------------- diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PingThread.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PingThread.cpp deleted file mode 100644 index ea814f758a4..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PingThread.cpp +++ /dev/null @@ -1,575 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PingThread.cpp ////////////////////////////////////////////////////// -// Ping thread -// Author: Matthew D. Campbell, August 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include // This one has to be here. Prevents collisions with windsock2.h - -#include "GameNetwork/GameSpy/PingThread.h" -#include "mutex.h" -#include "thread.h" - -#include "Common/StackDump.h" -#include "Common/SubsystemInterface.h" - -//------------------------------------------------------------------------- - -static const Int NumWorkerThreads = 10; - -typedef std::queue RequestQueue; -typedef std::queue ResponseQueue; -class PingThreadClass; - -class Pinger : public PingerInterface -{ -public: - virtual ~Pinger(); - Pinger(); - virtual void startThreads( void ); - virtual void endThreads( void ); - virtual Bool areThreadsRunning( void ); - - virtual void addRequest( const PingRequest& req ); - virtual Bool getRequest( PingRequest& resp ); - - virtual void addResponse( const PingResponse& resp ); - virtual Bool getResponse( PingResponse& resp ); - - virtual Bool arePingsInProgress( void ); - virtual Int getPing( AsciiString hostname ); - - virtual void clearPingMap( void ); - virtual AsciiString getPingString( Int timeout ); - -private: - MutexClass m_requestMutex; - MutexClass m_responseMutex; - MutexClass m_pingMapMutex; - RequestQueue m_requests; - ResponseQueue m_responses; - Int m_requestCount; - Int m_responseCount; - - std::map m_pingMap; - - PingThreadClass *m_workerThreads[NumWorkerThreads]; -}; - -PingerInterface* PingerInterface::createNewPingerInterface( void ) -{ - return NEW Pinger; -} - -PingerInterface *ThePinger; - -//------------------------------------------------------------------------- - -class PingThreadClass : public ThreadClass -{ - -public: - PingThreadClass() : ThreadClass() {} - - void Thread_Function(); - -private: - Int doPing( UnsignedInt IP, Int timeout ); -}; - - -//------------------------------------------------------------------------- - -Pinger::Pinger() : m_requestCount(0), m_responseCount(0) -{ - for (Int i=0; iExecute(); - } -} - -void Pinger::endThreads( void ) -{ - for (Int i=0; iIs_Running()) - return true; - } - } - return false; -} - -void Pinger::addRequest( const PingRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex); - - ++m_requestCount; - m_requests.push(req); -} - -Bool Pinger::getRequest( PingRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex, 0); - if (m.Failed()) - return false; - - if (m_requests.empty()) - return false; - req = m_requests.front(); - m_requests.pop(); - return true; -} - -void Pinger::addResponse( const PingResponse& resp ) -{ - { - MutexClass::LockClass m(m_pingMapMutex); - - m_pingMap[resp.hostname] = resp.avgPing; - } - { - MutexClass::LockClass m(m_responseMutex); - - ++m_responseCount; - m_responses.push(resp); - } -} - -Bool Pinger::getResponse( PingResponse& resp ) -{ - MutexClass::LockClass m(m_responseMutex, 0); - if (m.Failed()) - return false; - - if (m_responses.empty()) - return false; - resp = m_responses.front(); - m_responses.pop(); - return true; -} - -Bool Pinger::arePingsInProgress( void ) -{ - return (m_requestCount != m_responseCount); -} - -Int Pinger::getPing( AsciiString hostname ) -{ - MutexClass::LockClass m(m_pingMapMutex, 0); - if (m.Failed()) - return false; - - std::map::const_iterator it = m_pingMap.find(hostname.str()); - if (it != m_pingMap.end()) - return it->second; - - return -1; -} - -void Pinger::clearPingMap( void ) -{ - MutexClass::LockClass m(m_pingMapMutex); - m_pingMap.clear(); -} - -AsciiString Pinger::getPingString( Int timeout ) -{ - MutexClass::LockClass m(m_pingMapMutex); - - AsciiString pingString; - AsciiString tmp; - for (std::map::const_iterator it = m_pingMap.begin(); it != m_pingMap.end(); ++it) - { - Int ping = it->second; - if (ping < 0 || ping > timeout) - ping = timeout; - ping = ping * 255 / timeout; - tmp.format("%2.2X", ping); - pingString.concat(tmp); - } - return pingString; -} - -//------------------------------------------------------------------------- - -void PingThreadClass::Thread_Function() -{ - try { - _set_se_translator( DumpExceptionInfo ); // Hook that allows stack trace. - PingRequest req; - - WSADATA wsaData; - - // Fire up winsock (prob already done, but doesn't matter) - WORD wVersionRequested = MAKEWORD(1, 1); - WSAStartup( wVersionRequested, &wsaData ); - - while ( running ) - { - // deal with requests - if (ThePinger->getRequest(req)) - { - // resolve the hostname - const char *hostnameBuffer = req.hostname.c_str(); - UnsignedInt IP = 0xFFFFFFFF; - if (isdigit(hostnameBuffer[0])) - { - IP = inet_addr(hostnameBuffer); - in_addr hostNode; - hostNode.s_addr = IP; - DEBUG_LOG(("pinging %s - IP = %s\n", hostnameBuffer, inet_ntoa(hostNode) )); - } - else - { - HOSTENT *hostStruct; - in_addr *hostNode; - hostStruct = gethostbyname(hostnameBuffer); - if (hostStruct == NULL) - { - DEBUG_LOG(("pinging %s - host lookup failed\n", hostnameBuffer)); - - // Even though this failed to resolve IP, still need to send a - // callback. - IP = 0xFFFFFFFF; // flag for IP resolve failed - } - hostNode = (in_addr *) hostStruct->h_addr; - IP = hostNode->s_addr; - DEBUG_LOG(("pinging %s IP = %s\n", hostnameBuffer, inet_ntoa(*hostNode) )); - } - - // do ping - Int totalPing = 0; - Int goodReps = 0; - Int reps = req.repetitions; - while (reps-- && running && IP != 0xFFFFFFFF) - { - Int ping = doPing(IP, req.timeout); - if (ping >= 0) - { - totalPing += ping; - ++goodReps; - } - - // end our timeslice - Switch_Thread(); - } - if (!goodReps) - totalPing = -1; - else - totalPing = totalPing / goodReps; - - PingResponse resp; - resp.hostname = req.hostname; - resp.avgPing = totalPing; - resp.repetitions = goodReps; - ThePinger->addResponse(resp); - } - - // end our timeslice - Switch_Thread(); - } - - WSACleanup(); - } catch ( ... ) { - DEBUG_CRASH(("Exception in ping thread!")); - } -} - -//------------------------------------------------------------------------- -//------------------------------------------------------------------------- -//------------------------------------------------------------------------- -//------------------------------------------------------------------------- -//------------------------------------------------------------------------- -//------------------------------------------------------------------------- - -HANDLE WINAPI IcmpCreateFile(VOID); /* INVALID_HANDLE_VALUE on error */ -BOOL WINAPI IcmpCloseHandle(HANDLE IcmpHandle); /* FALSE on error */ - -/* Note 2: For the most part, you can refer to RFC 791 for detials - * on how to fill in values for the IP option information structure. - */ -typedef struct ip_option_information -{ - UnsignedByte Ttl; /* Time To Live (used for traceroute) */ - UnsignedByte Tos; /* Type Of Service (usually 0) */ - UnsignedByte Flags; /* IP header flags (usually 0) */ - UnsignedByte OptionsSize; /* Size of options data (usually 0, max 40) */ - UnsignedByte FAR *OptionsData; /* Options data buffer */ -} -IPINFO, *PIPINFO, FAR *LPIPINFO; - - -/* Note 1: The Reply Buffer will have an array of ICMP_ECHO_REPLY - * structures, followed by options and the data in ICMP echo reply - * datagram received. You must have room for at least one ICMP - * echo reply structure, plus 8 bytes for an ICMP header. - */ -typedef struct icmp_echo_reply -{ - UnsignedInt Address; /* source address */ - ////////UnsignedInt Status; /* IP status value (see below) */ - UnsignedInt RTTime; /* Round Trip Time in milliseconds */ - UnsignedShort DataSize; /* reply data size */ - UnsignedShort Reserved; /* */ - void FAR *Data; /* reply data buffer */ - struct ip_option_information Options; /* reply options */ -} -ICMPECHO, *PICMPECHO, FAR *LPICMPECHO; - - -DWORD WINAPI IcmpSendEcho( - HANDLE IcmpHandle, /* handle returned from IcmpCreateFile() */ - UnsignedInt DestAddress, /* destination IP address (in network order) */ - LPVOID RequestData, /* pointer to buffer to send */ - WORD RequestSize, /* length of data in buffer */ - LPIPINFO RequestOptns, /* see Note 2 */ - LPVOID ReplyBuffer, /* see Note 1 */ - DWORD ReplySize, /* length of reply (must allow at least 1 reply) */ - DWORD Timeout /* time in milliseconds to wait for reply */ -); - - -#define IP_STATUS_BASE 11000 -#define IP_SUCCESS 0 -#define IP_BUF_TOO_SMALL (IP_STATUS_BASE + 1) -#define IP_DEST_NET_UNREACHABLE (IP_STATUS_BASE + 2) -#define IP_DEST_HOST_UNREACHABLE (IP_STATUS_BASE + 3) -#define IP_DEST_PROT_UNREACHABLE (IP_STATUS_BASE + 4) -#define IP_DEST_PORT_UNREACHABLE (IP_STATUS_BASE + 5) -#define IP_NO_RESOURCES (IP_STATUS_BASE + 6) -#define IP_BAD_OPTION (IP_STATUS_BASE + 7) -#define IP_HW_ERROR (IP_STATUS_BASE + 8) -#define IP_PACKET_TOO_BIG (IP_STATUS_BASE + 9) -#define IP_REQ_TIMED_OUT (IP_STATUS_BASE + 10) -#define IP_BAD_REQ (IP_STATUS_BASE + 11) -#define IP_BAD_ROUTE (IP_STATUS_BASE + 12) -#define IP_TTL_EXPIRED_TRANSIT (IP_STATUS_BASE + 13) -#define IP_TTL_EXPIRED_REASSEM (IP_STATUS_BASE + 14) -#define IP_PARAM_PROBLEM (IP_STATUS_BASE + 15) -#define IP_SOURCE_QUENCH (IP_STATUS_BASE + 16) -#define IP_OPTION_TOO_BIG (IP_STATUS_BASE + 17) -#define IP_BAD_DESTINATION (IP_STATUS_BASE + 18) -#define IP_ADDR_DELETED (IP_STATUS_BASE + 19) -#define IP_SPEC_MTU_CHANGE (IP_STATUS_BASE + 20) -#define IP_MTU_CHANGE (IP_STATUS_BASE + 21) -#define IP_UNLOAD (IP_STATUS_BASE + 22) -#define IP_GENERAL_FAILURE (IP_STATUS_BASE + 50) -#define MAX_IP_STATUS IP_GENERAL_FAILURE -#define IP_PENDING (IP_STATUS_BASE + 255) - - -#define BUFSIZE 8192 -#define DEFAULT_LEN 32 -#define LOOPLIMIT 4 -#define DEFAULT_TTL 64 - -Int PingThreadClass::doPing(UnsignedInt IP, Int timeout) -{ - /* - * Initialize default settings - */ - - IPINFO stIPInfo, *lpstIPInfo; - HANDLE hICMP, hICMP_DLL; - int i, j, nDataLen, nLoopLimit, nTimeOut, nTTL, nTOS; - DWORD dwReplyCount; - ///////IN_ADDR stDestAddr; - BOOL fRet, fDontStop; - ///BOOL fTraceRoute; - - nDataLen = DEFAULT_LEN; - nLoopLimit = LOOPLIMIT; - nTimeOut = timeout; - fDontStop = FALSE; - lpstIPInfo = NULL; - nTTL = DEFAULT_TTL; - nTOS = 0; - - Int pingTime = -1; // in case of error - - char achReqData[BUFSIZE]; - char achRepData[sizeof(ICMPECHO) + BUFSIZE]; - - - HANDLE ( WINAPI *lpfnIcmpCreateFile )( VOID ) = NULL; - BOOL ( WINAPI *lpfnIcmpCloseHandle )( HANDLE ) = NULL; - DWORD (WINAPI *lpfnIcmpSendEcho)(HANDLE, DWORD, LPVOID, WORD, LPVOID, - LPVOID, DWORD, DWORD) = NULL; - - - /* - * Load the ICMP.DLL - */ - hICMP_DLL = LoadLibrary("ICMP.DLL"); - if (hICMP_DLL == 0) - { - DEBUG_LOG(("LoadLibrary() failed: Unable to locate ICMP.DLL!\n")); - goto cleanup; - } - - /* - * Get pointers to ICMP.DLL functions - */ - lpfnIcmpCreateFile = (void * (__stdcall *)(void))GetProcAddress( (HINSTANCE)hICMP_DLL, "IcmpCreateFile"); - lpfnIcmpCloseHandle = (int (__stdcall *)(void *))GetProcAddress( (HINSTANCE)hICMP_DLL, "IcmpCloseHandle"); - lpfnIcmpSendEcho = (unsigned long (__stdcall *)(void *, unsigned long, void *, unsigned short, - void *, void *, unsigned long, unsigned long))GetProcAddress( (HINSTANCE)hICMP_DLL, "IcmpSendEcho" ); - - if ((!lpfnIcmpCreateFile) || - (!lpfnIcmpCloseHandle) || - (!lpfnIcmpSendEcho)) - { - DEBUG_LOG(("GetProcAddr() failed for at least one function.\n")); - goto cleanup; - } - - - /* - * IcmpCreateFile() - Open the ping service - */ - hICMP = (HANDLE) lpfnIcmpCreateFile(); - if (hICMP == INVALID_HANDLE_VALUE) - { - DEBUG_LOG(("IcmpCreateFile() failed")); - goto cleanup; - } - - /* - * Init data buffer printable ASCII - * 32 (space) through 126 (tilde) - */ - for (j = 0, i = 32; j < nDataLen; j++, i++) - { - if (i >= 126) - i = 32; - achReqData[j] = i; - } - - /* - * Init IPInfo structure - */ - lpstIPInfo = &stIPInfo; - stIPInfo.Ttl = nTTL; - stIPInfo.Tos = nTOS; - stIPInfo.Flags = 0; - stIPInfo.OptionsSize = 0; - stIPInfo.OptionsData = NULL; - - - - /* - * IcmpSendEcho() - Send the ICMP Echo Request - * and read the Reply - */ - dwReplyCount = lpfnIcmpSendEcho( - hICMP, - IP, - achReqData, - nDataLen, - lpstIPInfo, - achRepData, - sizeof(achRepData), - nTimeOut); - if (dwReplyCount != 0) - { - //////////IN_ADDR stDestAddr; - DWORD dwStatus; - - pingTime = (*(UnsignedInt *) & (achRepData[8])); - - // I've seen the ping time bigger than the timeout by a little - // bit. How lame. - if (pingTime > timeout) - pingTime = timeout; - - dwStatus = *(DWORD *) & (achRepData[4]); - if (dwStatus != IP_SUCCESS) - { - DEBUG_LOG(("ICMPERR: %d\n", dwStatus)); - } - - } - else - { - DEBUG_LOG(("IcmpSendEcho() failed: %d\n", dwReplyCount)); - // Ok we didn't get a packet, just say everything's OK - // and the time was -1 - pingTime = -1; - goto cleanup; - } - - - /* - * IcmpCloseHandle - Close the ICMP handle - */ - fRet = lpfnIcmpCloseHandle(hICMP); - if (fRet == FALSE) - { - DEBUG_LOG(("Error closing ICMP handle\n")); - } - - // Say what you will about goto's but it's handy for stuff like this -cleanup: - - // Shut down... - if (hICMP_DLL) - FreeLibrary((HINSTANCE)hICMP_DLL); - - return pingTime; -} - - -//------------------------------------------------------------------------- diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/ThreadUtils.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/ThreadUtils.cpp deleted file mode 100644 index 274ea55f575..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/ThreadUtils.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ThreadUtils.cpp ////////////////////////////////////////////////////// -// GameSpy thread utils -// Author: Matthew D. Campbell, July 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -//------------------------------------------------------------------------- - -std::wstring MultiByteToWideCharSingleLine( const char *orig ) -{ - Int len = strlen(orig); - WideChar *dest = NEW WideChar[len+1]; - - MultiByteToWideChar(CP_UTF8, 0, orig, -1, dest, len); - WideChar *c = NULL; - do - { - c = wcschr(dest, L'\n'); - if (c) - { - *c = L' '; - } - } - while ( c != NULL ); - do - { - c = wcschr(dest, L'\r'); - if (c) - { - *c = L' '; - } - } - while ( c != NULL ); - - dest[len] = 0; - std::wstring ret = dest; - delete dest; - return ret; -} - -std::string WideCharStringToMultiByte( const WideChar *orig ) -{ - std::string ret; - Int len = WideCharToMultiByte( CP_UTF8, 0, orig, wcslen(orig), NULL, 0, NULL, NULL ) + 1; - if (len > 0) - { - char *dest = NEW char[len]; - WideCharToMultiByte( CP_UTF8, 0, orig, -1, dest, len, NULL, NULL ); - dest[len-1] = 0; - ret = dest; - delete dest; - } - return ret; -} - -//------------------------------------------------------------------------- - diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpyChat.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpyChat.cpp deleted file mode 100644 index 2d17ff3db4f..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpyChat.cpp +++ /dev/null @@ -1,455 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameSpyChat.cpp ////////////////////////////////////////////////////// -// GameSpy chat handlers -// Author: Matthew D. Campbell, February 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "GameClient/GameText.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/LanguageFilter.h" -#include "GameNetwork/GameSpy.h" -#include "GameNetwork/GameSpyChat.h" -#include "Common/QuotedPrintable.h" - -typedef set::const_iterator AsciiSetIter; - -/** - * handleSlashCommands looks for slash ccommands and handles them, - * returning true if it found one, false otherwise. - * /i,/ignore list ignored players - * /i,/ignore +name1 -name2 ignore name1, stop ignoring name2 - * /m,/me: shorthand for an action - * /o,/on: find command to look up a user's location - * /f,/find: find command to look up a user's location - * /p,/page: page user(s) - * /r,/reply: reply to last page - * /raw: raw IRC command (only in debug & internal) - * /oper: become an IRC op (only in debug & internal) - * /quit: send the IRC quit command to exit WOL - */ -static Bool handleSlashCommands( UnicodeString message, Bool isAction, GameWindow *playerListbox ) -{ - /* - if (message.getCharAt(0) == L'/') - { - UnicodeString remainder = UnicodeString(message.str() + 1); - UnicodeString token; - - switch (message.getCharAt(1)) - { - case L'i': - case L'I': - remainder.nextToken(&token); - if (token.compareNoCase(L"i") == 0 || token.compareNoCase(L"ignore") == 0) - { - if (remainder.isEmpty()) - { - // List the people we're ignoring - TheWOL->addText(TheGameText->fetch("WOL:BeginIgnoreList")); - set *ignoreList = getIgnoreList(); - if (ignoreList) - { - UnicodeString msg; - UnicodeString uName; - AsciiSetIter iter = ignoreList->begin(); - while (iter != ignoreList->end()) - { - uName.translate(*iter); - msg.format(TheGameText->fetch("WOL:IgnoredUser"), uName.str()); - TheWOL->addText(msg); - iter++; - } - } - TheWOL->addText(TheGameText->fetch("WOL:EndIgnoreList")); - } - - while ( remainder.nextToken(&token) ) - { - AsciiString name; - int doIgnore = 0; - if (token.getCharAt(0) == L'+') - { - // Ignore somebody - token = UnicodeString(token.str() + 1); - name.translate(token); - doIgnore = 1; - } - else if (token.getCharAt(0) == L'-') - { - // Listen to someone again - token = UnicodeString(token.str() + 1); - name.translate(token); - doIgnore = 0; - } - else - { - // Ignore somebody - token = UnicodeString(token.str()); - name.translate(token); - doIgnore = 1; - } - IChat *ichat = TheWOL->getIChat(); - User user; - strncpy((char *)user.name, name.str(), 9); - user.name[9] = 0; - ichat->SetSquelch(&user, doIgnore); - - if (doIgnore) - addIgnore(name); - else - removeIgnore(name); - - UnicodeString msg; - UnicodeString uName; - uName.translate(name); - msg.format(TheGameText->fetch("WOL:IgnoredUser"), uName.str()); - TheWOL->addText(msg); - } - return true; - } - break; - case L'r': - case L'R': - remainder.nextToken(&token); -#if defined _DEBUG || defined _INTERNAL - if (token.compareNoCase(L"raw") == 0) - { - // Send raw IRC commands (Ascii only) - AsciiString str; - str.translate(remainder); - str.concat('\n'); - IChat *ichat = TheWOL->getIChat(); - ichat->RequestRawMessage(str.str()); - TheWOL->addText(remainder); - return true; // show it anyway - } -#endif - break; -#if defined _DEBUG || defined _INTERNAL - case L'k': - case L'K': - remainder.nextToken(&token); - if (token.compareNoCase(L"kick") == 0) - { - - while ( remainder.nextToken(&token) ) - { - AsciiString name; - name.translate(token); - IChat *ichat = TheWOL->getIChat(); - User user; - strncpy((char *)user.name, name.str(), 9); - user.name[9] = 0; - ichat->RequestUserKick(&user); - } - return true; - } - break; -#endif - case L'o': - case L'O': - remainder.nextToken(&token); - if (token.compareNoCase(L"on") == 0 || token.compareNoCase(L"o") == 0) - { - remainder.nextToken(&token); - AsciiString userName; - userName.translate(token); - User user; - strncpy((char *)user.name, userName.str(), 10); - user.name[9] = 0; - if (user.name[0] == 0) - { - // didn't enter a name - TheWOL->addText(message); - } - else - { - // Send find command - IChat *ichat = TheWOL->getIChat(); - ichat->RequestGlobalFind(&user); - } - return true; // show it anyway - } -#if defined _DEBUG || defined _INTERNAL - else if (token.compareNoCase(L"oper") == 0) - { - // Send raw IRC oper command - AsciiString str; - str.translate(message); - str.concat('\n'); - IChat *ichat = TheWOL->getIChat(); - ichat->RequestRawMessage(str.str()); - TheWOL->addText(message); - return true; // show it anyway - } -#endif - break; - case L'p': - case L'P': - remainder.nextToken(&token); - if (token.compareNoCase(L"page") == 0 || token.compareNoCase(L"p") == 0) - { - remainder.nextToken(&token); - AsciiString userName; - userName.translate(token); - User user; - strncpy((char *)user.name, userName.str(), 10); - user.name[9] = 0; - remainder.trim(); - if (user.name[0] == 0 || remainder.isEmpty()) - { - // didn't enter a name or message - TheWOL->addText(message); - } - else - { - // Send page command - IChat *ichat = TheWOL->getIChat(); - ichat->RequestGlobalUnicodePage(&user, remainder.str()); - } - return true; // show it anyway - } - break; - case L'q': - case L'Q': - remainder.nextToken(&token); - if (token.compareNoCase(L"quit") == 0) - { - TheWOL->setState(WOLAPI_LOGIN); - TheWOL->addCommand(WOLCOMMAND_LOGOUT); - //TheWOL->setScreen(WOLAPI_MENU_WELCOME); - return true; // show it anyway - } - break; -#if defined _DEBUG || defined _INTERNAL - case L'c': - case L'C': - remainder.nextToken(&token); - if (token.compareNoCase(L"colortest") == 0) - { - addColorText(token, 0xDD, 0xE2, 0x0D, 0xff); - addColorText(token, 0xFF, 0x19, 0x19, 0xff); - addColorText(token, 0x2A, 0x74, 0xE2, 0xff); - addColorText(token, 0x3E, 0xD1, 0x2E, 0xff); - addColorText(token, 0xFF, 0xA0, 0x19, 0xff); - addColorText(token, 0x32, 0xD7, 0xE6, 0xff); - addColorText(token, 0x95, 0x28, 0xBD, 0xff); - addColorText(token, 0xFF, 0x9A, 0xEB, 0xff); - return true; // show it anyway - } - break; -#endif // _DEBUG || defined _INTERNAL - } - } - */ - return false; -} - -static handleUnicodeMessage( const char *nick, UnicodeString msg, Bool isPublic, Bool isAction ); - -Bool GameSpySendChat( UnicodeString message, Bool isAction, GameWindow *playerListbox ) -{ - RoomType roomType = StagingRoom; - if (TheGameSpyChat->getCurrentGroupRoomID()) - roomType = GroupRoom; - - message.trim(); - // Echo the user's input to the chat window - if (!message.isEmpty()) - { - // Check for slash commands - if (handleSlashCommands(message, isAction, playerListbox)) - { - return false; // already handled - } - - if (!playerListbox) - { - // Public message - if (isAction) - { - peerMessageRoom(TheGameSpyChat->getPeer(), roomType, UnicodeStringToQuotedPrintable(message).str(), ActionMessage); - //if (roomType == StagingRoom) - //handleUnicodeMessage(TheGameSpyChat->getloginName().str(), message, true, true); - } - else - { - peerMessageRoom(TheGameSpyChat->getPeer(), roomType, UnicodeStringToQuotedPrintable(message).str(), NormalMessage); - //if (roomType == StagingRoom) - //handleUnicodeMessage(TheGameSpyChat->getloginName().str(), message, true, false); - } - return false; - } - - // Get the selections (is this a private message?) - Int maxSel = GadgetListBoxGetListLength(playerListbox); - Int *selections; - GadgetListBoxGetSelected(playerListbox, (Int *)&selections); - - if (selections[0] == -1) - { - // Public message - if (isAction) - { - peerMessageRoom(TheGameSpyChat->getPeer(), roomType, UnicodeStringToQuotedPrintable(message).str(), ActionMessage); - //if (roomType == StagingRoom) - //handleUnicodeMessage(TheGameSpyChat->getloginName().str(), message, true, true); - } - else - { - peerMessageRoom(TheGameSpyChat->getPeer(), roomType, UnicodeStringToQuotedPrintable(message).str(), NormalMessage); - //if (roomType == StagingRoom) - //handleUnicodeMessage(TheGameSpyChat->getloginName().str(), message, true, false); - } - return false; - } - else - { - // Private message - - // Construct a list - AsciiString names = AsciiString::TheEmptyString; - AsciiString tmp = AsciiString::TheEmptyString; - AsciiString aStr; // AsciiString buf for translating Unicode entries - names.format("%s", TheGameSpyChat->getLoginName().str()); - for (int i=0; igetLoginName())) - { - tmp.format(",%s", aStr.str()); - names.concat(tmp); - } - } - else - { - break; - } - } - - if (!names.isEmpty()) - { - if (isAction) - { - peerMessagePlayer(TheGameSpyChat->getPeer(), names.str(), UnicodeStringToQuotedPrintable(message).str(), ActionMessage); - } - else - { - peerMessagePlayer(TheGameSpyChat->getPeer(), names.str(), UnicodeStringToQuotedPrintable(message).str(), NormalMessage); - } - } - - return true; - } - } - return false; -} - -void RoomMessageCallback(PEER peer, RoomType roomType, - const char * nick, const char * message, - MessageType messageType, void * param) -{ - DEBUG_LOG(("RoomMessageCallback\n")); - handleUnicodeMessage(nick, QuotedPrintableToUnicodeString(message), true, (messageType == ActionMessage)); -} - -void PlayerMessageCallback(PEER peer, - const char * nick, const char * message, - MessageType messageType, void * param) -{ - DEBUG_LOG(("PlayerMessageCallback\n")); - handleUnicodeMessage(nick, QuotedPrintableToUnicodeString(message), false, (messageType == ActionMessage)); -} - -static handleUnicodeMessage( const char *nick, UnicodeString msg, Bool isPublic, Bool isAction ) -{ - GameSpyColors style; - - Bool isOwner = false; - Int flags = 0; - if (TheGameSpyChat->getCurrentGroupRoomID()) - peerGetPlayerFlags(TheGameSpyChat->getPeer(), nick, GroupRoom, &flags); - else - peerGetPlayerFlags(TheGameSpyChat->getPeer(), nick, StagingRoom, &flags); - isOwner = flags & PEER_FLAG_OP; - - if (isPublic && isAction) - { - style = (isOwner)?GSCOLOR_CHAT_OWNER_EMOTE:GSCOLOR_CHAT_EMOTE; - } - else if (isPublic) - { - style = (isOwner)?GSCOLOR_CHAT_OWNER:GSCOLOR_CHAT_NORMAL; - } - else if (isAction) - { - style = (isOwner)?GSCOLOR_CHAT_PRIVATE_OWNER_EMOTE:GSCOLOR_CHAT_PRIVATE_EMOTE; - } - else - { - style = (isOwner)?GSCOLOR_CHAT_PRIVATE_OWNER:GSCOLOR_CHAT_PRIVATE; - } - - UnicodeString name; - name.translate(nick); - - // filters language -// if( TheGlobalData->m_languageFilterPref ) -// { - TheLanguageFilter->filterLine(msg); -// } - - UnicodeString fullMsg; - if (isAction) - { - fullMsg.format( L"%ls %ls", name.str(), msg.str() ); - } - else - { - fullMsg.format( L"[%ls] %ls", name.str(), msg.str() ); - } - GameSpyAddText(fullMsg, style); -} - -void GameSpyAddText( UnicodeString message, GameSpyColors color ) -{ - GameWindow *textWindow = NULL; - - if (!textWindow) - textWindow = listboxLobbyChat; - if (!textWindow) - textWindow = listboxGameSetupChat; - - if (!textWindow) - return; - - GadgetListBoxAddEntryText(textWindow, message, GameSpyColor[color], -1, -1); - -} - diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpyGP.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpyGP.cpp deleted file mode 100644 index 751d81d21f0..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpyGP.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameSpyGP.cpp ////////////////////////////////////////////////////// -// GameSpy GP callbacks, utils, etc -// Author: Matthew D. Campbell, February 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "GameClient/GameText.h" -#include "GameNetwork/GameSpy.h" -#include "GameNetwork/GameSpyGP.h" -#include "GameNetwork/GameSpyOverlay.h" - -GPConnection TheGPConnectionObj; -GPConnection *TheGPConnection = &TheGPConnectionObj; -GPProfile GameSpyLocalProfile = 0; -char GameSpyProfilePassword[64]; - -void GPRecvBuddyMessageCallback(GPConnection * pconnection, GPRecvBuddyMessageArg * arg, void * param) -{ - DEBUG_LOG(("GPRecvBuddyMessageCallback: message from %d is %s\n", arg->profile, arg->message)); - - //gpGetInfo(pconn, arg->profile, GP_DONT_CHECK_CACHE, GP_BLOCKING, (GPCallback)Whois, NULL); - //printf("MESSAGE (%d): %s: %s\n", msgCount,whois, arg->message); -} - -static void buddyTryReconnect( void ) -{ - TheGameSpyChat->reconnectProfile(); -} - -void GPErrorCallback(GPConnection * pconnection, GPErrorArg * arg, void * param) -{ - DEBUG_LOG(("GPErrorCallback\n")); - - AsciiString errorCodeString; - AsciiString resultString; - - #define RESULT(x) case x: resultString = #x; break; - switch(arg->result) - { - RESULT(GP_NO_ERROR) - RESULT(GP_MEMORY_ERROR) - RESULT(GP_PARAMETER_ERROR) - RESULT(GP_NETWORK_ERROR) - RESULT(GP_SERVER_ERROR) - default: - resultString = "Unknown result!"; - } - #undef RESULT - - #define ERRORCODE(x) case x: errorCodeString = #x; break; - switch(arg->errorCode) - { - ERRORCODE(GP_GENERAL) - ERRORCODE(GP_PARSE) - ERRORCODE(GP_NOT_LOGGED_IN) - ERRORCODE(GP_BAD_SESSKEY) - ERRORCODE(GP_DATABASE) - ERRORCODE(GP_NETWORK) - ERRORCODE(GP_FORCED_DISCONNECT) - ERRORCODE(GP_CONNECTION_CLOSED) - ERRORCODE(GP_LOGIN) - ERRORCODE(GP_LOGIN_TIMEOUT) - ERRORCODE(GP_LOGIN_BAD_NICK) - ERRORCODE(GP_LOGIN_BAD_EMAIL) - ERRORCODE(GP_LOGIN_BAD_PASSWORD) - ERRORCODE(GP_LOGIN_BAD_PROFILE) - ERRORCODE(GP_LOGIN_PROFILE_DELETED) - ERRORCODE(GP_LOGIN_CONNECTION_FAILED) - ERRORCODE(GP_LOGIN_SERVER_AUTH_FAILED) - ERRORCODE(GP_NEWUSER) - ERRORCODE(GP_NEWUSER_BAD_NICK) - ERRORCODE(GP_NEWUSER_BAD_PASSWORD) - ERRORCODE(GP_UPDATEUI) - ERRORCODE(GP_UPDATEUI_BAD_EMAIL) - ERRORCODE(GP_NEWPROFILE) - ERRORCODE(GP_NEWPROFILE_BAD_NICK) - ERRORCODE(GP_NEWPROFILE_BAD_OLD_NICK) - ERRORCODE(GP_UPDATEPRO) - ERRORCODE(GP_UPDATEPRO_BAD_NICK) - ERRORCODE(GP_ADDBUDDY) - ERRORCODE(GP_ADDBUDDY_BAD_FROM) - ERRORCODE(GP_ADDBUDDY_BAD_NEW) - ERRORCODE(GP_ADDBUDDY_ALREADY_BUDDY) - ERRORCODE(GP_AUTHADD) - ERRORCODE(GP_AUTHADD_BAD_FROM) - ERRORCODE(GP_AUTHADD_BAD_SIG) - ERRORCODE(GP_STATUS) - ERRORCODE(GP_BM) - ERRORCODE(GP_BM_NOT_BUDDY) - ERRORCODE(GP_GETPROFILE) - ERRORCODE(GP_GETPROFILE_BAD_PROFILE) - ERRORCODE(GP_DELBUDDY) - ERRORCODE(GP_DELBUDDY_NOT_BUDDY) - ERRORCODE(GP_DELPROFILE) - ERRORCODE(GP_DELPROFILE_LAST_PROFILE) - ERRORCODE(GP_SEARCH) - ERRORCODE(GP_SEARCH_CONNECTION_FAILED) - default: - errorCodeString = "Unknown error code!"; - } - #undef ERRORCODE - - if(arg->fatal) - { - DEBUG_LOG(( "-----------\n")); - DEBUG_LOG(( "GP FATAL ERROR\n")); - DEBUG_LOG(( "-----------\n")); - - // if we're still connected to the chat server, tell the user. He can always hit the buddy - // button to try reconnecting. Oh yes, also hide the buddy popup. - GameSpyCloseOverlay(GSOVERLAY_BUDDY); - if (TheGameSpyChat->isConnected()) - { - GSMessageBoxYesNo(TheGameText->fetch("GUI:GPErrorTitle"), TheGameText->fetch("GUI:GPDisconnected"), buddyTryReconnect, NULL); - } - } - else - { - DEBUG_LOG(( "-----\n")); - DEBUG_LOG(( "GP ERROR\n")); - DEBUG_LOG(( "-----\n")); - } - DEBUG_LOG(( "RESULT: %s (%d)\n", resultString.str(), arg->result)); - DEBUG_LOG(( "ERROR CODE: %s (0x%X)\n", errorCodeString.str(), arg->errorCode)); - DEBUG_LOG(( "ERROR STRING: %s\n", arg->errorString)); -} - -void GPRecvBuddyStatusCallback(GPConnection * connection, GPRecvBuddyStatusArg * arg, void * param) -{ - DEBUG_LOG(("GPRecvBuddyStatusCallback: info on %d is in %d\n", arg->profile, arg->index)); - - //GameSpyUpdateBuddyOverlay(); -} - -void GPRecvBuddyRequestCallback(GPConnection * connection, GPRecvBuddyRequestArg * arg, void * param) -{ - DEBUG_LOG(("GPRecvBuddyRequestCallback: %d wants to be our buddy because '%s'\n", arg->profile, arg->reason)); -} diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpyGameInfo.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpyGameInfo.cpp deleted file mode 100644 index 4fecf7a8d77..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpyGameInfo.cpp +++ /dev/null @@ -1,754 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameSpyGameInfo.cpp ////////////////////////////////////////////////////// -// GameSpy game setup state info -// Author: Matthew D. Campbell, December 2001 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "Common/Player.h" -#include "Common/PlayerList.h" -#include "Common/RandomValue.h" -#include "Common/Scorekeeper.h" -#include "GameClient/Shell.h" -#include "GameClient/GameText.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpyGameInfo.h" -#include "GameNetwork/NetworkInterface.h" -#include "GameNetwork/NetworkUtil.h" -#include "GameNetwork/NetworkDefs.h" -#include "GameNetwork/NAT.h" -#include "GameLogic/GameLogic.h" -#include "GameLogic/VictoryConditions.h" - -// Singleton ------------------------------------------ - -GameSpyGameInfo *TheGameSpyGame = NULL; - -// Helper Functions ---------------------------------------- - -GameSpyGameSlot::GameSpyGameSlot() -{ - GameSlot(); - m_gameSpyLogin.clear(); - m_gameSpyLocale.clear(); - m_profileID = 0; -} - -// Helper Functions ---------------------------------------- -/* -** Function definitions for the MIB-II entry points. -*/ - -BOOL (__stdcall *SnmpExtensionInitPtr)(IN DWORD dwUpTimeReference, OUT HANDLE *phSubagentTrapEvent, OUT AsnObjectIdentifier *pFirstSupportedRegion); -BOOL (__stdcall *SnmpExtensionQueryPtr)(IN BYTE bPduType, IN OUT RFC1157VarBindList *pVarBindList, OUT AsnInteger32 *pErrorStatus, OUT AsnInteger32 *pErrorIndex); -LPVOID (__stdcall *SnmpUtilMemAllocPtr)(IN DWORD bytes); -VOID (__stdcall *SnmpUtilMemFreePtr)(IN LPVOID pMem); - -typedef struct tConnInfoStruct { - unsigned int State; - unsigned long LocalIP; - unsigned short LocalPort; - unsigned long RemoteIP; - unsigned short RemotePort; -} ConnInfoStruct; - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) -#endif - -/*********************************************************************************************** - * Get_Local_Chat_Connection_Address -- Which address are we using to talk to the chat server? * - * * - * * - * * - * INPUT: Ptr to address to return local address * * - * * - * OUTPUT: True if success * - * * - * WARNINGS: None * - * * - * HISTORY: * - * 10/27/00 3:24PM ST : Created * - *=============================================================================================*/ -Bool GetLocalChatConnectionAddress(AsciiString serverName, UnsignedShort serverPort, UnsignedInt& localIP) -{ - //return false; - /* - ** Local defines. - */ - enum { - CLOSED = 1, - LISTENING, - SYN_SENT, - SEN_RECEIVED, - ESTABLISHED, - FIN_WAIT, - FIN_WAIT2, - CLOSE_WAIT, - LAST_ACK, - CLOSING, - TIME_WAIT, - DELETE_TCB - }; - - enum { - tcpConnState = 1, - tcpConnLocalAddress, - tcpConnLocalPort, - tcpConnRemAddress, - tcpConnRemPort - }; - - - /* - ** Locals. - */ - unsigned char serverAddress[4]; - unsigned char remoteAddress[4]; - HANDLE trap_handle; - AsnObjectIdentifier first_supported_region; - std::vector connectionVector; - int last_field; - int index; - AsnInteger error_status; - AsnInteger error_index; - int conn_entry_type_index; - int conn_entry_type; - Bool found; - - /* - ** Statics. - */ - static char _conn_state[][32] = { - "?", - "CLOSED", - "LISTENING", - "SYN_SENT", - "SEN_RECEIVED", - "ESTABLISHED", - "FIN_WAIT", - "FIN_WAIT2", - "CLOSE_WAIT", - "LAST_ACK", - "CLOSING", - "TIME_WAIT", - "DELETE_TCB" - }; - - DEBUG_LOG(("Finding local address used to talk to the chat server\n")); - DEBUG_LOG(("Current chat server name is %s\n", serverName.str())); - DEBUG_LOG(("Chat server port is %d\n", serverPort)); - - /* - ** Get the address of the chat server. - */ - DEBUG_LOG( ("About to call gethostbyname\n")); - struct hostent *host_info = gethostbyname(serverName.str()); - - if (!host_info) { - DEBUG_LOG( ("gethostbyname failed! Error code %d\n", WSAGetLastError())); - return(false); - } - - memcpy(serverAddress, &host_info->h_addr_list[0][0], 4); - unsigned long temp = *((unsigned long*)(&serverAddress[0])); - temp = ntohl(temp); - *((unsigned long*)(&serverAddress[0])) = temp; - - DEBUG_LOG(("Host address is %d.%d.%d.%d\n", serverAddress[3], serverAddress[2], serverAddress[1], serverAddress[0])); - - /* - ** Load the MIB-II SNMP DLL. - */ - DEBUG_LOG(("About to load INETMIB1.DLL\n")); - - HINSTANCE mib_ii_dll = LoadLibrary("inetmib1.dll"); - if (mib_ii_dll == NULL) { - DEBUG_LOG(("Failed to load INETMIB1.DLL\n")); - return(false); - } - - DEBUG_LOG(("About to load SNMPAPI.DLL\n")); - - HINSTANCE snmpapi_dll = LoadLibrary("snmpapi.dll"); - if (snmpapi_dll == NULL) { - DEBUG_LOG(("Failed to load SNMPAPI.DLL\n")); - FreeLibrary(mib_ii_dll); - return(false); - } - - /* - ** Get the function pointers into the .dll - */ - SnmpExtensionInitPtr = (int (__stdcall *)(unsigned long,void ** ,AsnObjectIdentifier *)) GetProcAddress(mib_ii_dll, "SnmpExtensionInit"); - SnmpExtensionQueryPtr = (int (__stdcall *)(unsigned char,SnmpVarBindList *,long *,long *)) GetProcAddress(mib_ii_dll, "SnmpExtensionQuery"); - SnmpUtilMemAllocPtr = (void *(__stdcall *)(unsigned long)) GetProcAddress(snmpapi_dll, "SnmpUtilMemAlloc"); - SnmpUtilMemFreePtr = (void (__stdcall *)(void *)) GetProcAddress(snmpapi_dll, "SnmpUtilMemFree"); - if (SnmpExtensionInitPtr == NULL || SnmpExtensionQueryPtr == NULL || SnmpUtilMemAllocPtr == NULL || SnmpUtilMemFreePtr == NULL) { - DEBUG_LOG(("Failed to get proc addresses for linked functions\n")); - FreeLibrary(snmpapi_dll); - FreeLibrary(mib_ii_dll); - return(false); - } - - - RFC1157VarBindList *bind_list_ptr = (RFC1157VarBindList *) SnmpUtilMemAllocPtr(sizeof(RFC1157VarBindList)); - RFC1157VarBind *bind_ptr = (RFC1157VarBind *) SnmpUtilMemAllocPtr(sizeof(RFC1157VarBind)); - - /* - ** OK, here we go. Try to initialise the .dll - */ - DEBUG_LOG(("About to init INETMIB1.DLL\n")); - int ok = SnmpExtensionInitPtr(GetCurrentTime(), &trap_handle, &first_supported_region); - - if (!ok) { - /* - ** Aw crap. - */ - DEBUG_LOG(("Failed to init the .dll\n")); - SnmpUtilMemFreePtr(bind_list_ptr); - SnmpUtilMemFreePtr(bind_ptr); - FreeLibrary(snmpapi_dll); - FreeLibrary(mib_ii_dll); - return(false); - } - - /* - ** Name of mib_ii object we want to query. See RFC 1213. - ** - ** iso.org.dod.internet.mgmt.mib-2.tcp.tcpConnTable.TcpConnEntry.tcpConnState - ** 1 3 6 1 2 1 6 13 1 1 - */ - unsigned int mib_ii_name[] = {1,3,6,1,2,1,6,13,1,1}; - unsigned int *mib_ii_name_ptr = (unsigned int *) SnmpUtilMemAllocPtr(sizeof(mib_ii_name)); - memcpy(mib_ii_name_ptr, mib_ii_name, sizeof(mib_ii_name)); - - /* - ** Get the index of the conn entry data. - */ - conn_entry_type_index = ARRAY_SIZE(mib_ii_name) - 1; - - /* - ** Set up the bind list. - */ - bind_ptr->name.idLength = ARRAY_SIZE(mib_ii_name); - bind_ptr->name.ids = mib_ii_name; - bind_list_ptr->list = bind_ptr; - bind_list_ptr->len = 1; - - - /* - ** We start with the tcpConnLocalAddress field. - */ - last_field = 1; - - /* - ** First connection. - */ - index = 0; - - /* - ** Suck out that tcp connection info.... - */ - while (true) { - - if (!SnmpExtensionQueryPtr(SNMP_PDU_GETNEXT, bind_list_ptr, &error_status, &error_index)) { - //if (!SnmpExtensionQueryPtr(ASN_RFC1157_GETNEXTREQUEST, bind_list_ptr, &error_status, &error_index)) { - DEBUG_LOG(("SnmpExtensionQuery returned false\n")); - SnmpUtilMemFreePtr(bind_list_ptr); - SnmpUtilMemFreePtr(bind_ptr); - FreeLibrary(snmpapi_dll); - FreeLibrary(mib_ii_dll); - return(false); - } - - /* - ** If this is something new we aren't looking for then we are done. - */ - if (bind_ptr->name.idLength < ARRAY_SIZE(mib_ii_name)) { - break; - } - - /* - ** Get the type of info we are looking at. See RFC1213. - ** - ** 1 = tcpConnState - ** 2 = tcpConnLocalAddress - ** 3 = tcpConnLocalPort - ** 4 = tcpConnRemAddress - ** 5 = tcpConnRemPort - ** - ** tcpConnState is one of the following... - ** - ** 1 closed - ** 2 listen - ** 3 synSent - ** 4 synReceived - ** 5 established - ** 6 finWait1 - ** 7 finWait2 - ** 8 closeWait - ** 9 lastAck - ** 10 closing - ** 11 timeWait - ** 12 deleteTCB - */ - conn_entry_type = bind_ptr->name.ids[conn_entry_type_index]; - - if (last_field != conn_entry_type) { - index = 0; - last_field = conn_entry_type; - } - - switch (conn_entry_type) { - - /* - ** 1. First field in the entry. Need to create a new connection info struct - ** here to store this connection in. - */ - case tcpConnState: - { - ConnInfoStruct new_conn; - new_conn.State = bind_ptr->value.asnValue.number; - connectionVector.push_back(new_conn); - break; - } - - /* - ** 2. Local address field. - */ - case tcpConnLocalAddress: - DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index")); - connectionVector[index].LocalIP = *((unsigned long*)bind_ptr->value.asnValue.address.stream); - index++; - break; - - /* - ** 3. Local port field. - */ - case tcpConnLocalPort: - DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index")); - connectionVector[index].LocalPort = bind_ptr->value.asnValue.number; - //connectionVector[index]->LocalPort = ntohs(connectionVector[index]->LocalPort); - index++; - break; - - /* - ** 4. Remote address field. - */ - case tcpConnRemAddress: - DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index")); - connectionVector[index].RemoteIP = *((unsigned long*)bind_ptr->value.asnValue.address.stream); - index++; - break; - - /* - ** 5. Remote port field. - */ - case tcpConnRemPort: - DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index")); - connectionVector[index].RemotePort = bind_ptr->value.asnValue.number; - //connectionVector[index]->RemotePort = ntohs(connectionVector[index]->RemotePort); - index++; - break; - } - } - - SnmpUtilMemFreePtr(bind_list_ptr); - SnmpUtilMemFreePtr(bind_ptr); - SnmpUtilMemFreePtr(mib_ii_name_ptr); - - DEBUG_LOG(("Got %d connections in list, parsing...\n", connectionVector.size())); - - /* - ** Right, we got the lot. Lets see if any of them have the same address as the chat - ** server we think we are talking to. - */ - found = false; - for (Int i=0; igetSlot(i); - if (slot && slot->isOccupied()) - numUsers++; - } - - if (numUsers < 2) - { - if (TheGameSpyGame->amIHost()) - { - UnicodeString text; - text.format(TheGameText->fetch("LAN:NeedMorePlayers"),numUsers); - TheGameSpyInfo->addText(text, GSCOLOR_DEFAULT, NULL); - } - return; - } - - TheGameSpyGame->startGame(0); - } -} - -void GameSpyLaunchGame( void ) -{ - if (TheGameSpyGame) - { - - // Set up the game network - AsciiString user; - AsciiString userList; - DEBUG_ASSERTCRASH(TheNetwork == NULL, ("For some reason TheNetwork isn't NULL at the start of this game. Better look into that.")); - - if (TheNetwork != NULL) { - delete TheNetwork; - TheNetwork = NULL; - } - - // Time to initialize TheNetwork for this game. - TheNetwork = NetworkInterface::createNetwork(); - TheNetwork->init(); - /* - if (!TheGameSpyGame->amIHost()) - TheNetwork->setLocalAddress((207<<24) | (138<<16) | (47<<8) | 15, 8088); - else - */ - TheNetwork->setLocalAddress(TheGameSpyGame->getLocalIP(), TheNAT->getSlotPort(TheGameSpyGame->getLocalSlotNum())); - TheNetwork->attachTransport(TheNAT->getTransport()); - - user = TheGameSpyInfo->getLocalName(); - for (Int i=0; igetSlot(i); - if (!slot) - { - DEBUG_CRASH(("No GameSlot[%d]!", i)); - delete TheNetwork; - TheNetwork = NULL; - return; - } - -// UnsignedInt ip = htonl(slot->getIP()); - UnsignedInt ip = slot->getIP(); - AsciiString tmpUserName; - tmpUserName.translate(slot->getName()); - if (ip) - { - /* - if (i == 1) - { - user.format(",%s@207.138.47.15:8088", tmpUserName.str()); - } - else - */ - { - user.format(",%s@%d.%d.%d.%d:%d", tmpUserName.str(), - ((ip & 0xff000000) >> 24), - ((ip & 0xff0000) >> 16), - ((ip & 0xff00) >> 8), - ((ip & 0xff)), - TheNAT->getSlotPort(i) - ); - } - userList.concat(user); - } - } - userList.trim(); - - TheNetwork->parseUserList(TheGameSpyGame); - - // shutdown the top, but do not pop it off the stack -// TheShell->hideShell(); - // setup the Global Data with the Map and Seed - TheGlobalData->m_pendingFile = TheGameSpyGame->getMap(); - - if (TheGameLogic->isInGame()) { - TheGameLogic->clearGameData(); - } - // send a message to the logic for a new game - GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_NEW_GAME ); - msg->appendIntegerArgument(GAME_INTERNET); - - TheGlobalData->m_useFpsLimit = false; - - // Set the random seed - InitGameLogicRandom( TheGameSpyGame->getSeed() ); - DEBUG_LOG(("InitGameLogicRandom( %d )\n", TheGameSpyGame->getSeed())); - - if (TheNAT != NULL) { - delete TheNAT; - TheNAT = NULL; - } - } -} - -void GameSpyGameInfo::init( void ) -{ - GameInfo::init(); - - m_hasBeenQueried = false; -} - -void GameSpyGameInfo::resetAccepted( void ) -{ - GameInfo::resetAccepted(); - - if (m_hasBeenQueried && amIHost()) - { - // ANCIENTMUNKEE peerStateChanged(TheGameSpyChat->getPeer()); - m_hasBeenQueried = false; - DEBUG_LOG(("resetAccepted() called peerStateChange()\n")); - } -} - -Int GameSpyGameInfo::getLocalSlotNum( void ) const -{ - DEBUG_ASSERTCRASH(m_inGame, ("Looking for local game slot while not in game")); - if (!m_inGame) - return -1; - - AsciiString localName = TheGameSpyInfo->getLocalName(); - - for (Int i=0; iisPlayer(localName)) - return i; - } - return -1; -} - -void GameSpyGameInfo::gotGOACall( void ) -{ - DEBUG_LOG(("gotGOACall()\n")); - m_hasBeenQueried = true; -} - -void GameSpyGameInfo::startGame(Int gameID) -{ - DEBUG_LOG(("GameSpyGameInfo::startGame - game id = %d\n", gameID)); - DEBUG_ASSERTCRASH(m_transport == NULL, ("m_transport is not NULL when it should be")); - DEBUG_ASSERTCRASH(TheNAT == NULL, ("TheNAT is not NULL when it should be")); - - // fill in GS-specific info - for (Int i=0; igetPlayerInfoMap(); - PlayerInfoMap::iterator it = pInfoMap->find(gsName); - if (it != pInfoMap->end()) - { - m_GameSpySlot[i].setProfileID(it->second.m_profileID); - m_GameSpySlot[i].setLocale(it->second.m_locale); - } - else - { - DEBUG_CRASH(("No player info for %s", gsName.str())); - } - } - } - - if (TheNAT != NULL) { - delete TheNAT; - TheNAT = NULL; - } - TheNAT = NEW NAT(); - TheNAT->attachSlotList(m_slot, getLocalSlotNum(), m_localIP); - TheNAT->establishConnectionPaths(); -} - -AsciiString GameSpyGameInfo::generateGameResultsPacket( void ) -{ - Int i; - Int endFrame = TheVictoryConditions->getEndFrame(); - Int localSlotNum = getLocalSlotNum(); - //GameSlot *localSlot = getSlot(localSlotNum); - Bool sawGameEnd = (endFrame > 0);// && localSlot->lastFrameInGame() <= endFrame); - Int winningTeam = -1; - Int numPlayers = 0; - Int numTeamsAtGameEnd = 0; - Int lastTeamAtGameEnd = -1; - for (i=0; ifindPlayerWithNameKey(NAMEKEY(playerName)); - if (p) - { - ++numPlayers; - if (TheVictoryConditions->hasAchievedVictory(p)) - { - winningTeam = getSlot(i)->getTeamNumber(); - } - - // check if he lasted - GameSlot *slot = getSlot(i); - if (!slot->disconnected()) - { - if (slot->getTeamNumber() != lastTeamAtGameEnd || numTeamsAtGameEnd == 0) - { - lastTeamAtGameEnd = slot->getTeamNumber(); - ++numTeamsAtGameEnd; - } - } - } - } - - AsciiString results; - results.format("seed=%d,slotNum=%d,sawDesync=%d,sawGameEnd=%d,winningTeam=%d,disconEnd=%d,duration=%d,numPlayers=%d,isQM=%d", - getSeed(), localSlotNum, TheNetwork->sawCRCMismatch(), sawGameEnd, winningTeam, (numTeamsAtGameEnd != 0), - endFrame, numPlayers, m_isQM); - - Int playerID = 0; - for (i=0; ifindPlayerWithNameKey(NAMEKEY(playerName)); - if (p) - { - GameSpyGameSlot *slot = &(m_GameSpySlot[i]); - ScoreKeeper *keeper = p->getScoreKeeper(); - AsciiString playerName = slot->getLoginName(); - Int gsPlayerID = slot->getProfileID(); - AsciiString locale = slot->getLocale(); - Int fps = TheNetwork->getAverageFPS(); - Int unitsKilled = keeper->getTotalUnitsDestroyed(); - Int unitsLost = keeper->getTotalUnitsLost(); - Int unitsBuilt = keeper->getTotalUnitsBuilt(); - Int buildingsKilled = keeper->getTotalBuildingsDestroyed(); - Int buildingsLost = keeper->getTotalBuildingsLost(); - Int buildingsBuilt = keeper->getTotalBuildingsBuilt(); - Int earnings = keeper->getTotalMoneyEarned(); - Int techCaptured = keeper->getTotalTechBuildingsCaptured(); - Bool disconnected = slot->disconnected(); - - AsciiString playerStr; - playerStr.format(",player%d=%s,playerID%d=%d,locale%d=%s", - playerID, playerName.str(), playerID, gsPlayerID, playerID, locale.str()); - results.concat(playerStr); - playerStr.format(",unitsKilled%d=%d,unitsLost%d=%d,unitsBuilt%d=%d", - playerID, unitsKilled, playerID, unitsLost, playerID, unitsBuilt); - results.concat(playerStr); - playerStr.format(",buildingsKilled%d=%d,buildingsLost%d=%d,buildingsBuilt%d=%d", - playerID, buildingsKilled, playerID, buildingsLost, playerID, buildingsBuilt); - results.concat(playerStr); - playerStr.format(",fps%d=%d,cash%d=%d,capturedTech%d=%d,discon%d=%d", - playerID, fps, playerID, earnings, playerID, techCaptured, playerID, disconnected); - results.concat(playerStr); - - ++playerID; - } - } - - // Add a trailing size value (so the server can ensure it got the entire packet) - int resultsLen = results.getLength()+10; - AsciiString tail; - tail.format("%10.10d", resultsLen); - results.concat(tail); - - return results; -} - diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpyOverlay.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpyOverlay.cpp deleted file mode 100644 index c44709d3d76..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpyOverlay.cpp +++ /dev/null @@ -1,333 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: wolscreens.cpp ////////////////////////////////////////////////////// -// Westwood Online screen setup/teardown -// Author: Matthew D. Campbell, November 2001 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine -#include "Common/AudioEventRTS.h" - -#include "GameClient/GadgetListBox.h" -#include "GameClient/GameText.h" -#include "GameClient/MessageBox.h" -#include "GameClient/ShellHooks.h" -//#include "GameNetwork/GameSpy.h" -//#include "GameNetwork/GameSpyGP.h" - -#include "GameNetwork/GameSpyOverlay.h" -//#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/BuddyThread.h" - -void deleteNotificationBox( void ); -static void raiseOverlays( void ); - -// Message boxes ------------------------------------- -static GameWindow *messageBoxWindow = NULL; -static GameWinMsgBoxFunc okFunc = NULL; -static GameWinMsgBoxFunc cancelFunc = NULL; -static Bool reOpenPlayerInfoFlag = FALSE; -/** - * messageBoxOK is called when a message box is destroyed - * by way of an OK button, so we can clear our pointers to it. - */ -static void messageBoxOK( void ) -{ - DEBUG_ASSERTCRASH(messageBoxWindow, ("Message box window went away without being there in the first place!")); - messageBoxWindow = NULL; - if (okFunc) - { - okFunc(); - okFunc = NULL; - } -} - -/** - * messageBoxCancel is called when a message box is destroyed - * by way of a Cancel button, so we can clear our pointers to it. - */ -static void messageBoxCancel( void ) -{ - DEBUG_ASSERTCRASH(messageBoxWindow, ("Message box window went away without being there in the first place!")); - messageBoxWindow = NULL; - if (cancelFunc) - { - cancelFunc(); - cancelFunc = NULL; - } -} - -/** - * clearGSMessageBoxes removes the current message box if - * one is present. This is usually done when putting up a - * second messageBox. - */ -void ClearGSMessageBoxes( void ) -{ - if (messageBoxWindow) - { - TheWindowManager->winDestroy(messageBoxWindow); - messageBoxWindow = NULL; - } - - if (okFunc) - { - okFunc = NULL; - } - - if (cancelFunc) - { - cancelFunc = NULL; - } -} - -/** - * GSMessageBoxOk puts up an OK dialog box and saves the - * pointers to it and its callbacks. - */ -void GSMessageBoxOk(UnicodeString title, UnicodeString message, GameWinMsgBoxFunc newOkFunc) -{ - ClearGSMessageBoxes(); - messageBoxWindow = MessageBoxOk(title, message, messageBoxOK); - okFunc = newOkFunc; -} - -/** - * GSMessageBoxOkCancel puts up an OK/Cancel dialog box and saves the - * pointers to it and its callbacks. - */ -void GSMessageBoxOkCancel(UnicodeString title, UnicodeString message, GameWinMsgBoxFunc newOkFunc, GameWinMsgBoxFunc newCancelFunc) -{ - ClearGSMessageBoxes(); - messageBoxWindow = MessageBoxOkCancel(title, message, messageBoxOK, messageBoxCancel); - okFunc = newOkFunc; - cancelFunc = newCancelFunc; -} - -/** - * GSMessageBoxYesNo puts up a Yes/No dialog box and saves the - * pointers to it and its callbacks. - */ -void GSMessageBoxYesNo(UnicodeString title, UnicodeString message, GameWinMsgBoxFunc newYesFunc, GameWinMsgBoxFunc newNoFunc) -{ - ClearGSMessageBoxes(); - messageBoxWindow = MessageBoxYesNo(title, message, messageBoxOK, messageBoxCancel); - okFunc = newYesFunc; - cancelFunc = newNoFunc; -} - -/** - * If the screen transitions underneath the dialog box, we - * need to raise it to keep it visible. - */ -void RaiseGSMessageBox( void ) -{ - raiseOverlays(); - - if (!messageBoxWindow) - return; - - messageBoxWindow->winBringToTop(); -} - -// Overlay screens ------------------------------------- - -/** - * gsOverlays holds a list of the .wnd files used in GS overlays. - * The entries *MUST* be in the same order as the GSOverlayType enum. - */ -static const char * gsOverlays[GSOVERLAY_MAX] = -{ - "Menus/PopupPlayerInfo.wnd", // Player info (right-click) - "Menus/WOLMapSelectMenu.wnd", // Map select - "Menus/WOLBuddyOverlay.wnd", // Buddy list - "Menus/WOLPageOverlay.wnd", // Find/page - "Menus/PopupHostGame.wnd", // Hosting options (game name, password, etc) - "Menus/PopupJoinGame.wnd", // Joining options (password, etc) - "Menus/PopupLadderSelect.wnd",// LadderSelect - "Menus/PopupLocaleSelect.wnd",// Prompt for user's locale - "Menus/OptionsMenu.wnd", // popup options -}; - -static WindowLayout *overlayLayouts[GSOVERLAY_MAX] = -{ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, -}; - -static void buddyTryReconnect( void ) -{ - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_RELOGIN; - TheGameSpyBuddyMessageQueue->addRequest( req ); -} - -void GameSpyOpenOverlay( GSOverlayType overlay ) -{ - if (overlay == GSOVERLAY_BUDDY) - { - if (!TheGameSpyBuddyMessageQueue->isConnected()) - { - // not connected - is it because we were disconnected? - if (TheGameSpyBuddyMessageQueue->getLocalProfileID()) - { - // used to be connected - GSMessageBoxYesNo(TheGameText->fetch("GUI:GPErrorTitle"), TheGameText->fetch("GUI:GPDisconnected"), buddyTryReconnect, NULL); - } - else - { - // no profile - GSMessageBoxOk(TheGameText->fetch("GUI:GPErrorTitle"), TheGameText->fetch("GUI:GPNoProfile"), NULL); - } - return; - } - AudioEventRTS buttonClick("GUICommunicatorOpen"); - - if( TheAudio ) - { - TheAudio->addAudioEvent( &buttonClick ); - } // end if - } - if (overlayLayouts[overlay]) - { - overlayLayouts[overlay]->hide( FALSE ); - overlayLayouts[overlay]->bringForward(); - } - else - { - overlayLayouts[overlay] = TheWindowManager->winCreateLayout( AsciiString( gsOverlays[overlay] ) ); - overlayLayouts[overlay]->runInit(); - overlayLayouts[overlay]->hide( FALSE ); - overlayLayouts[overlay]->bringForward(); - } -} - -void GameSpyCloseOverlay( GSOverlayType overlay ) -{ - switch(overlay) - { - case GSOVERLAY_PLAYERINFO: - DEBUG_LOG(("Closing overlay GSOVERLAY_PLAYERINFO\n")); - break; - case GSOVERLAY_MAPSELECT: - DEBUG_LOG(("Closing overlay GSOVERLAY_MAPSELECT\n")); - break; - case GSOVERLAY_BUDDY: - DEBUG_LOG(("Closing overlay GSOVERLAY_BUDDY\n")); - break; - case GSOVERLAY_PAGE: - DEBUG_LOG(("Closing overlay GSOVERLAY_PAGE\n")); - break; - case GSOVERLAY_GAMEOPTIONS: - DEBUG_LOG(("Closing overlay GSOVERLAY_GAMEOPTIONS\n")); - break; - case GSOVERLAY_GAMEPASSWORD: - DEBUG_LOG(("Closing overlay GSOVERLAY_GAMEPASSWORD\n")); - break; - case GSOVERLAY_LADDERSELECT: - DEBUG_LOG(("Closing overlay GSOVERLAY_LADDERSELECT\n")); - break; - case GSOVERLAY_OPTIONS: - DEBUG_LOG(("Closing overlay GSOVERLAY_OPTIONS\n")); - if( overlayLayouts[overlay] ) - { - SignalUIInteraction(SHELL_SCRIPT_HOOK_OPTIONS_CLOSED); - } - break; - } - if( overlayLayouts[overlay] ) - { - overlayLayouts[overlay]->runShutdown(); - overlayLayouts[overlay]->destroyWindows(); - overlayLayouts[overlay]->deleteInstance(); - overlayLayouts[overlay] = NULL; - } -} - -Bool GameSpyIsOverlayOpen( GSOverlayType overlay ) -{ - return (overlayLayouts[overlay] != NULL); -} - -void GameSpyToggleOverlay( GSOverlayType overlay ) -{ - if (GameSpyIsOverlayOpen(overlay)) - GameSpyCloseOverlay(overlay); - else - GameSpyOpenOverlay(overlay); -} - -void raiseOverlays( void ) -{ - for (int i=0; ibringForward(); - } - } -} - -void GameSpyCloseAllOverlays( void ) -{ - for (int i=0; irunUpdate(); - } - } -} - -void ReOpenPlayerInfo( void ) -{ - reOpenPlayerInfoFlag = TRUE; -} -void CheckReOpenPlayerInfo(void ) -{ - if(!reOpenPlayerInfoFlag) - return; - - GameSpyOpenOverlay(GSOVERLAY_PLAYERINFO); - reOpenPlayerInfoFlag = FALSE; - -} diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpyPersistentStorage.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpyPersistentStorage.cpp deleted file mode 100644 index 742f9737653..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpyPersistentStorage.cpp +++ /dev/null @@ -1,392 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameSpyPersistentStorage.cpp ////////////////////////////////////////////////////// -// GameSpy Persistent Storage callbacks, utils, etc -// Author: Matthew D. Campbell, March 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "GameSpy/gstats/gpersist.h" - -#include "GameClient/Shell.h" -#include "GameClient/MessageBox.h" -#include "GameNetwork/GameSpy.h" -#include "GameNetwork/GameSpyGP.h" -#include "GameNetwork/GameSpyPersistentStorage.h" -#include "GameNetwork/GameSpyThread.h" - -static Bool isProfileAuthorized = false; - -static Bool gameSpyInitPersistentStorageConnection( void ); -static void getPersistentDataCallback(int localid, int profileid, persisttype_t type, int index, int success, char *data, int len, void *instance); -static void setPersistentDataCallback(int localid, int profileid, persisttype_t type, int index, int success, void *instance); - - -class GameSpyPlayerInfo : public GameSpyPlayerInfoInterface -{ -public: - GameSpyPlayerInfo() { m_locale.clear(); m_wins = m_losses = m_operationCount = 0; m_shouldDisconnect = false; } - virtual ~GameSpyPlayerInfo() { reset(); } - - virtual void init( void ) { m_locale.clear(); m_wins = m_losses = m_operationCount = 0; queueDisconnect(); }; - virtual void reset( void ) { m_locale.clear(); m_wins = m_losses = m_operationCount = 0; queueDisconnect(); }; - virtual void update( void ); - - virtual AsciiString getLocale( void ) { return m_locale; } - virtual Int getWins( void ) { return m_wins; } - virtual Int getLosses( void ) { return m_losses; } - - virtual void setLocale( AsciiString locale, Bool setOnServer ); - virtual void setWins( Int wins, Bool setOnServer ); - virtual void setLosses( Int losses, Bool setOnServer ); - - virtual void readFromServer( void ); - virtual void threadReadFromServer( void ); - virtual void threadSetLocale( AsciiString val ); - virtual void threadSetWins ( AsciiString val ); - virtual void threadSetLosses( AsciiString val ); - - void queueDisconnect( void ) { MutexClass::LockClass m(TheGameSpyMutex); if (IsStatsConnected()) m_shouldDisconnect = true; else m_shouldDisconnect = false; } - -private: - void setValue( AsciiString key, AsciiString val, Bool setOnServer ); - - AsciiString m_locale; - Int m_wins; - Int m_losses; - Int m_operationCount; - Bool m_shouldDisconnect; -}; - -void GameSpyPlayerInfo::update( void ) -{ - if (IsStatsConnected()) - { - if (m_shouldDisconnect) - { - DEBUG_LOG(("Persistent Storage close\n")); - CloseStatsConnection(); - } - else - { - PersistThink(); - } - } -} - -void GameSpyPlayerInfo::readFromServer( void ) -{ - TheGameSpyThread->queueReadPersistentStatsFromServer(); -} - -void GameSpyPlayerInfo::threadReadFromServer( void ) -{ - MutexClass::LockClass m(TheGameSpyMutex); - if (gameSpyInitPersistentStorageConnection()) - { - // get persistent info - m_operationCount++; - DEBUG_LOG(("GameSpyPlayerInfo::readFromServer() operation count = %d\n", m_operationCount)); - GetPersistDataValues(0, TheGameSpyChat->getProfileID(), pd_public_rw, 0, "\\locale\\wins\\losses", getPersistentDataCallback, &m_operationCount); - } - else - { - //TheGameSpyThread->setNextShellScreen("Menus/WOLWelcomeMenu.wnd"); - //TheShell->pop(); - //TheShell->push("Menus/WOLWelcomeMenu.wnd"); - } -} - -void GameSpyPlayerInfo::setLocale( AsciiString locale, Bool setOnServer ) -{ - m_locale = locale; - - if (!TheGameSpyChat->getProfileID() || !setOnServer) - return; - - setValue("locale", m_locale, setOnServer); -} - -void GameSpyPlayerInfo::setWins( Int wins, Bool setOnServer ) -{ - m_wins = wins; - - if (!TheGameSpyChat->getProfileID() || !setOnServer) - return; - - AsciiString winStr; - winStr.format("%d", wins); - - setValue("wins", winStr, setOnServer); -} - -void GameSpyPlayerInfo::setLosses( Int losses, Bool setOnServer ) -{ - m_losses = losses; - - if (!TheGameSpyChat->getProfileID() || !setOnServer) - return; - - AsciiString lossesStr; - lossesStr.format("%d", losses); - - setValue("losses", lossesStr, setOnServer); -} - -void GameSpyPlayerInfo::setValue( AsciiString key, AsciiString val, Bool setOnServer ) -{ - if (!setOnServer) - return; - - if (key == "locale") - TheGameSpyThread->queueUpdateLocale(val); - else if (key == "wins") - TheGameSpyThread->queueUpdateWins(val); - else if (key == "losses") - TheGameSpyThread->queueUpdateLosses(val); -} - -void GameSpyPlayerInfo::threadSetLocale( AsciiString val ) -{ - MutexClass::LockClass m(TheGameSpyMutex); - if (!gameSpyInitPersistentStorageConnection()) - return; - - // set locale info - AsciiString key = "locale"; - AsciiString str; - str.format("\\%s\\%s", key.str(), val.str()); - char *writable = strdup(str.str()); - m_operationCount++; - DEBUG_LOG(("GameSpyPlayerInfo::set%s() operation count = %d\n", key.str(), m_operationCount)); - SetPersistDataValues(0, TheGameSpyChat->getProfileID(), pd_public_rw, 0, writable, setPersistentDataCallback, &m_operationCount); - free(writable); -} - -void GameSpyPlayerInfo::threadSetWins( AsciiString val ) -{ - MutexClass::LockClass m(TheGameSpyMutex); - if (!gameSpyInitPersistentStorageConnection()) - return; - - // set win info - AsciiString key = "wins"; - AsciiString str; - str.format("\\%s\\%s", key.str(), val.str()); - char *writable = strdup(str.str()); - m_operationCount++; - DEBUG_LOG(("GameSpyPlayerInfo::set%s() operation count = %d\n", key.str(), m_operationCount)); - SetPersistDataValues(0, TheGameSpyChat->getProfileID(), pd_public_rw, 0, writable, setPersistentDataCallback, &m_operationCount); - free(writable); -} - -void GameSpyPlayerInfo::threadSetLosses( AsciiString val ) -{ - MutexClass::LockClass m(TheGameSpyMutex); - if (!gameSpyInitPersistentStorageConnection()) - return; - - // set loss info - AsciiString key = "losses"; - AsciiString str; - str.format("\\%s\\%s", key.str(), val.str()); - char *writable = strdup(str.str()); - m_operationCount++; - DEBUG_LOG(("GameSpyPlayerInfo::set%s() operation count = %d\n", key.str(), m_operationCount)); - SetPersistDataValues(0, TheGameSpyChat->getProfileID(), pd_public_rw, 0, writable, setPersistentDataCallback, &m_operationCount); - free(writable); -} - -GameSpyPlayerInfoInterface *TheGameSpyPlayerInfo = NULL; - -GameSpyPlayerInfoInterface *createGameSpyPlayerInfo( void ) -{ - return NEW GameSpyPlayerInfo; -} - - - - - - - - - -static void persAuthCallback(int localid, int profileid, int authenticated, char *errmsg, void *instance) -{ - DEBUG_LOG(("Auth callback: localid: %d profileid: %d auth: %d err: %s\n",localid, profileid, authenticated, errmsg)); - isProfileAuthorized = (authenticated != 0); -} - -static void getPersistentDataCallback(int localid, int profileid, persisttype_t type, int index, int success, char *data, int len, void *instance) -{ - DEBUG_LOG(("Data get callback: localid: %d profileid: %d success: %d len: %d data: %s\n",localid, profileid, success, len, data)); - - if (!TheGameSpyPlayerInfo) - { - //TheGameSpyThread->setNextShellScreen("Menus/WOLWelcomeMenu.wnd"); - //TheShell->pop(); - //TheShell->push("Menus/WOLWelcomeMenu.wnd"); - return; - } - - AsciiString str = data; - AsciiString key, val; - while (!str.isEmpty()) - { - str.nextToken(&key, "\\"); - str.nextToken(&val, "\\"); - if (!key.isEmpty() && !val.isEmpty()) - { - if (!key.compareNoCase("locale")) - { - TheGameSpyPlayerInfo->setLocale(val, false); - } - else if (!key.compareNoCase("wins")) - { - TheGameSpyPlayerInfo->setWins(atoi(val.str()), false); - } - else if (!key.compareNoCase("losses")) - { - TheGameSpyPlayerInfo->setLosses(atoi(val.str()), false); - } - } - } - - // decrement count of active operations - Int *opCount = (Int *)instance; - (*opCount) --; - DEBUG_LOG(("getPersistentDataCallback() operation count = %d\n", (*opCount))); - if (!*opCount) - { - DEBUG_LOG(("getPersistentDataCallback() queue disconnect\n")); - ((GameSpyPlayerInfo *)TheGameSpyPlayerInfo)->queueDisconnect(); - } - - const char *keys[3] = { "locale", "wins", "losses" }; - char valueStrings[3][20]; - char *values[3] = { valueStrings[0], valueStrings[1], valueStrings[2] }; - _snprintf(values[0], 20, "%s", TheGameSpyPlayerInfo->getLocale().str()); - _snprintf(values[1], 20, "%d", TheGameSpyPlayerInfo->getWins()); - _snprintf(values[2], 20, "%d", TheGameSpyPlayerInfo->getLosses()); - peerSetGlobalKeys(TheGameSpyChat->getPeer(), 3, (const char **)keys, (const char **)values); - peerSetGlobalWatchKeys(TheGameSpyChat->getPeer(), GroupRoom, 3, keys, PEERTrue); - peerSetGlobalWatchKeys(TheGameSpyChat->getPeer(), StagingRoom, 3, keys, PEERTrue); - - // choose next screen - if (TheGameSpyPlayerInfo->getLocale().isEmpty()) - { - TheGameSpyThread->setShowLocaleSelect(true); - } -} - -static void setPersistentDataCallback(int localid, int profileid, persisttype_t type, int index, int success, void *instance) -{ - DEBUG_LOG(("Data save callback: localid: %d profileid: %d success: %d\n", localid, profileid, success)); - - Int *opCount = (Int *)instance; - (*opCount) --; - DEBUG_LOG(("setPersistentDataCallback() operation count = %d\n", (*opCount))); - if (!*opCount) - { - DEBUG_LOG(("setPersistentDataCallback() queue disconnect\n")); - ((GameSpyPlayerInfo *)TheGameSpyPlayerInfo)->queueDisconnect(); - } -} - -static Bool gameSpyInitPersistentStorageConnection( void ) -{ - if (IsStatsConnected()) - return true; - - isProfileAuthorized = false; - Int result; - - /********* - First step, set our game authentication info - We could do: - strcpy(gcd_gamename,"gmtest"); - strcpy(gcd_secret_key,"HA6zkS"); - ...but this is more secure: - **********/ - gcd_gamename[0]='g';gcd_gamename[1]='m';gcd_gamename[2]='t';gcd_gamename[3]='e'; - gcd_gamename[4]='s';gcd_gamename[5]='t';gcd_gamename[6]='\0'; - gcd_secret_key[0]='H';gcd_secret_key[1]='A';gcd_secret_key[2]='6';gcd_secret_key[3]='z'; - gcd_secret_key[4]='k';gcd_secret_key[5]='S';gcd_secret_key[6]='\0'; - - /********* - Next, open the stats connection. This may block for - a 1-2 seconds, so it should be done before the actual game starts. - **********/ - result = InitStatsConnection(0); - - if (result != GE_NOERROR) - { - DEBUG_LOG(("InitStatsConnection returned %d\n",result)); - return isProfileAuthorized; - } - - if (TheGameSpyChat->getProfileID()) - { - char validate[33]; - - /*********** - We'll go ahead and start the authentication, using a Presence & Messaging SDK - profileid / password. To generate the new validation token, we'll need to pass - in the password for the profile we are authenticating. - Again, if this is done in a client/server setting, with the Persistent Storage - access being done on the server, and the P&M SDK is used on the client, the - server will need to send the challenge (GetChallenge(NULL)) to the client, the - client will create the validation token using GenerateAuth, and send it - back to the server for use in PreAuthenticatePlayerPM - ***********/ - char *munkeeHack = strdup(TheGameSpyChat->getPassword().str()); // GenerateAuth takes a char*, not a const char* :P - GenerateAuth(GetChallenge(NULL), munkeeHack, validate); - free (munkeeHack); - - /************ - After we get the validation token, we pass it and the profileid of the user - we are authenticating into PreAuthenticatePlayerPM. - We pass the same authentication callback as for the first user, but a different - localid this time. - ************/ - PreAuthenticatePlayerPM(0, TheGameSpyChat->getProfileID(), validate, persAuthCallback, NULL); - } - else - { - return isProfileAuthorized; - } - - UnsignedInt timeoutTime = timeGetTime() + 5000; - while (!isProfileAuthorized && timeGetTime() < timeoutTime && IsStatsConnected()) - { - PersistThink(); - msleep(10); - } - - DEBUG_LOG(("Persistent Storage connect: %d\n", isProfileAuthorized)); - return isProfileAuthorized; -} - diff --git a/Generals/Code/GameEngine/Source/GameNetwork/NAT.cpp b/Generals/Code/GameEngine/Source/GameNetwork/NAT.cpp deleted file mode 100644 index 7ed1f134e25..00000000000 --- a/Generals/Code/GameEngine/Source/GameNetwork/NAT.cpp +++ /dev/null @@ -1,1325 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: NAT.cpp ///////////////////////////////////////////////////////////////////////////////// -// Author: Bryan Cleveland April 2002 -// Props to Steve Tall for figuring all the NAT and Firewall behavior patterns out, making my job -// a LOT easier. -// Desc: Resolves NAT'd IPs and port numbers for the other players in a game. -/////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "GameNetwork/NAT.h" -#include "GameNetwork/Transport.h" -#include "GameNetwork/NetworkDefs.h" -#include "GameClient/EstablishConnectionsMenu.h" -#include "GameNetwork/NetworkInterface.h" -#include "GameNetwork/GameInfo.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpy/GSConfig.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -/* - * In case you're wondering, we do this weird connection pairing scheme - * to speed up the negotiation process, especially in cases where there - * are 4 or more players (nodes). Take for example an 8 player game... - * In an 8 player game there are 28 connections that need to be negotiated, - * doing this pairing scheme thing, we can make those 28 connections in the - * time it would normally take to make 7 connections. Since each connection - * could potentially take several seconds, this can be a HUGE time savings. - - * Right now you're probably wondering who this Bryan Cleveland guy is. - * He's the network coder that got fired when this didn't work. - - * In case you're wondering, this did end up working and Bryan left by - * his own choice. - */ -// m_connectionPairs[num nodes] [round] [node index] -/* static */ Int NAT::m_connectionPairs[MAX_SLOTS-1][MAX_SLOTS-1][MAX_SLOTS] = -{ - { // 2 nodes - // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7 - { 1, 0, -1, -1, -1, -1, -1, -1}, // round 0 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 1 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 2 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 3 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 4 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 5 - { -1, -1, -1, -1, -1, -1, -1, -1} // round 6 - }, - { // 3 nodes - // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7 - { 1, 0, -1, -1, -1, -1, -1, -1}, // round 0 - { 2, -1, 0, -1, -1, -1, -1, -1}, // round 1 - { -1, 2, 1, -1, -1, -1, -1, -1}, // round 2 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 3 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 4 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 5 - { -1, -1, -1, -1, -1, -1, -1, -1} // round 6 - }, - { // 4 nodes - // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7 - { 1, 0, 3, 2, -1, -1, -1, -1}, // round 0 - { 2, 3, 0, 1, -1, -1, -1, -1}, // round 1 - { 3, 2, 1, 0, -1, -1, -1, -1}, // round 2 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 3 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 4 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 5 - { -1, -1, -1, -1, -1, -1, -1, -1} // round 6 - }, - { // 5 nodes - // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7 - { 2, 4, 0, -1, 1, -1, -1, -1}, // round 0 - { -1, 3, 4, 1, 2, -1, -1, -1}, // round 1 - { 3, 2, 1, 0, -1, -1, -1, -1}, // round 2 - { 4, -1, 3, 2, 0, -1, -1, -1}, // round 3 - { 1, 0, -1, 4, 3, -1, -1, -1}, // round 4 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 5 - { -1, -1, -1, -1, -1, -1, -1, -1} // round 6 - }, - { // 6 nodes - // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7 - { 3, 5, 4, 0, 2, 1, -1, -1}, // round 0 - { 2, 4, 0, 5, 1, 3, -1, -1}, // round 1 - { 4, 3, 5, 1, 0, 2, -1, -1}, // round 2 - { 1, 0, 3, 2, 5, 4, -1, -1}, // round 3 - { 5, 2, 1, 4, 3, 0, -1, -1}, // round 4 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 5 - { -1, -1, -1, -1, -1, -1, -1, -1} // round 6 - }, - { // 7 nodes - // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7 - { -1, 6, 5, 4, 3, 2, 1, -1}, // round 0 - { 2, -1, 0, 6, 5, 4, 3, -1}, // round 1 - { 4, 3, -1, 1, 0, 6, 5, -1}, // round 2 - { 6, 5, 4, -1, 2, 1, 0, -1}, // round 3 - { 1, 0, 6, 5, -1, 3, 2, -1}, // round 4 - { 3, 2, 1, 0, 6, -1, 4, -1}, // round 5 - { 5, 4, 3, 2, 1, 0, -1, -1} // round 6 - }, - { // 8 nodes - // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7 - { 4, 5, 6, 7, 0, 1, 2, 3}, // round 0 - { 5, 4, 7, 6, 1, 0, 3, 2}, // round 1 - { 3, 6, 5, 0, 7, 2, 1, 4}, // round 2 - { 2, 7, 0, 5, 6, 3, 4, 1}, // round 3 - { 6, 3, 4, 1, 2, 7, 0, 5}, // round 4 - { 1, 0, 3, 2, 5, 4, 7, 6}, // round 5 - { 7, 2, 1, 4, 3, 6, 5, 0} // round 6 - } -}; - -/* static */ Int NAT::m_timeBetweenRetries = 500; // .5 seconds between retries sounds good to me. -/* static */ time_t NAT::m_manglerRetryTimeInterval = 300; // sounds good to me. -/* static */ Int NAT::m_maxAllowedManglerRetries = 25; // works for me. -/* static */ time_t NAT::m_keepaliveInterval = 15000; // 15 seconds between keepalive packets seems good. -/* static */ time_t NAT::m_timeToWaitForPort = 15000; // wait for 15 seconds for the other player's port number. -/* static */ time_t NAT::m_timeForRoundTimeout = 15000; // wait for at most 15 seconds for each connection round to finish. - -NAT *TheNAT = NULL; - -NAT::NAT() -{ - //Added By Sadullah Nader - //Initializations inserted - m_beenProbed = FALSE; - m_connectionPairIndex = 0; - m_connectionRound = 0; - m_localIP = 0; - m_localNodeNumber = 0; - m_manglerAddress = 0; - m_manglerRetries = 0; - m_numNodes = 0; - m_numRetries = 0; - m_previousSourcePort = 0; - for(Int i = 0; i < MAX_SLOTS; i++) - m_sourcePorts[i] = 0; - m_spareSocketPort = 0; - m_startingPortNumber = 0; - m_targetNodeNumber = 0; - // - m_transport = NULL; - m_slotList = NULL; - m_roundTimeout = 0; - - m_maxNumRetriesAllowed = 10; - m_packetID = 0x7f00; -} - -NAT::~NAT() { -} - -// if we're already finished, change to being idle -// if we are negotiating now, check to see if this round is done -// if it is, check to see if we're completely done with all rounds. -// if we are, set state to be done. -// if not go on to the next connection round. -// if we are negotiating still, call the connection update -// check to see if this connection is done for us, or if it has failed. -enum { MS_TO_WAIT_FOR_STATS = 5000 }; -NATStateType NAT::update() { - static UnsignedInt s_startStatWaitTime = 0; - if (m_NATState == NATSTATE_DONE) { - m_NATState = NATSTATE_IDLE; - } else if (m_NATState == NATSTATE_WAITFORSTATS) { - // check for all stats - Bool gotAllStats = TRUE; - Bool timedOut = FALSE; - for (Int i=0; igetGameSpySlot(i); - if (slot && slot->isHuman()) - { - PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(slot->getProfileID()); - if (stats.id == 0) - { - gotAllStats = FALSE; - //DEBUG_LOG(("Failed to find stats for %ls(%d)\n", slot->getName().str(), slot->getProfileID())); - } - } - } - // check for timeout. Timing out is not a fatal error - it just means we didn't get the other - // player's stats. We'll see 0/0 as his record, but we can still play him just fine. - UnsignedInt now = timeGetTime(); - if (now > s_startStatWaitTime + MS_TO_WAIT_FOR_STATS) - { - DEBUG_LOG(("Timed out waiting for stats. Let's just start the dang game.\n")); - timedOut = TRUE; - } - if (gotAllStats || timedOut) - { - m_NATState = NATSTATE_DONE; - TheEstablishConnectionsMenu->endMenu(); - if (TheFirewallHelper != NULL) { - delete TheFirewallHelper; - TheFirewallHelper = NULL; - } - } - } else if (m_NATState == NATSTATE_DOCONNECTIONPATHS) { - if (allConnectionsDoneThisRound() == TRUE) { - // we finished this round, move on to the next one. - ++m_connectionRound; -// m_roundTimeout = timeGetTime() + TheGameSpyConfig->getRoundTimeout(); - m_roundTimeout = timeGetTime() + m_timeForRoundTimeout; - DEBUG_LOG(("NAT::update - done with connection round, moving on to round %d\n", m_connectionRound)); - - // we finished that round, now check to see if we're done, or if there are more rounds to go. - if (allConnectionsDone() == TRUE) { - // we're all done, time to go back home. - m_NATState = NATSTATE_WAITFORSTATS; - - // 2/19/03 BGC - we have successfully negotaited a NAT thingy, so our behavior must be correct - // so therefore we don't need to refresh our NAT even if we previously thought we had to. - TheFirewallHelper->flagNeedToRefresh(FALSE); - - s_startStatWaitTime = timeGetTime(); - DEBUG_LOG(("NAT::update - done with all connections, woohoo!!\n")); - /* - m_NATState = NATSTATE_DONE; - TheEstablishConnectionsMenu->endMenu(); - if (TheFirewallHelper != NULL) { - delete TheFirewallHelper; - TheFirewallHelper = NULL; - } - */ - } else { - doThisConnectionRound(); - } - } - NATConnectionState state = connectionUpdate(); - - if (timeGetTime() > m_roundTimeout) { - DEBUG_LOG(("NAT::update - round timeout expired\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - notifyUsersOfConnectionFailed(m_localNodeNumber); - } - - if (state == NATCONNECTIONSTATE_FAILED) { - // if we fail - m_NATState = NATSTATE_FAILED; - TheEstablishConnectionsMenu->endMenu(); - if (TheFirewallHelper != NULL) { - // we failed NAT negotiation, perhaps we need to redetect our firewall settings. - // We don't trust the user to do it for themselves so we force them to do it next time - // the log in. - // 2/19/03 - ok, we don't want to do this right away, if the user tries to play in another game - // before they log out and log back in the game won't have a chance at working. - // so we need to simply flag it so that when they log out the firewall behavior gets blown away. - TheFirewallHelper->flagNeedToRefresh(TRUE); -// TheWritableGlobalData->m_firewallBehavior = FirewallHelperClass::FIREWALL_TYPE_UNKNOWN; -// TheFirewallHelper->writeFirewallBehavior(); - - delete TheFirewallHelper; - TheFirewallHelper = NULL; - } - // we failed to connect, so we don't have to pass on the transport to the network. - if (m_transport != NULL) { - delete m_transport; - m_transport = NULL; - } - } - } - return m_NATState; -} - - -// update transport, check for PROBE packets from our target. -// check to see if its time to PROBE our target -// MANGLER: -// if we are talking to the mangler, check to see if we got a response -// if we didn't get a response, check to see if its time to send another packet to it -NATConnectionState NAT::connectionUpdate() { - - GameSlot *targetSlot = NULL; - if (m_targetNodeNumber >= 0) { - targetSlot = m_slotList[m_connectionNodes[m_targetNodeNumber].m_slotIndex]; - } else { - return m_connectionStates[m_localNodeNumber]; - } - - if (m_beenProbed == FALSE) { - if (timeGetTime() >= m_nextPortSendTime) { -// sendMangledPortNumberToTarget(m_previousSourcePort, targetSlot); - sendMangledPortNumberToTarget(m_sourcePorts[m_targetNodeNumber], targetSlot); -// m_nextPortSendTime = timeGetTime() + TheGameSpyConfig->getRetryInterval(); - m_nextPortSendTime = timeGetTime() + m_timeBetweenRetries; - } - } - - // check to see if its time to send out our keepalives. - if (timeGetTime() >= m_nextKeepaliveTime) { - for (Int node = 0; node < m_numNodes; ++node) { - if (m_myConnections[node] == TRUE) { - // we've made this connection, send a keepalive. - Int slotIndex = m_connectionNodes[node].m_slotIndex; - GameSlot *slot = m_slotList[slotIndex]; - DEBUG_ASSERTCRASH(slot != NULL, ("Trying to send keepalive to a NULL slot")); - if (slot != NULL) { - UnsignedInt ip = slot->getIP(); - DEBUG_LOG(("NAT::connectionUpdate - sending keep alive to node %d at %d.%d.%d.%d:%d\n", node, - ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff, slot->getPort())); - m_transport->queueSend(ip, slot->getPort(), (const unsigned char *)"KEEPALIVE", strlen("KEEPALIVE") + 1); - } - } - } -// m_nextKeepaliveTime = timeGetTime() + TheGameSpyConfig->getKeepaliveInterval(); - m_nextKeepaliveTime = timeGetTime() + m_keepaliveInterval; - } - - m_transport->update(); - - // check to see if we've been probed. - for (Int i = 0; i < MAX_MESSAGES; ++i) { - if (m_transport->m_inBuffer[i].length > 0) { -#ifdef DEBUG_LOGGING - UnsignedInt ip = m_transport->m_inBuffer[i].addr; -#endif - DEBUG_LOG(("NAT::connectionUpdate - got a packet from %d.%d.%d.%d:%d, length = %d\n", - ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff, m_transport->m_inBuffer[i].port, m_transport->m_inBuffer[i].length)); - UnsignedByte *data = m_transport->m_inBuffer[i].data; - if (memcmp(data, "PROBE", strlen("PROBE")) == 0) { - Int fromNode = atoi((char *)data + strlen("PROBE")); - DEBUG_LOG(("NAT::connectionUpdate - we've been probed by node %d.\n", fromNode)); - - if (fromNode == m_targetNodeNumber) { - DEBUG_LOG(("NAT::connectionUpdate - probe was sent by our target, setting connection state %d to done.\n", m_targetNodeNumber)); - setConnectionState(m_targetNodeNumber, NATCONNECTIONSTATE_DONE); - - if (m_transport->m_inBuffer[i].addr != targetSlot->getIP()) { - UnsignedInt fromIP = m_transport->m_inBuffer[i].addr; -#ifdef DEBUG_LOGGING - UnsignedInt slotIP = targetSlot->getIP(); -#endif - DEBUG_LOG(("NAT::connectionUpdate - incomming packet has different from address than we expected, incoming: %d.%d.%d.%d expected: %d.%d.%d.%d\n", - fromIP >> 24, (fromIP >> 16) & 0xff, (fromIP >> 8) & 0xff, fromIP & 0xff, - slotIP >> 24, (slotIP >> 16) & 0xff, (slotIP >> 8) & 0xff, slotIP & 0xff)); - targetSlot->setIP(fromIP); - } - if (m_transport->m_inBuffer[i].port != targetSlot->getPort()) { - DEBUG_LOG(("NAT::connectionUpdate - incoming packet came from a different port than we expected, incoming: %d expected: %d\n", - m_transport->m_inBuffer[i].port, targetSlot->getPort())); - targetSlot->setPort(m_transport->m_inBuffer[i].port); - m_sourcePorts[m_targetNodeNumber] = m_transport->m_inBuffer[i].port; - } - notifyUsersOfConnectionDone(m_targetNodeNumber); - } - - m_transport->m_inBuffer[i].length = 0; - } - if (memcmp(data, "KEEPALIVE", strlen("KEEPALIVE")) == 0) { - // keep alive packet, just toss it. - DEBUG_LOG(("NAT::connectionUpdate - got keepalive from %d.%d.%d.%d:%d\n", - ip >> 24, (ip >> 16) & 0xff, (ip >> 8) && 0xff, ip & 0xff, m_transport->m_inBuffer[i].port)); - m_transport->m_inBuffer[i].length = 0; - } - } - } - - // we are waiting for our target to tell us that they have received our probe. - if (m_connectionStates[m_localNodeNumber] == NATCONNECTIONSTATE_WAITINGFORRESPONSE) { - // check to see if it's time to probe our target. - if ((m_timeTillNextSend != -1) && (m_timeTillNextSend <= timeGetTime())) { - if (m_numRetries > m_maxNumRetriesAllowed) { - DEBUG_LOG(("NAT::connectionUpdate - too many retries, connection failed.\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - - notifyUsersOfConnectionFailed(m_localNodeNumber); - } else { - DEBUG_LOG(("NAT::connectionUpdate - trying to send another probe (#%d) to our target\n", m_numRetries+1)); - // Send a probe. - sendAProbe(targetSlot->getIP(), targetSlot->getPort(), m_localNodeNumber); -// m_timeTillNextSend = timeGetTime() + TheGameSpyConfig->getRetryInterval(); - m_timeTillNextSend = timeGetTime() + m_timeBetweenRetries; - - // tell the target they've been probed. In other words, our port is open. - notifyTargetOfProbe(targetSlot); - - ++m_numRetries; - } - } - } - - // we are waiting for a response from the mangler to tell us what port we're using. - if (m_connectionStates[m_localNodeNumber] == NATCONNECTIONSTATE_WAITINGFORMANGLERRESPONSE) { - UnsignedShort mangledPort = 0; - if (TheFirewallHelper != NULL) { - mangledPort = TheFirewallHelper->getManglerResponse(m_packetID); - } - if (mangledPort != 0) { - // we got a response. now we need to start probing (unless of course we have a netgear) - processManglerResponse(mangledPort); - - // we know there is a firewall helper if we got here. - TheFirewallHelper->closeSpareSocket(m_spareSocketPort); - m_spareSocketPort = 0; - } else { - if (timeGetTime() >= m_manglerRetryTime) { - ++m_manglerRetries; -// if (m_manglerRetries > TheGameSpyConfig->getMaxManglerRetries()) { - if (m_manglerRetries > m_maxAllowedManglerRetries) { - // we couldn't communicate with the mangler, just use our non-mangled - // port number and hope that works. - DEBUG_LOG(("NAT::connectionUpdate - couldn't talk with the mangler using default port number\n")); - sendMangledPortNumberToTarget(getSlotPort(m_connectionNodes[m_localNodeNumber].m_slotIndex), targetSlot); - m_sourcePorts[m_targetNodeNumber] = getSlotPort(m_connectionNodes[m_localNodeNumber].m_slotIndex); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORRESPONSE); - } else { - if (TheFirewallHelper != NULL) { - DEBUG_LOG(("NAT::connectionUpdate - trying to send to the mangler again. mangler address: %d.%d.%d.%d, from port: %d, packet ID:%d\n", - m_manglerAddress >> 24, (m_manglerAddress >> 16) & 0xff, (m_manglerAddress >> 8) & 0xff, m_manglerAddress & 0xff, m_spareSocketPort, m_packetID)); - TheFirewallHelper->sendToManglerFromPort(m_manglerAddress, m_spareSocketPort, m_packetID); - } -// m_manglerRetryTime = TheGameSpyConfig->getRetryInterval() + timeGetTime(); - m_manglerRetryTime = m_manglerRetryTimeInterval + timeGetTime(); - } - } - } - } - - if (m_connectionStates[m_localNodeNumber] == NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT) { - if (timeGetTime() > m_timeoutTime) { - DEBUG_LOG(("NAT::connectionUpdate - waiting too long to get the other player's port number, failed.\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - - notifyUsersOfConnectionFailed(m_localNodeNumber); - } - } - - return m_connectionStates[m_localNodeNumber]; -} - -// this is the function that starts the NAT/firewall negotiation process. -// after calling this, you should call the update function untill it returns -// NATSTATE_DONE. -void NAT::establishConnectionPaths() { - DEBUG_LOG(("NAT::establishConnectionPaths - entering\n")); - m_NATState = NATSTATE_DOCONNECTIONPATHS; - DEBUG_LOG(("NAT::establishConnectionPaths - using %d as our starting port number\n", m_startingPortNumber)); - if (TheEstablishConnectionsMenu == NULL) { - TheEstablishConnectionsMenu = NEW EstablishConnectionsMenu; - } - TheEstablishConnectionsMenu->initMenu(); - - if (TheFirewallHelper == NULL) { - TheFirewallHelper = createFirewallHelper(); - } - - DEBUG_ASSERTCRASH(m_slotList != NULL, ("NAT::establishConnectionPaths - don't have a slot list")); - if (m_slotList == NULL) { - return; - } - - // determine how many nodes we have. - m_numNodes = 0; - for (Int i = 0; i < MAX_SLOTS; ++i) { - if (m_slotList[i] != NULL) { - if (m_slotList[i]->isHuman()) { - DEBUG_LOG(("NAT::establishConnectionPaths - slot %d is %ls\n", i, m_slotList[i]->getName().str())); - ++m_numNodes; - } - } - } - DEBUG_LOG(("NAT::establishConnectionPaths - number of nodes: %d\n", m_numNodes)); - - if (m_numNodes < 2) - { - // just start the game - there isn't anybody to which to connect. :P - m_NATState = NATSTATE_DONE; - return; - } - - m_connectionRound = 0; - m_connectionPairIndex = m_numNodes - 2; - Bool connectionAssigned[MAX_SLOTS]; - - for (i = 0; i < MAX_SLOTS; ++i) { - m_connectionNodes[i].m_slotIndex = -1; - connectionAssigned[i] = FALSE; - m_sourcePorts[i] = 0; - } - - m_previousSourcePort = 0; - -// check for netgear bug behavior. -// as an aside, if there are more than 2 netgear bug firewall's in the game, -// it probably isn't going to work so well. stupid netgear. - -// nodes with a netgear bug behavior need to be matched up first. This prevents -// the NAT table from being reset for connections to other nodes. This also happens -// to be the reason why I call them "nodes" rather than "slots" or "players" as the -// ordering has to be messed with to get the netgears to make love, not war. - DEBUG_LOG(("NAT::establishConnectionPaths - about to set up the node list\n")); - DEBUG_LOG(("NAT::establishConnectionPaths - doing the netgear stuff\n")); - UnsignedInt otherNetgearNum = -1; - for (i = 0; i < MAX_SLOTS; ++i) { - if ((m_slotList != NULL) && (m_slotList[i] != NULL)) { - if ((m_slotList[i]->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) != 0) { - if (otherNetgearNum == -1) { - // this is the start of a new pair, put it in as the first non -1 node connection pair thing. - Int nodeindex = 0; - while ((m_connectionPairs[m_connectionPairIndex][0][nodeindex] == -1) || (m_connectionNodes[nodeindex].m_slotIndex != -1)) { - ++nodeindex; - } - m_connectionNodes[nodeindex].m_slotIndex = i; - m_connectionNodes[nodeindex].m_behavior = m_slotList[i]->getNATBehavior(); - connectionAssigned[i] = TRUE; - otherNetgearNum = nodeindex; - DEBUG_LOG(("NAT::establishConnectionPaths - first netgear in pair. assigning node %d to slot %d (%ls)\n", nodeindex, i, m_slotList[i]->getName().str())); - } else { - // this is the second in the pair of netgears, pair this up with the other one - // for the first round. - Int nodeindex = 0; - while (m_connectionPairs[m_connectionPairIndex][0][nodeindex] != otherNetgearNum) { - ++nodeindex; - } - m_connectionNodes[nodeindex].m_slotIndex = i; - m_connectionNodes[nodeindex].m_behavior = m_slotList[i]->getNATBehavior(); - connectionAssigned[i] = TRUE; - otherNetgearNum = -1; - DEBUG_LOG(("NAT::establishConnectionPaths - second netgear in pair. assigning node %d to slot %d (%ls)\n", nodeindex, i, m_slotList[i]->getName().str())); - } - } - } - } - - // fill in the rest of the nodes with the remaining slots. - DEBUG_LOG(("NAT::establishConnectionPaths - doing the non-Netgear nodes\n")); - for (i = 0; i < MAX_SLOTS; ++i) { - if (connectionAssigned[i] == TRUE) { - continue; - } - if (m_slotList[i] == NULL) { - continue; - } - if (!(m_slotList[i]->isHuman())) { - continue; - } - // find the first available connection node for this slot. - Int nodeindex = 0; - while (m_connectionNodes[nodeindex].m_slotIndex != -1) { - ++nodeindex; - } - DEBUG_LOG(("NAT::establishConnectionPaths - assigning node %d to slot %d (%ls)\n", nodeindex, i, m_slotList[i]->getName().str())); - m_connectionNodes[nodeindex].m_slotIndex = i; - m_connectionNodes[nodeindex].m_behavior = m_slotList[i]->getNATBehavior(); - connectionAssigned[i] = TRUE; - } - -// sanity check -#if defined(_DEBUG) || defined(_INTERNAL) - for (i = 0; i < m_numNodes; ++i) { - DEBUG_ASSERTCRASH(connectionAssigned[i] == TRUE, ("connection number %d not assigned", i)); - } -#endif - - // find the local node number. - for (i = 0; i < m_numNodes; ++i) { - if (m_connectionNodes[i].m_slotIndex == TheGameSpyGame->getLocalSlotNum()) { - m_localNodeNumber = i; - DEBUG_LOG(("NAT::establishConnectionPaths - local node is %d\n", m_localNodeNumber)); - break; - } - } - - // set up the names in the connection window. - Int playerNum = 0; - for (i = 0; i < MAX_SLOTS; ++i) { - while ((i < MAX_SLOTS) && (m_slotList[i] != NULL) && !(m_slotList[i]->isHuman())) { - ++i; - } - if (i >= MAX_SLOTS) { - break; - } - if (i != TheGameSpyGame->getLocalSlotNum()) { - TheEstablishConnectionsMenu->setPlayerName(playerNum, m_slotList[i]->getName()); - TheEstablishConnectionsMenu->setPlayerStatus(playerNum, NATCONNECTIONSTATE_WAITINGTOBEGIN); - ++playerNum; - } - } - -// m_roundTimeout = timeGetTime() + TheGameSpyConfig->getRoundTimeout(); - m_roundTimeout = timeGetTime() + m_timeForRoundTimeout; - - // make the connections for this round. - // this song is cool. - doThisConnectionRound(); -} - -void NAT::attachSlotList(GameSlot *slotList[], Int localSlot, UnsignedInt localIP) { - m_slotList = slotList; - m_localIP = localIP; - m_transport = new Transport; - DEBUG_LOG(("NAT::attachSlotList - initting the transport socket with address %d.%d.%d.%d:%d\n", - m_localIP >> 24, (m_localIP >> 16) & 0xff, (m_localIP >> 8) & 0xff, m_localIP & 0xff, getSlotPort(localSlot))); - - m_startingPortNumber = NETWORK_BASE_PORT_NUMBER + ((timeGetTime() / 1000) % 20000); - DEBUG_LOG(("NAT::attachSlotList - using %d as the starting port number\n", m_startingPortNumber)); - generatePortNumbers(slotList, localSlot); - m_transport->init(m_localIP, getSlotPort(localSlot)); -} - -Int NAT::getSlotPort(Int slot) { -// return (slot + m_startingPortNumber); - if (m_slotList[slot] != NULL) { - return m_slotList[slot]->getPort(); - } - return 0; -} - -void NAT::generatePortNumbers(GameSlot *slotList[], Int localSlot) { - for (Int i = 0; i < MAX_SLOTS; ++i) { - if (slotList[i] != NULL) { - if ((i == localSlot) && (TheWritableGlobalData->m_firewallPortOverride != 0)) { - slotList[i]->setPort(TheWritableGlobalData->m_firewallPortOverride); - } else { - slotList[i]->setPort(i + m_startingPortNumber); - } - } - } -} - -Transport * NAT::getTransport() { - return m_transport; -} - -// figure out which port I'll be using. -// send the port number to our target for this round. -// init the m_connectionStates for all players. -void NAT::doThisConnectionRound() { - DEBUG_LOG(("NAT::doThisConnectionRound - starting process for connection round %d\n", m_connectionRound)); - // clear out the states from the last round. - m_targetNodeNumber = -1; - - for (Int i = 0; i < MAX_SLOTS; ++i) { - setConnectionState(i, NATCONNECTIONSTATE_NOSTATE); - } - - m_beenProbed = FALSE; - m_numRetries = 0; - - for (i = 0; i < m_numNodes; ++i) { - Int targetNodeNumber = m_connectionPairs[m_connectionPairIndex][m_connectionRound][i]; - DEBUG_LOG(("NAT::doThisConnectionRound - node %d needs to connect to node %d\n", i, targetNodeNumber)); - if (targetNodeNumber != -1) { - if (i == m_localNodeNumber) { - m_targetNodeNumber = targetNodeNumber; - DEBUG_LOG(("NAT::doThisConnectionRound - Local node is connecting to node %d\n", m_targetNodeNumber)); - UnsignedInt targetSlotIndex = m_connectionNodes[(m_connectionPairs[m_connectionPairIndex][m_connectionRound][i])].m_slotIndex; - GameSlot *targetSlot = m_slotList[targetSlotIndex]; - GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]; - - DEBUG_ASSERTCRASH(localSlot != NULL, ("local slot is NULL")); - DEBUG_ASSERTCRASH(targetSlot != NULL, ("trying to negotiate with a NULL target slot, slot is %d", m_connectionPairs[m_connectionPairIndex][m_connectionRound][i])); - DEBUG_LOG(("NAT::doThisConnectionRound - Target slot index = %d (%ls)\n", targetSlotIndex, m_slotList[targetSlotIndex]->getName().str())); - DEBUG_LOG(("NAT::doThisConnectionRound - Target slot has NAT behavior 0x%8X, local slot has NAT behavior 0x%8X\n", targetSlot->getNATBehavior(), localSlot->getNATBehavior())); - -#if defined(DEBUG_LOGGING) - UnsignedInt targetIP = targetSlot->getIP(); - UnsignedInt localIP = localSlot->getIP(); -#endif - - DEBUG_LOG(("NAT::doThisConnectionRound - Target slot has IP %d.%d.%d.%d Local slot has IP %d.%d.%d.%d\n", - targetIP >> 24, (targetIP >> 16) & 0xff, (targetIP >> 8) & 0xff, targetIP & 0xff, - localIP >> 24, (localIP >> 16) & 0xff, (localIP >> 8) & 0xff, localIP & 0xff)); - - if (((targetSlot->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) == 0) && - ((localSlot->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) != 0)) { - - // we have a netgear bug type behavior and the target does not, so we need them to send to us - // first to avoid having our NAT table reset. - - DEBUG_LOG(("NAT::doThisConnectionRound - Local node has a netgear and the target node does not, need to delay our probe.\n")); - m_timeTillNextSend = -1; - } - - // figure out which port number I'm using for this connection - // this merely starts to talk to the mangler server, we have to keep calling - // the update function till we get a response. - DEBUG_LOG(("NAT::doThisConnectionRound - About to attempt to get the next mangled source port\n")); - sendMangledSourcePort(); -// m_nextPortSendTime = timeGetTime() + TheGameSpyConfig->getRetryInterval(); - m_nextPortSendTime = timeGetTime() + m_timeBetweenRetries; -// m_timeoutTime = timeGetTime() + TheGameSpyConfig->getPortTimeout(); - m_timeoutTime = timeGetTime() + m_timeToWaitForPort; - } else { - // this is someone else that needs to connect to someone, so wait till they tell us - // that they're done. - setConnectionState(i, NATCONNECTIONSTATE_WAITINGFORRESPONSE); - } - } else { - // no one to connect to, so this one is done. - DEBUG_LOG(("NAT::doThisConnectionRound - node %d has no one to connect to, so they're done\n", i)); - setConnectionState(i, NATCONNECTIONSTATE_DONE); - } - } -} - -void NAT::sendAProbe(UnsignedInt ip, UnsignedShort port, Int fromNode) { - DEBUG_LOG(("NAT::sendAProbe - sending a probe from port %d to %d.%d.%d.%d:%d\n", getSlotPort(m_connectionNodes[m_localNodeNumber].m_slotIndex), - ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff, port)); - AsciiString str; - str.format("PROBE%d", fromNode); - m_transport->queueSend(ip, port, (unsigned char *)str.str(), str.getLength() + 1); - m_transport->doSend(); -} - -// find the next mangled source port, and then send it to the other player. -// if this requires talking to the mangler, we'll have to wait till a later update -// to send our port out. -void NAT::sendMangledSourcePort() { - UnsignedShort sourcePort = getSlotPort(m_connectionNodes[m_localNodeNumber].m_slotIndex); - - FirewallHelperClass::tFirewallBehaviorType fwType = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]->getNATBehavior(); - GameSlot *targetSlot = m_slotList[m_connectionNodes[m_targetNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(targetSlot != NULL, ("NAT::sendMangledSourcePort - targetSlot is NULL")); - if (targetSlot == NULL) { - DEBUG_LOG(("NAT::sendMangledSourcePort - targetSlot is NULL, failed this connection\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - return; - } - - GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(localSlot != NULL, ("NAT::sendMangledSourcePort - localSlot is NULL, WTF?")); - if (localSlot == NULL) { - DEBUG_LOG(("NAT::sendMangledSourcePort - localSlot is NULL, failed this connection\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - return; - } - - // check to see if the target and I are behind the same NAT - if (targetSlot->getIP() == localSlot->getIP()) { -#if defined(DEBUG_LOGGING) - UnsignedInt localip = localSlot->getIP(); - UnsignedInt targetip = targetSlot->getIP(); -#endif - DEBUG_LOG(("NAT::sendMangledSourcePort - target and I are behind the same NAT, no mangling\n")); - DEBUG_LOG(("NAT::sendMangledSourcePort - I am %ls, target is %ls, my IP is %d.%d.%d.%d, target IP is %d.%d.%d.%d\n", localSlot->getName().str(), targetSlot->getName().str(), - localip >> 24, (localip >> 16) & 0xff, (localip >> 8) & 0xff, localip & 0xff, - targetip >> 24, (targetip >> 16) & 0xff, (targetip >> 8) & 0xff, targetip & 0xff)); - - sendMangledPortNumberToTarget(sourcePort, targetSlot); - m_sourcePorts[m_targetNodeNumber] = sourcePort; - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT); - // In case you're wondering, we don't set the m_previousSourcePort here because this will be a different source - // address than what other nodes will likely see (unless of course there are more than - // two of us behind the same NAT, but we won't worry about that cause theres no mangling - // in that case anyways) - return; - } - - // check to see if we are NAT'd at all. - if ((fwType == 0) || (fwType == FirewallHelperClass::FIREWALL_TYPE_SIMPLE)) { - // no mangling, just return the source port - DEBUG_LOG(("NAT::sendMangledSourcePort - no mangling, just using the source port\n")); - sendMangledPortNumberToTarget(sourcePort, targetSlot); - m_previousSourcePort = sourcePort; - m_sourcePorts[m_targetNodeNumber] = sourcePort; - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT); - return; - } - - // check to see if our NAT keeps the same source port for different destinations. - // if this is the case, and we've already worked out what our mangled port number is - // then we don't have to figure it out again. - if (((fwType & FirewallHelperClass::FIREWALL_TYPE_DESTINATION_PORT_DELTA) == 0) && - ((fwType & FirewallHelperClass::FIREWALL_TYPE_SMART_MANGLING) == 0)) { - DEBUG_LOG(("NAT::sendMangledSourcePort - our firewall doesn't NAT based on destination address, checking for old connections from this address\n")); - if (m_previousSourcePort != 0) { - DEBUG_LOG(("NAT::sendMangledSourcePort - Previous source port was %d, using that one\n", m_previousSourcePort)); - sendMangledPortNumberToTarget(m_previousSourcePort, targetSlot); - m_sourcePorts[m_targetNodeNumber] = m_previousSourcePort; - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT); - return; - } else { - DEBUG_LOG(("NAT::sendMangledSourcePort - Previous source port not found\n")); - } - } - - // At this point we know that our NAT uses some kind of relative port mapping scheme, so we - // need to talk to the mangler to find out where we are now so we can find out where we'll be on the - // next port allocation. - - // get the address of the mangler we need to talk to. - Char manglerName[256]; - FirewallHelperClass::getManglerName(1, manglerName); - DEBUG_LOG(("NAT::sendMangledSourcePort - about to call gethostbyname for mangler at %s\n", manglerName)); - struct hostent *hostInfo = gethostbyname(manglerName); - - if (hostInfo == NULL) { - DEBUG_LOG(("NAT::sendMangledSourcePort - gethostbyname failed for mangler address %s\n", manglerName)); - // can't find the mangler, we're screwed so just send the source port. - sendMangledPortNumberToTarget(sourcePort, targetSlot); - m_sourcePorts[m_targetNodeNumber] = sourcePort; - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT); - return; - } - - memcpy(&m_manglerAddress, &(hostInfo->h_addr_list[0][0]), 4); - m_manglerAddress = ntohl(m_manglerAddress); - DEBUG_LOG(("NAT::sendMangledSourcePort - mangler %s address is %d.%d.%d.%d\n", manglerName, - m_manglerAddress >> 24, (m_manglerAddress >> 16) & 0xff, (m_manglerAddress >> 8) & 0xff, m_manglerAddress & 0xff)); - - DEBUG_LOG(("NAT::sendMangledSourcePort - NAT behavior = 0x%08x\n", fwType)); - -// m_manglerRetryTime = TheGameSpyConfig->getRetryInterval() + timeGetTime(); - m_manglerRetryTime = m_manglerRetryTimeInterval + timeGetTime(); - m_manglerRetries = 0; - - if (TheFirewallHelper != NULL) { - m_spareSocketPort = TheFirewallHelper->getNextTemporarySourcePort(0); - TheFirewallHelper->openSpareSocket(m_spareSocketPort); - TheFirewallHelper->sendToManglerFromPort(m_manglerAddress, m_spareSocketPort, m_packetID); -// m_manglerRetryTime = TheGameSpyConfig->getRetryInterval() + timeGetTime(); - m_manglerRetryTime = m_manglerRetryTimeInterval + timeGetTime(); - } - - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLERRESPONSE); -} - -void NAT::processManglerResponse(UnsignedShort mangledPort) { - DEBUG_LOG(("NAT::processManglerResponse - Work out what my NAT'd port will be\n")); - - GameSlot *targetSlot = m_slotList[m_connectionNodes[m_targetNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(targetSlot != NULL, ("NAT::processManglerResponse - targetSlot is NULL")); - if (targetSlot == NULL) { - DEBUG_LOG(("NAT::processManglerResponse - targetSlot is NULL, failed this connection\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - return; - } - - Short delta = TheGlobalData->m_firewallPortAllocationDelta; - UnsignedShort sourcePort = getSlotPort(m_connectionNodes[m_localNodeNumber].m_slotIndex); - UnsignedShort returnPort = 0; - - FirewallHelperClass::tFirewallBehaviorType fwType = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]->getNATBehavior(); - - if ((fwType & FirewallHelperClass::FIREWALL_TYPE_SIMPLE_PORT_ALLOCATION) != 0) { - returnPort = mangledPort + delta; - } else { - // to steal a line from Steve Tall... - // Rats. It's a relative mangler. This is much harder. Damn NAT32 guy. - if (delta == 100) { - // Special NAT32 section. - // NAT32 mangles source UDP port by ading 1700 + 100*NAT table index. - returnPort = mangledPort - m_spareSocketPort; - returnPort -= 1700; - - returnPort += delta; - returnPort += sourcePort; - returnPort += 1700; - - } else if (delta == 0) { - returnPort = sourcePort; - } else { - returnPort = mangledPort / delta; - returnPort = returnPort * delta; - - returnPort += (sourcePort % delta); - returnPort += delta; - } - } - - // This bit is probably doomed. - if (returnPort > 65535) { - returnPort -= 65535; - } - if (returnPort < 1024) { - returnPort += 1024; - } - - DEBUG_LOG(("NAT::processManglerResponse - mangled port is %d\n", returnPort)); - m_previousSourcePort = returnPort; - - sendMangledPortNumberToTarget(returnPort, targetSlot); - m_sourcePorts[m_targetNodeNumber] = returnPort; - if (targetSlot->getPort() == 0) { - // we haven't got the target's mangled port number yet, wait for it. - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT); - } else { - // in this case we should have already sent a PROBE, so we'll just change the state - // and leave it at that. - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORRESPONSE); - } -} - -// check to see if we've completed all the rounds -// this is kind of a cheesy way to check, but it works. -Bool NAT::allConnectionsDone() { - if (m_numNodes == 2) { - if (m_connectionRound >= 1) { - return TRUE; - } - } else if (m_numNodes == 3) { - if (m_connectionRound >= 3) { - return TRUE; - } - } else if (m_numNodes == 4) { - if (m_connectionRound >= 3) { - return TRUE; - } - } else if (m_numNodes == 5) { - if (m_connectionRound >= 5) { - return TRUE; - } - } else if (m_numNodes == 6) { - if (m_connectionRound >= 5) { - return TRUE; - } - } else if (m_numNodes == 7) { - if (m_connectionRound >= 7) { - return TRUE; - } - } else if (m_numNodes == 8) { - if (m_connectionRound >= 7) { - return TRUE; - } - } - return FALSE; -} - -Bool NAT::allConnectionsDoneThisRound() { - Bool retval = TRUE; - for (Int i = 0; (i < m_numNodes) && (retval == TRUE); ++i) { - if ((m_connectionStates[i] != NATCONNECTIONSTATE_DONE) && (m_connectionStates[i] != NATCONNECTIONSTATE_FAILED)) { - retval = FALSE; - } - } - return retval; -} - -// this node's connection for this round has been completed. -void NAT::connectionComplete(Int slotIndex) { -} - -// this node's connection for this round has failed. -void NAT::connectionFailed(Int slotIndex) { -} - -// I have been probed by the target. -void NAT::probed(Int nodeNumber) { - GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(localSlot != NULL, ("NAT::probed - localSlot is NULL, WTF?")); - if (localSlot == NULL) { - DEBUG_LOG(("NAT::probed - localSlot is NULL, failed this connection\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - return; - } - - if (m_beenProbed == FALSE) { - m_beenProbed = TRUE; - DEBUG_LOG(("NAT::probed - just got probed for the first time.\n")); - if ((localSlot->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) != 0) { - DEBUG_LOG(("NAT::probed - we have a NETGEAR and we were just probed for the first time\n")); - GameSlot *targetSlot = m_slotList[m_connectionNodes[m_targetNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(targetSlot != NULL, ("NAT::probed - targetSlot is NULL")); - if (targetSlot == NULL) { - DEBUG_LOG(("NAT::probed - targetSlot is NULL, failed this connection\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - return; - } - - if (targetSlot->getPort() == 0) { - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT); - DEBUG_LOG(("NAT::probed - still waiting for mangled port\n")); - } else { - DEBUG_LOG(("NAT::probed - sending a probe to %ls\n", targetSlot->getName().str())); - sendAProbe(targetSlot->getIP(), targetSlot->getPort(), m_localNodeNumber); - notifyTargetOfProbe(targetSlot); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORRESPONSE); - } - } - } -} - -// got the mangled port for our target for this round. -void NAT::gotMangledPort(Int nodeNumber, UnsignedShort mangledPort) { - - // if we've already finished the connection, then we don't need to process this. - if (m_connectionStates[m_localNodeNumber] == NATCONNECTIONSTATE_DONE) { - DEBUG_LOG(("NAT::gotMangledPort - got a mangled port, but we've already finished this connection, ignoring.\n")); - return; - } - - GameSlot *targetSlot = m_slotList[m_connectionNodes[m_targetNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(targetSlot != NULL, ("NAT::gotMangledPort - targetSlot is NULL")); - if (targetSlot == NULL) { - DEBUG_LOG(("NAT::gotMangledPort - targetSlot is NULL, failed this connection\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - return; - } - - GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(localSlot != NULL, ("NAT::gotMangledPort - localSlot is NULL, WTF?")); - if (localSlot == NULL) { - DEBUG_LOG(("NAT::gotMangledPort - localSlot is NULL, failed this connection\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - return; - } - - if (nodeNumber != m_targetNodeNumber) { - DEBUG_LOG(("NAT::gotMangledPort - got a mangled port number for someone that isn't my target. node = %d, target node = %d\n", nodeNumber, m_targetNodeNumber)); - return; - } - - targetSlot->setPort(mangledPort); - DEBUG_LOG(("NAT::gotMangledPort - got mangled port number %d from our target node (%ls)\n", mangledPort, targetSlot->getName().str())); - if (((localSlot->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) == 0) || (m_beenProbed == TRUE) || - (((localSlot->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) != 0) && ((targetSlot->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) != 0))) { -#ifdef DEBUG_LOGGING - UnsignedInt ip = targetSlot->getIP(); -#endif - DEBUG_LOG(("NAT::gotMangledPort - don't have a netgear or we have already been probed, or both my target and I have a netgear, send a PROBE. Sending to %d.%d.%d.%d:%d\n", - ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff, targetSlot->getPort())); - - sendAProbe(targetSlot->getIP(), targetSlot->getPort(), m_localNodeNumber); - notifyTargetOfProbe(targetSlot); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORRESPONSE); - } else { - DEBUG_LOG(("NAT::gotMangledPort - we are a netgear, not sending a PROBE yet.\n")); - } -} - -void NAT::gotInternalAddress(Int nodeNumber, UnsignedInt address) { - GameSlot *targetSlot = m_slotList[m_connectionNodes[nodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(targetSlot != NULL, ("NAT::gotInternalAddress - targetSlot is NULL")); - if (targetSlot == NULL) { - return; - } - - GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(localSlot != NULL, ("NAT::gotInternalAddress - localSlot is NULL, WTF?")); - if (localSlot == NULL) { - return; - } - - if (nodeNumber != m_targetNodeNumber) { - DEBUG_LOG(("NAT::gotInternalAddress - got a internal address for someone that isn't my target. node = %d, target node = %d\n", nodeNumber, m_targetNodeNumber)); - return; - } - - if (localSlot->getIP() == targetSlot->getIP()) { - // we have the same IP address, i.e. we are behind the same NAT. - // I need to talk directly to his internal address. - DEBUG_LOG(("NAT::gotInternalAddress - target and local players have same external address, using internal address.\n")); - targetSlot->setIP(address); // use the slot's internal address from now on - } -} - -void NAT::notifyTargetOfProbe(GameSlot *targetSlot) { - PeerRequest req; - AsciiString options; - options.format("PROBED%d", m_localNodeNumber); - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "NAT/"; - AsciiString hostName; - hostName.translate(targetSlot->getName()); - req.nick = hostName.str(); - req.options = options.str(); - TheGameSpyPeerMessageQueue->addRequest(req); - DEBUG_LOG(("NAT::notifyTargetOfProbe - notifying %ls that we have probed them.\n", targetSlot->getName().str())); -} - -void NAT::notifyUsersOfConnectionDone(Int nodeIndex) { - GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(localSlot != NULL, ("NAT::notifyUsersOfConnectionDone - localSlot is NULL, WTF?")); - if (localSlot == NULL) { - DEBUG_LOG(("NAT::notifyUsersOfConnectionDone - localSlot is NULL, failed this connection\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - return; - } - - PeerRequest req; - AsciiString options; - options.format("CONNDONE%d %d", nodeIndex, m_localNodeNumber); - - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "NAT"; - AsciiString names; - for (Int i=0; iisHuman() == FALSE)) { - continue; - } - - AsciiString name; - name.translate(m_slotList[i]->getName()); - if (names.isNotEmpty()) - { - names.concat(','); - } - names.concat(name); - } - req.nick = names.str(); - req.options = options.str(); - - DEBUG_LOG(("NAT::notifyUsersOfConnectionDone - sending %s to %s\n", options.str(), names.str())); - TheGameSpyPeerMessageQueue->addRequest(req); -} - -void NAT::notifyUsersOfConnectionFailed(Int nodeIndex) { - GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(localSlot != NULL, ("NAT::notifyUsersOfConnectionFailed - localSlot is NULL, WTF?")); - if (localSlot == NULL) { - DEBUG_LOG(("NAT::notifyUsersOfConnectionFailed - localSlot is NULL, failed this connection\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - return; - } - - PeerRequest req; - AsciiString options; - options.format("CONNFAILED%d", nodeIndex); -/* - req.peerRequestType = PeerRequest::PEERREQUEST_UTMROOM; - req.UTM.isStagingRoom = TRUE; - req.id = "NAT/"; - req.options = options.str(); - - DEBUG_LOG(("NAT::notifyUsersOfConnectionFailed - sending %s to room\n", options.str())); -*/ - - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "NAT"; - AsciiString names; - for (Int i=0; iisHuman() == FALSE)) { - continue; - } - - AsciiString name; - name.translate(m_slotList[i]->getName()); - if (names.isNotEmpty()) - { - names.concat(','); - } - names.concat(name); - } - req.nick = names.str(); - req.options = options.str(); - - DEBUG_LOG(("NAT::notifyUsersOfConnectionFailed - sending %s to %s\n", options.str(), names.str())); - - TheGameSpyPeerMessageQueue->addRequest(req); -} - -void NAT::sendMangledPortNumberToTarget(UnsignedShort mangledPort, GameSlot *targetSlot) { - PeerRequest req; - AsciiString options; - options.format("PORT%d %d %08X", m_localNodeNumber, mangledPort, m_localIP); - - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "NAT/"; - AsciiString hostName; - hostName.translate(targetSlot->getName()); - req.nick = hostName.str(); - req.options = options.str(); - DEBUG_LOG(("NAT::sendMangledPortNumberToTarget - sending \"%s\" to %s\n", options.str(), hostName.str())); - TheGameSpyPeerMessageQueue->addRequest(req); -} - -void NAT::processGlobalMessage(Int slotNum, const char *options) { - const char *ptr = options; - // skip preceding whitespace. - while (isspace(*ptr)) { - ++ptr; - } - DEBUG_LOG(("NAT::processGlobalMessage - got message from slot %d, message is \"%s\"\n", slotNum, ptr)); - if (!strncmp(ptr, "PROBED", strlen("PROBED"))) { - // format: PROBED - // a probe has been sent at us, if we are waiting because of a netgear or something, we - // should start sending our own probes. - Int node = atoi(ptr + strlen("PROBED")); - if (node == m_targetNodeNumber) { - // make sure we're being probed by who we're supposed to be probed by. - probed(node); - } else { - DEBUG_LOG(("NAT::processGlobalMessage - probed by node %d, not our target\n", node)); - } - } else if (!strncmp(ptr, "CONNDONE", strlen("CONNDONE"))) { - // format: CONNDONE - // we should get the node number of the player who's connection is done from the options - // and mark that down as part of the connectionStates. - const char *c = ptr + strlen("CONNDONE"); -/* while (*c != ' ') { - ++c; - } - while (*c == ' ') { - ++c; - } -*/ Int node; - Int sendingNode; - sscanf(c, "%d %d\n", &node, &sendingNode); - - if (m_connectionPairs[m_connectionPairIndex][m_connectionRound][node] == sendingNode) { -// Int node = atoi(ptr + strlen("CONNDONE")); - DEBUG_LOG(("NAT::processGlobalMessage - got a CONNDONE message for node %d\n", node)); - if ((node >= 0) && (node <= m_numNodes)) { - DEBUG_LOG(("NAT::processGlobalMessage - node %d's connection is complete, setting connection state to done\n", node)); - setConnectionState(node, NATCONNECTIONSTATE_DONE); - } - } else { - DEBUG_LOG(("NAT::processGlobalMessage - got a connection done message that isn't from this round. node: %d sending node: %d\n", node, sendingNode)); - } - } else if (!strncmp(ptr, "CONNFAILED", strlen("CONNFAILED"))) { - // format: CONNFAILED - // we should get the node number of the player who's connection failed from the options - // and mark that down as part of the connectionStates. - Int node = atoi(ptr + strlen("CONNFAILED")); - if ((node >= 0) && (node < m_numNodes)) { - DEBUG_LOG(("NAT::processGlobalMessage - node %d's connection failed, setting connection state to failed\n", node)); - setConnectionState(node, NATCONNECTIONSTATE_FAILED); - } - } else if (!strncmp(ptr, "PORT", strlen("PORT"))) { - // format: PORT - // we should get the node number and the mangled port number of the client we - // are supposed to be communicating with and start probing them. No, that was not - // meant to be a phallic reference, you sicko. - const char *c = ptr + strlen("PORT"); - Int node = atoi(c); - while (*c != ' ') { - ++c; - } - while (*c == ' ') { - ++c; - } - UnsignedInt intport = 0; - UnsignedInt addr = 0; - sscanf(c, "%d %X", &intport, &addr); - UnsignedShort port = (UnsignedShort)intport; - - DEBUG_LOG(("NAT::processGlobalMessage - got port message from node %d, port: %d, internal address: %d.%d.%d.%d\n", node, port, - addr >> 24, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff)); - - if ((node >= 0) && (node < m_numNodes)) { - if (port < 1024) { - // it has to be less than 65535 cause its a short duh. - DEBUG_ASSERTCRASH(port >= 1024, ("Was passed an invalid port number")); - port += 1024; - } - gotInternalAddress(node, addr); - gotMangledPort(node, port); - } - } -} - -void NAT::setConnectionState(Int nodeNumber, NATConnectionState state) { - m_connectionStates[nodeNumber] = state; - - if (nodeNumber != m_localNodeNumber) { - return; - } - - // if this is the case we are starting a new round and we don't know - // who we're connecting to yet. - if (m_localNodeNumber == m_targetNodeNumber) { - return; - } - - // if this is the start of a new connection round we don't have a - // target yet. - if (m_targetNodeNumber == -1) { - return; - } - - // find the menu slot of the target node. - Int slotIndex = m_connectionNodes[m_targetNodeNumber].m_slotIndex; - Int slot = 0; - for (Int i = 0; i < MAX_SLOTS; ++i) { - if (m_slotList[i] != NULL) { - if (m_slotList[i]->isHuman()) { - if (i != m_connectionNodes[m_localNodeNumber].m_slotIndex) { - if (i == slotIndex) { - break; - } - ++slot; - } - } - } - } - if (i == MAX_SLOTS) { - DEBUG_ASSERTCRASH(i < MAX_SLOTS, ("Didn't find the node number in the slot list")); - return; - } - TheEstablishConnectionsMenu->setPlayerStatus(slot, state); -} diff --git a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DMainMenu.cpp b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DMainMenu.cpp index 580f7e75c4c..8da88662fe1 100644 --- a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DMainMenu.cpp +++ b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DMainMenu.cpp @@ -916,17 +916,11 @@ void W3DMainMenuInit( WindowLayout *layout, void *userData ) NameKeyType buttonUSAID = TheNameKeyGenerator->nameToKey( "MainMenu.wnd:ButtonUSA" ); NameKeyType buttonGLAID = TheNameKeyGenerator->nameToKey( "MainMenu.wnd:ButtonGLA" ); NameKeyType buttonChinaID = TheNameKeyGenerator->nameToKey( "MainMenu.wnd:ButtonChina" ); - NameKeyType skirmishID = TheNameKeyGenerator->nameToKey( AsciiString("MainMenu.wnd:ButtonSkirmish") ); - NameKeyType onlineID = TheNameKeyGenerator->nameToKey( AsciiString("MainMenu.wnd:ButtonOnline") ); - NameKeyType networkID = TheNameKeyGenerator->nameToKey( AsciiString("MainMenu.wnd:ButtonNetwork") ); + NameKeyType skirmishID = TheNameKeyGenerator->nameToKey( AsciiString("MainMenu.wnd:ButtonSkirmish") ); NameKeyType networkID = TheNameKeyGenerator->nameToKey( AsciiString("MainMenu.wnd:ButtonNetwork") ); GameWindow *button = TheWindowManager->winGetWindowFromId( parent, skirmishID ); if (button) - button->winSetDrawFunc(W3DMainMenuButtonDropShadowDraw); - button = TheWindowManager->winGetWindowFromId( parent, onlineID ); - if (button) - button->winSetDrawFunc(W3DMainMenuButtonDropShadowDraw); - button = TheWindowManager->winGetWindowFromId( parent, networkID ); + button->winSetDrawFunc(W3DMainMenuButtonDropShadowDraw); button = TheWindowManager->winGetWindowFromId( parent, networkID ); if (button) button->winSetDrawFunc(W3DMainMenuButtonDropShadowDraw); diff --git a/Generals/Code/Main/WinMain.cpp b/Generals/Code/Main/WinMain.cpp index e504e6db2a4..c6b1ab877f3 100644 --- a/Generals/Code/Main/WinMain.cpp +++ b/Generals/Code/Main/WinMain.cpp @@ -378,7 +378,6 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message, // ------------------------------------------------------------------------ case WM_CLOSE: - TheGameEngine->checkAbnormalQuitting(); TheGameEngine->reset(); TheGameEngine->setQuitting(TRUE); _exit(EXIT_SUCCESS); diff --git a/GeneralsMD/Code/GameEngine/GameEngine.dsp b/GeneralsMD/Code/GameEngine/GameEngine.dsp index 803e13bf105..2ddb395651f 100644 --- a/GeneralsMD/Code/GameEngine/GameEngine.dsp +++ b/GeneralsMD/Code/GameEngine/GameEngine.dsp @@ -42,7 +42,7 @@ RSC=rc.exe # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /G6 /MD /W3 /WX /GX /O2 /Ob2 /I "Include/Precompiled" /I "../Libraries/Source/WWVegas" /I "../Libraries/Source/WWVegas\WWLib" /I "Include" /I "../Libraries/Include" /I "../Libraries/Source/GameSpy" /I "../Libraries/Source/Compression" /D "IG_DEBUG_STACKTRACE" /D "NDEBUG" /D "_RELEASE" /D WINVER=0x400 /D "_MBCS" /D "_LIB" /D "_WINDOWS" /D "WIN32" /D "Z_PREFIX" /Yu"PreRTS.h" /FD /c +# ADD CPP /nologo /G6 /MD /W3 /WX /GX /O2 /Ob2 /I "Include/Precompiled" /I "../Libraries/Source/WWVegas" /I "../Libraries/Source/WWVegas\WWLib" /I "Include" /I "../Libraries/Include" /I "../Libraries/Source/Compression" /D "IG_DEBUG_STACKTRACE" /D "NDEBUG" /D "_RELEASE" /D WINVER=0x400 /D "_MBCS" /D "_LIB" /D "_WINDOWS" /D "WIN32" /D "Z_PREFIX" /Yu"PreRTS.h" /FD /c # SUBTRACT CPP /Fr # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" @@ -66,7 +66,7 @@ LIB32=link.exe -lib # PROP Intermediate_Dir "Debug" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /G6 /MDd /W3 /WX /Gm /GX /ZI /Od /I "..\Libraries\Source\WWVegas" /I "..\Libraries\Source\WWVegas\WWLib" /I "Include/Precompiled" /I "../Libraries/Source/WWVegas" /I "../Libraries/Source/WWVegas\WWLib" /I "Include" /I "../Libraries/Include" /I "../Libraries/Source/GameSpy" /I "../Libraries/Source/Compression" /D "_DEBUG" /D WINVER=0x400 /D "_MBCS" /D "_LIB" /D "_WINDOWS" /D "WIN32" /D "Z_PREFIX" /Yu"PreRTS.h" /FD /GZ /c +# ADD CPP /nologo /G6 /MDd /W3 /WX /Gm /GX /ZI /Od /I "..\Libraries\Source\WWVegas" /I "..\Libraries\Source\WWVegas\WWLib" /I "Include/Precompiled" /I "../Libraries/Source/WWVegas" /I "../Libraries/Source/WWVegas\WWLib" /I "Include" /I "../Libraries/Include" /I "../Libraries/Source/Compression" /D "_DEBUG" /D WINVER=0x400 /D "_MBCS" /D "_LIB" /D "_WINDOWS" /D "WIN32" /D "Z_PREFIX" /Yu"PreRTS.h" /FD /GZ /c # SUBTRACT CPP /Fr # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" @@ -90,7 +90,7 @@ LIB32=link.exe -lib # PROP Intermediate_Dir "Internal" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GR /GX /O2 /I "../Libraries/Source/WWVegas" /I "../Libraries/Source/WWVegas\WWLib" /I "Include" /I "../Libraries/Include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "_WINDOWS" /YX /FD /c -# ADD CPP /nologo /G6 /MD /W3 /WX /GX /Zi /Od /I "../Libraries/Source/Compression" /I "Include/Precompiled" /I "../Libraries/Source/WWVegas" /I "../Libraries/Source/WWVegas\WWLib" /I "Include" /I "../Libraries/Include" /I "../Libraries/Source/GameSpy" /D "NDEBUG" /D "_INTERNAL" /D WINVER=0x400 /D "_MBCS" /D "_LIB" /D "_WINDOWS" /D "WIN32" /D "Z_PREFIX" /Yu"PreRTS.h" /FD /c +# ADD CPP /nologo /G6 /MD /W3 /WX /GX /Zi /Od /I "../Libraries/Source/Compression" /I "Include/Precompiled" /I "../Libraries/Source/WWVegas" /I "../Libraries/Source/WWVegas\WWLib" /I "Include" /I "../Libraries/Include" /D "NDEBUG" /D "_INTERNAL" /D WINVER=0x400 /D "_MBCS" /D "_LIB" /D "_WINDOWS" /D "WIN32" /D "Z_PREFIX" /Yu"PreRTS.h" /FD /c # SUBTRACT CPP /Fr # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" @@ -2426,102 +2426,26 @@ SOURCE=.\Source\GameClient\Water.cpp # Begin Group "GameNetwork" # PROP Default_Filter "" -# Begin Group "GameSpy" - -# PROP Default_Filter "" -# Begin Group "Thread" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\Source\GameNetwork\GameSpy\Thread\BuddyThread.cpp -# End Source File -# Begin Source File - -SOURCE=.\Source\GameNetwork\GameSpy\Thread\GameResultsThread.cpp -# End Source File -# Begin Source File - -SOURCE=.\Source\GameNetwork\GameSpy\Thread\PeerThread.cpp -# End Source File -# Begin Source File - -SOURCE=.\Source\GameNetwork\GameSpy\Thread\PersistentStorageThread.cpp -# End Source File -# Begin Source File - -SOURCE=.\Source\GameNetwork\GameSpy\Thread\PingThread.cpp -# End Source File # Begin Source File -SOURCE=.\Source\GameNetwork\GameSpy\Thread\ThreadUtils.cpp -# End Source File -# End Group -# Begin Source File - -SOURCE=.\Source\GameNetwork\GameSpy\Chat.cpp -# End Source File # Begin Source File SOURCE=.\Source\GameNetwork\DownloadManager.cpp # End Source File # Begin Source File -SOURCE=.\Source\GameNetwork\GameSpyOverlay.cpp -# End Source File # Begin Source File -SOURCE=.\Source\GameNetwork\GameSpy\GSConfig.cpp -# End Source File # Begin Source File -SOURCE=.\Source\GameNetwork\GameSpy\LadderDefs.cpp -# End Source File # Begin Source File -SOURCE=.\Source\GameNetwork\GameSpy\LobbyUtils.cpp -# End Source File # Begin Source File -SOURCE=.\Source\GameNetwork\GameSpy\MainMenuUtils.cpp -# End Source File # Begin Source File -SOURCE=.\Source\GameNetwork\GameSpy\PeerDefs.cpp -# End Source File # Begin Source File -SOURCE=.\Source\GameNetwork\GameSpy\StagingRoomGameInfo.cpp -# End Source File -# End Group -# Begin Group "GameSpyEvalImplementation" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\Source\GameNetwork\GameSpy.cpp -# PROP Exclude_From_Build 1 -# End Source File -# Begin Source File - -SOURCE=.\Source\GameNetwork\GameSpyChat.cpp -# PROP Exclude_From_Build 1 -# End Source File -# Begin Source File - -SOURCE=.\Source\GameNetwork\GameSpyGameInfo.cpp -# PROP Exclude_From_Build 1 -# End Source File -# Begin Source File - -SOURCE=.\Source\GameNetwork\GameSpyGP.cpp -# PROP Exclude_From_Build 1 -# End Source File -# Begin Source File - -SOURCE=.\Source\GameNetwork\GameSpyPersistentStorage.cpp -# PROP Exclude_From_Build 1 -# End Source File # End Group # Begin Group "InGameNetwork" @@ -2858,10 +2782,6 @@ SOURCE=.\Include\Common\GameSpeech.h # End Source File # Begin Source File -SOURCE=.\Include\Common\GameSpyMiscPreferences.h -# End Source File -# Begin Source File - SOURCE=.\Include\Common\GameState.h # End Source File # Begin Source File @@ -4666,209 +4586,90 @@ SOURCE=.\Include\GameClient\WinInstanceData.h # PROP Default_Filter "" # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\md5.h -# End Source File # End Group # Begin Group "queryreporting" # PROP Default_Filter "" # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\queryreporting\gqueryreporting.h -# End Source File # End Group # Begin Group "pinger" # PROP Default_Filter "" # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\pinger\pinger.h -# End Source File # End Group # Begin Group "CEngine" # PROP Default_Filter "" # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\CEngine\goaceng.h -# End Source File # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\CEngine\gserver.h -# End Source File # End Group # Begin Group "hashtable" # PROP Default_Filter "" # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\hashtable.h -# End Source File # End Group # Begin Group "chat" # PROP Default_Filter "" # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\chat\chat.h -# End Source File # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\chat\chatCallbacks.h -# End Source File # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\chat\chatChannel.h -# End Source File # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\Chat\chatCrypt.h -# End Source File # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\chat\chatHandlers.h -# End Source File # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\chat\chatMain.h -# End Source File # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\chat\chatSocket.h -# End Source File # End Group # Begin Group "nonport" # PROP Default_Filter "" # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\nonport.h -# End Source File # End Group # Begin Group "darray" # PROP Default_Filter "" # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\darray.h -# End Source File # End Group # Begin Group "peer.H" # PROP Default_Filter "" # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\peer\peer.h -# End Source File # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\peer\peerCallbacks.h -# End Source File # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\peer\peerCEngine.h -# End Source File # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\peer\peerGlobalCallbacks.h -# End Source File # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\peer\peerKeys.h -# End Source File # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\peer\peerMain.h -# End Source File # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\peer\peerMangle.h -# End Source File # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\peer\peerOperations.h -# End Source File # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\peer\peerPing.h -# End Source File # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\peer\peerPlayers.h -# End Source File # Begin Source File -SOURCE=..\Libraries\Source\GameSpy\GameSpy\peer\peerRooms.h -# End Source File # End Group # End Group -# Begin Group "GameSpy.H" - -# PROP Default_Filter "" -# Begin Group "Thread.H" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpy\BuddyThread.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpy\GameResultsThread.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpy\PeerThread.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpy\PersistentStorageThread.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpy\PingThread.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpy\ThreadUtils.h -# End Source File -# End Group -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpy\BuddyDefs.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpy\GSConfig.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpy\LadderDefs.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpy\LobbyUtils.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpy\MainMenuUtils.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpy\PeerDefs.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpy\PeerDefsImplementation.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpy\PersistentStorageDefs.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpy\StagingRoomGameInfo.h -# End Source File # End Group # Begin Source File @@ -4916,34 +4717,6 @@ SOURCE=.\Include\GameNetwork\GameMessageParser.h # End Source File # Begin Source File -SOURCE=.\Include\GameNetwork\GameSpy.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpyChat.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpyGameInfo.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpyGP.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpyOverlay.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpyPersistentStorage.h -# End Source File -# Begin Source File - -SOURCE=.\Include\GameNetwork\GameSpyThread.h -# End Source File -# Begin Source File - SOURCE=.\Include\GameNetwork\GUIUtil.h # End Source File # Begin Source File diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/EstablishConnectionsMenu.h b/GeneralsMD/Code/GameEngine/Include/GameClient/EstablishConnectionsMenu.h index 7a8a8db403d..57eb0859a5a 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameClient/EstablishConnectionsMenu.h +++ b/GeneralsMD/Code/GameEngine/Include/GameClient/EstablishConnectionsMenu.h @@ -25,7 +25,16 @@ //// EstablishConnectionsMenu.h ///////////////////////// #include "GameNetwork/NetworkDefs.h" -#include "GameNetwork/NAT.h" + +// NAT traversal support has been removed; provide a minimal stub for compatibility. +enum NATConnectionState { + NATCONNECTIONSTATE_WAITINGFORMANGLERRESPONSE, + NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT, + NATCONNECTIONSTATE_WAITINGFORRESPONSE, + NATCONNECTIONSTATE_DONE, + NATCONNECTIONSTATE_FAILED, + NATCONNECTIONSTATE_WAITINGTOBEGIN +}; enum EstablishConnectionsMenuStateType { ESTABLISHCONNECTIONSMENUSTATETYPE_SCREENON, diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/GUICallbacks.h b/GeneralsMD/Code/GameEngine/Include/GameClient/GUICallbacks.h index 8d3bfd23f5d..f32301a5714 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameClient/GUICallbacks.h +++ b/GeneralsMD/Code/GameEngine/Include/GameClient/GUICallbacks.h @@ -270,12 +270,6 @@ extern WindowMsgHandledType WOLBuddyOverlayInput( GameWindow *window, UnsignedIn extern void WOLBuddyOverlayRCMenuInit( WindowLayout *layout, void *userData ); extern WindowMsgHandledType WOLBuddyOverlayRCMenuSystem( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 ); -// GameSpy Player Info Overlay --------------------------------------------------------------------------------- -extern void GameSpyPlayerInfoOverlayInit( WindowLayout *layout, void *userData ); -extern void GameSpyPlayerInfoOverlayUpdate( WindowLayout *layout, void *userData ); -extern void GameSpyPlayerInfoOverlayShutdown( WindowLayout *layout, void *userData ); -extern WindowMsgHandledType GameSpyPlayerInfoOverlaySystem( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 ); -extern WindowMsgHandledType GameSpyPlayerInfoOverlayInput( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 ); // Popup host Game Internet ----------------------------------------------------------------------------------- extern void PopupHostGameInit( WindowLayout *layout, void *userData ); diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/LoadScreen.h b/GeneralsMD/Code/GameEngine/Include/GameClient/LoadScreen.h index 4b0bbe457e3..80caab76a0f 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameClient/LoadScreen.h +++ b/GeneralsMD/Code/GameEngine/Include/GameClient/LoadScreen.h @@ -258,41 +258,6 @@ class MultiPlayerLoadScreen : public LoadScreen /////////////////////////////////////////////////////////////////////////////////////////////////// // class MultiPlayerLoadScreen is to be used for multiplayer communication on the loadscreens //// /////////////////////////////////////////////////////////////////////////////////////////////// -class GameSpyLoadScreen : public LoadScreen -{ -public: - GameSpyLoadScreen( void ); - virtual ~GameSpyLoadScreen( void ); - - virtual void init( GameInfo *game ); ///< Init the loadscreen - virtual void reset( void ); ///< Reset the system - virtual void update( void ) - { - DEBUG_CRASH(("Call update(Int) instead. This update isn't supported")); - }; - virtual void update(Int percent); ///< Update the state of the progress bar - void processProgress(Int playerId, Int percentage); - virtual void setProgressRange( Int min, Int max ) { } -private: - GameWindow *m_progressBars[MAX_SLOTS]; ///< pointer array to all the progress bars on the window - GameWindow *m_playerNames[MAX_SLOTS]; ///< pointer array to all the static text player names on the window - GameWindow *m_playerSide[MAX_SLOTS]; ///< pointer array to all the static text player sides - GameWindow *m_playerFavoriteFactions[MAX_SLOTS]; ///< pointer array to all the static text player sides - GameWindow *m_playerTotalDisconnects[MAX_SLOTS]; ///< pointer array to all the static text player sides - GameWindow *m_playerWin[MAX_SLOTS]; ///< pointer array to all the static text player sides - GameWindow *m_playerWinLosses[MAX_SLOTS]; ///< pointer array to all the static text player sides - GameWindow *m_playerRank[MAX_SLOTS]; ///< pointer array to all the static text player sides - GameWindow *m_playerOfficerMedal[MAX_SLOTS]; ///< pointer array to all the static text player munkees - GameWindow *m_mapPreview; - GameWindow *m_buttonMapStartPosition[MAX_SLOTS]; - - Int m_playerLookup[MAX_SLOTS]; ///< lookup table to translate network slot info screen slot (to account for holes in the slot list) - - GameWindow *m_portraitLocalGeneral; - GameWindow *m_featuresLocalGeneral; - GameWindow *m_nameLocalGeneral; -}; - /////////////////////////////////////////////////////////////////////////////////////////////////// // class MapTransferLoadScreen is to be used for map transfers before multiplayer game load screens //// /////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyDefs.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyDefs.h deleted file mode 100644 index 2d032020f84..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyDefs.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: BuddyDefs.h ////////////////////////////////////////////////////// -// Generals GameSpy Buddy (GP) definitions -// Author: Matthew D. Campbell, July 2002 - -#pragma once - -#ifndef __BUDDYDEFS_H__ -#define __BUDDYDEFS_H__ - -void HandleBuddyResponses(void); -void PopulateOldBuddyMessages(void); - -#endif // __BUDDYDEFS_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyThread.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyThread.h deleted file mode 100644 index 770f174053a..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyThread.h +++ /dev/null @@ -1,179 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: BuddyThread.h ////////////////////////////////////////////////////// -// Generals GameSpy BuddyList thread class interface -// Author: Matthew D. Campbell, June 2002 - -#pragma once - -#ifndef __BUDDYTHREAD_H__ -#define __BUDDYTHREAD_H__ - -#include "GameSpy/GP/GP.h" - -#define MAX_BUDDY_CHAT_LEN 128 - -// this class encapsulates a request for the buddy thread -class BuddyRequest -{ -public: - enum - { - BUDDYREQUEST_LOGIN, // attempt to login - BUDDYREQUEST_RELOGIN, // log in after being disconnected - BUDDYREQUEST_LOGOUT, // log out if connected - BUDDYREQUEST_MESSAGE, - BUDDYREQUEST_LOGINNEW, // attempt to create a new nick and login - //BUDDYREQUEST_DELETELOGIN, - BUDDYREQUEST_ADDBUDDY, // add someone to your buddy list - BUDDYREQUEST_DELBUDDY, // delete someone from your buddy list - BUDDYREQUEST_OKADD, // allow someone to add you to their buddy list - BUDDYREQUEST_DENYADD, // don't allow someone to add you to their buddy list - BUDDYREQUEST_SETSTATUS, // Set our status - BUDDYREQUEST_DELETEACCT, // Delete our account - BUDDYREQUEST_MAX - } buddyRequestType; - - union - { - struct - { - GPProfile recipient; - WideChar text[MAX_BUDDY_CHAT_LEN]; - } message; - - struct - { - char nick[GP_NICK_LEN]; - char email[GP_EMAIL_LEN]; - char password[GP_PASSWORD_LEN]; - Bool hasFirewall; - } login; - - struct - { - GPProfile id; - WideChar text[MAX_BUDDY_CHAT_LEN]; - } addbuddy; - - struct - { - GPProfile id; - } profile; - - struct - { - GPEnum status; - char statusString[GP_STATUS_STRING_LEN]; - char locationString[GP_LOCATION_STRING_LEN]; - } status; - - } arg; -}; - -//------------------------------------------------------------------------- - -// this class encapsulates an action the buddy thread wants from the UI -class BuddyResponse -{ -public: - enum - { - BUDDYRESPONSE_LOGIN, - BUDDYRESPONSE_DISCONNECT, - BUDDYRESPONSE_MESSAGE, - BUDDYRESPONSE_REQUEST, - BUDDYRESPONSE_STATUS, - BUDDYRESPONSE_MAX - } buddyResponseType; - - GPProfile profile; - GPResult result; - - union - { - struct - { - UnsignedInt date; - char nick[GP_NICK_LEN]; - WideChar text[MAX_BUDDY_CHAT_LEN]; - } message; - - struct - { - char nick[GP_NICK_LEN]; - char email[GP_EMAIL_LEN]; - char countrycode[GP_COUNTRYCODE_LEN]; - WideChar text[GP_REASON_LEN]; - } request; - - struct - { - //GPResult result; - GPErrorCode errorCode; - char errorString[MAX_BUDDY_CHAT_LEN]; - GPEnum fatal; - } error; - - struct - { - char nick[GP_NICK_LEN]; - char email[GP_EMAIL_LEN]; - char countrycode[GP_COUNTRYCODE_LEN]; - char location[GP_LOCATION_STRING_LEN]; - GPEnum status; - char statusString[GP_STATUS_STRING_LEN]; - } status; - } arg; -}; - -//------------------------------------------------------------------------- - -// this is the actual message queue used to pass messages between threads -class GameSpyBuddyMessageQueueInterface -{ -public: - virtual ~GameSpyBuddyMessageQueueInterface() {} - virtual void startThread( void ) = 0; - virtual void endThread( void ) = 0; - virtual Bool isThreadRunning( void ) = 0; - virtual Bool isConnected( void ) = 0; - virtual Bool isConnecting( void ) = 0; - - virtual void addRequest( const BuddyRequest& req ) = 0; - virtual Bool getRequest( BuddyRequest& req ) = 0; - - virtual void addResponse( const BuddyResponse& resp ) = 0; - virtual Bool getResponse( BuddyResponse& resp ) = 0; - - virtual GPProfile getLocalProfileID( void ) = 0; - - static GameSpyBuddyMessageQueueInterface* createNewMessageQueue( void ); -}; - -extern GameSpyBuddyMessageQueueInterface *TheGameSpyBuddyMessageQueue; - - -#endif // __BUDDYTHREAD_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/GSConfig.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/GSConfig.h deleted file mode 100644 index fb03080e9e1..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/GSConfig.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GSConfig.h /////////////////////////////////////////////////////////// -// Author: Matthew D. Campbell, Sept 2002 -// Description: GameSpy online config -/////////////////////////////////////////////////////////////////////////////// - -#pragma once - -#ifndef __GSCONFIG_H__ -#define __GSCONFIG_H__ - -#include "Common/AsciiString.h" -#include "Common/STLTypedefs.h" - -class GameSpyConfigInterface -{ -public: - virtual ~GameSpyConfigInterface() {} - - // Pings - virtual std::list getPingServers(void) = 0; - virtual Int getNumPingRepetitions(void) = 0; - virtual Int getPingTimeoutInMs(void) = 0; - virtual Int getPingCutoffGood( void ) = 0; - virtual Int getPingCutoffBad( void ) = 0; //Bryan sez, Maybe - - // QM - virtual std::list getQMMaps(void) = 0; - virtual Int getQMBotID(void) = 0; - virtual Int getQMChannel(void) = 0; - virtual void setQMChannel(Int channel) = 0; - - // Player Info - virtual Int getPointsForRank(Int rank) = 0; - virtual Bool isPlayerVIP(Int id) = 0; - - // mangler Info - virtual Bool getManglerLocation(Int index, AsciiString& host, UnsignedShort& port) = 0; - - // Ladder / Any other external parsing - virtual AsciiString getLeftoverConfig(void) = 0; - - // Custom match - virtual Bool restrictGamesToLobby() = 0; - static GameSpyConfigInterface* create(AsciiString config); -}; - -extern GameSpyConfigInterface *TheGameSpyConfig; - -#endif // __GSCONFIG_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/GameResultsThread.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/GameResultsThread.h deleted file mode 100644 index 76c91675855..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/GameResultsThread.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameResultsThread.h ////////////////////////////////////////////////////// -// Generals game results thread class interface -// Author: Matthew D. Campbell, August 2002 - -#pragma once - -#ifndef __GAMERESULTSTHREAD_H__ -#define __GAMERESULTSTHREAD_H__ - -#include "Common/SubsystemInterface.h" - -// this class encapsulates a request for the thread -class GameResultsRequest -{ -public: - std::string hostname; - UnsignedShort port; - std::string results; -}; - -//------------------------------------------------------------------------- - -// this class encapsulates a response from the thread -class GameResultsResponse -{ -public: - std::string hostname; - UnsignedShort port; - Bool sentOk; -}; - -//------------------------------------------------------------------------- - -// this is the actual message queue used to pass messages between threads -class GameResultsInterface : public SubsystemInterface -{ -public: - virtual ~GameResultsInterface() {} - virtual void startThreads( void ) = 0; - virtual void endThreads( void ) = 0; - virtual Bool areThreadsRunning( void ) = 0; - - virtual void addRequest( const GameResultsRequest& req ) = 0; - virtual Bool getRequest( GameResultsRequest& resp ) = 0; - - virtual void addResponse( const GameResultsResponse& resp ) = 0; - virtual Bool getResponse( GameResultsResponse& resp ) = 0; - - static GameResultsInterface* createNewGameResultsInterface( void ); - - virtual Bool areGameResultsBeingSent( void ) = 0; -}; - -extern GameResultsInterface *TheGameResultsQueue; - - -#endif // __GAMERESULTSTHREAD_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/LadderDefs.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/LadderDefs.h deleted file mode 100644 index 25d8098c2ed..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/LadderDefs.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: LadderDefs.h ////////////////////////////////////////////////////// -// Generals ladder definitions -// Author: Matthew D. Campbell, August 2002 - -#pragma once - -#ifndef __LADDERDEFS_H__ -#define __LADDERDEFS_H__ - -#include "Common/UnicodeString.h" -#include "Common/AsciiString.h" -#include "Common/STLTypedefs.h" - -class GameWindow; - -class LadderInfo -{ -public: - LadderInfo(); - UnicodeString name; - UnicodeString description; - UnicodeString location; - Int playersPerTeam; - Int minWins; - Int maxWins; - Bool randomMaps; - Bool randomFactions; - Bool validQM; - Bool validCustom; - std::list validMaps; - std::list validFactions; - AsciiString cryptedPassword; - AsciiString address; - UnsignedShort port; - AsciiString homepageURL; - Bool submitReplay; // with game results - Int index; -}; - -typedef std::list LadderInfoList; - -class LadderList -{ -public: - LadderList(); - ~LadderList(); - - const LadderInfo* findLadder( const AsciiString& addr, UnsignedShort port ); - const LadderInfo* findLadderByIndex( Int index ); // doesn't look in local ladders - const LadderInfoList* getLocalLadders( void ); - const LadderInfoList* getSpecialLadders( void ); - const LadderInfoList* getStandardLadders( void ); - -private: - void loadLocalLadders( void ); - void checkLadder( AsciiString fname, Int index ); - LadderInfoList m_localLadders; - LadderInfoList m_specialLadders; - LadderInfoList m_standardLadders; -}; - -extern LadderList *TheLadderList; - -#endif // __LADDERDEFS_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/LobbyUtils.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/LobbyUtils.h deleted file mode 100644 index 3cdd85cc628..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/LobbyUtils.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: LobbyUtils.h ////////////////////////////////////////////////////// -// Generals lobby utils -// Author: Matthew D. Campbell, Sept 2002 - -#pragma once - -#ifndef __LOBBYUTILS_H__ -#define __LOBBYUTILS_H__ - -class GameWindow; - -GameWindow *GetGameListBox( void ); -GameWindow *GetGameInfoListBox( void ); -NameKeyType GetGameListBoxID( void ); -NameKeyType GetGameInfoListBoxID( void ); -void GrabWindowInfo( void ); -void ReleaseWindowInfo( void ); -void RefreshGameInfoListBox( GameWindow *mainWin, GameWindow *win ); -void RefreshGameListBoxes( void ); -void ToggleGameListType( void ); - -void playerTemplateComboBoxTooltip(GameWindow *wndComboBox, WinInstanceData *instData, UnsignedInt mouse); -void playerTemplateListBoxTooltip(GameWindow *wndListBox, WinInstanceData *instData, UnsignedInt mouse); - -enum GameSortType -{ - GAMESORT_ALPHA_ASCENDING = 0, - GAMESORT_ALPHA_DESCENDING, - GAMESORT_PING_ASCENDING, - GAMESORT_PING_DESCENDING, - GAMESORT_MAX, -}; - -Bool HandleSortButton( NameKeyType sortButton ); -void PopulateLobbyPlayerListbox(void); - -#endif // __LOBBYUTILS_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/MainMenuUtils.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/MainMenuUtils.h deleted file mode 100644 index a0a8aff3dab..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/MainMenuUtils.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: MainMenuUtils.h ////////////////////////////////////////////////////// -// Author: Matthew D. Campbell, Sept 2002 -// Description: GameSpy version check, patch download, etc utils -/////////////////////////////////////////////////////////////////////////////// - -#pragma once - -#ifndef __MAINMENUUTILS_H__ -#define __MAINMENUUTILS_H__ - -void HTTPThinkWrapper( void ); -void StopAsyncDNSCheck( void ); -void StartPatchCheck( void ); -void CancelPatchCheckCallback( void ); -void StartDownloadingPatches( void ); -void HandleCanceledDownload( Bool resetDropDown = TRUE ); - -void CheckOverallStats( void ); -void HandleOverallStats( const char* szHTTPStats, unsigned len ); - -void CheckNumPlayersOnline( void ); -void HandleNumPlayersOnline( Int numPlayersOnline ); - -#endif // __MAINMENUUTILS_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefs.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefs.h deleted file mode 100644 index a8a5151293d..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefs.h +++ /dev/null @@ -1,303 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PeerDefs.h ////////////////////////////////////////////////////// -// Generals GameSpy Peer (chat) definitions -// Author: Matthew D. Campbell, June 2002 - -#pragma once - -#ifndef __PEERDEFS_H__ -#define __PEERDEFS_H__ - -#include "GameSpy/Peer/Peer.h" -#include "GameSpy/GP/GP.h" - -#include "GameClient/Color.h" -#include "Common/STLTypedefs.h" -#include "GameNetwork/GameSpy/StagingRoomGameInfo.h" - -class GameWindow; -class PSPlayerStats; - -typedef std::set IgnoreList; -typedef std::map SavedIgnoreMap; - -enum RCItemType -{ - ITEM_BUDDY, - ITEM_REQUEST, - ITEM_NONBUDDY, - ITEM_NONE, -}; - -class GameSpyRCMenuData -{ -public: - AsciiString m_nick; - GPProfile m_id; - RCItemType m_itemType; -}; - -class BuddyInfo -{ -public: - GPProfile m_id; - AsciiString m_name; - AsciiString m_email; - AsciiString m_countryCode; - GPEnum m_status; - UnicodeString m_statusString; - UnicodeString m_locationString; -}; -typedef std::map BuddyInfoMap; - -class BuddyMessage -{ -public: - UnsignedInt m_timestamp; - GPProfile m_senderID; - AsciiString m_senderNick; - GPProfile m_recipientID; - AsciiString m_recipientNick; - UnicodeString m_message; -}; -typedef std::list BuddyMessageList; - -class GameSpyGroupRoom -{ -public: - GameSpyGroupRoom() { m_name = AsciiString::TheEmptyString; m_translatedName = UnicodeString::TheEmptyString; m_groupID = m_numWaiting = m_maxWaiting = m_numGames = m_numPlaying = 0; } - AsciiString m_name; - UnicodeString m_translatedName; - Int m_groupID; - Int m_numWaiting; - Int m_maxWaiting; - Int m_numGames; - Int m_numPlaying; -}; -typedef std::map GroupRoomMap; - -class Transport; -class NAT; - -typedef std::map StagingRoomMap; - -class PlayerInfo -{ -public: - PlayerInfo() { m_name = m_locale = AsciiString::TheEmptyString; m_wins = m_losses = m_rankPoints = m_side = m_preorder = m_profileID = m_flags = 0; } - AsciiString m_name; - AsciiString m_locale; - Int m_wins; - Int m_losses; - Int m_profileID; - Int m_flags; - Int m_rankPoints; - Int m_side; - Int m_preorder; - Bool isIgnored( void ); -}; -struct AsciiComparator -{ - bool operator()(AsciiString s1, AsciiString s2) const; -}; - - -typedef std::map PlayerInfoMap; - -enum GameSpyColors { - GSCOLOR_DEFAULT = 0, - GSCOLOR_CURRENTROOM, - GSCOLOR_ROOM, - GSCOLOR_GAME, - GSCOLOR_GAME_FULL, - GSCOLOR_GAME_CRCMISMATCH, - GSCOLOR_PLAYER_NORMAL, - GSCOLOR_PLAYER_OWNER, - GSCOLOR_PLAYER_BUDDY, - GSCOLOR_PLAYER_SELF, - GSCOLOR_PLAYER_IGNORED, - GSCOLOR_CHAT_NORMAL, - GSCOLOR_CHAT_EMOTE, - GSCOLOR_CHAT_OWNER, - GSCOLOR_CHAT_OWNER_EMOTE, - GSCOLOR_CHAT_PRIVATE, - GSCOLOR_CHAT_PRIVATE_EMOTE, - GSCOLOR_CHAT_PRIVATE_OWNER, - GSCOLOR_CHAT_PRIVATE_OWNER_EMOTE, - GSCOLOR_CHAT_BUDDY, - GSCOLOR_CHAT_SELF, - GSCOLOR_ACCEPT_TRUE, - GSCOLOR_ACCEPT_FALSE, - GSCOLOR_MAP_SELECTED, - GSCOLOR_MAP_UNSELECTED, - GSCOLOR_MOTD, - GSCOLOR_MOTD_HEADING, - GSCOLOR_MAX -}; - -extern Color GameSpyColor[GSCOLOR_MAX]; - -enum GameSpyBuddyStatus { - BUDDY_OFFLINE, - BUDDY_ONLINE, - BUDDY_LOBBY, - BUDDY_STAGING, - BUDDY_LOADING, - BUDDY_PLAYING, - BUDDY_MATCHING, - BUDDY_MAX -}; - -// --------------------------------------------------- -// this class holds info used in the main thread -class GameSpyInfoInterface -{ -public: - virtual ~GameSpyInfoInterface() {}; - virtual void reset( void ) {}; - virtual void clearGroupRoomList( void ) = 0; - virtual GroupRoomMap* getGroupRoomList( void ) = 0; - virtual void addGroupRoom( GameSpyGroupRoom room ) = 0; - virtual Bool gotGroupRoomList( void ) = 0; - virtual void joinGroupRoom( Int groupID ) = 0; - virtual void leaveGroupRoom( void ) = 0; - virtual void joinBestGroupRoom( void ) = 0; - virtual void setCurrentGroupRoom( Int groupID ) = 0; - virtual Int getCurrentGroupRoom( void ) = 0; - virtual void updatePlayerInfo( PlayerInfo pi, AsciiString oldNick = AsciiString::TheEmptyString ) = 0; - virtual void playerLeftGroupRoom( AsciiString nick ) = 0; - virtual PlayerInfoMap* getPlayerInfoMap( void ) = 0; - - virtual BuddyInfoMap* getBuddyMap( void ) = 0; - virtual BuddyInfoMap* getBuddyRequestMap( void ) = 0; - virtual BuddyMessageList* getBuddyMessages( void ) = 0; - virtual Bool isBuddy( Int id ) = 0; - - virtual void setLocalName( AsciiString name ) = 0; - virtual AsciiString getLocalName( void ) = 0; - virtual void setLocalProfileID( Int profileID ) = 0; - virtual Int getLocalProfileID( void ) = 0; - virtual AsciiString getLocalEmail( void ) = 0; - virtual void setLocalEmail( AsciiString email ) = 0; - virtual AsciiString getLocalPassword( void ) = 0; - virtual void setLocalPassword( AsciiString passwd ) = 0; - virtual void setLocalBaseName( AsciiString name ) = 0; - virtual AsciiString getLocalBaseName( void ) = 0; - - virtual void setCachedLocalPlayerStats( PSPlayerStats stats ) = 0; - virtual PSPlayerStats getCachedLocalPlayerStats( void ) = 0; - - virtual void clearStagingRoomList( void ) = 0; - virtual StagingRoomMap* getStagingRoomList( void ) = 0; - virtual GameSpyStagingRoom* findStagingRoomByID( Int id ) = 0; - virtual void addStagingRoom( GameSpyStagingRoom room ) = 0; - virtual void updateStagingRoom( GameSpyStagingRoom room ) = 0; - virtual void removeStagingRoom( GameSpyStagingRoom room ) = 0; - virtual Bool hasStagingRoomListChanged( void ) = 0; - virtual void leaveStagingRoom( void ) = 0; - virtual void markAsStagingRoomHost( void ) = 0; - virtual void markAsStagingRoomJoiner( Int game ) = 0; - virtual void sawFullGameList( void ) = 0; - - virtual Bool amIHost( void ) = 0; - virtual GameSpyStagingRoom* getCurrentStagingRoom( void ) = 0; - virtual void setGameOptions( void ) = 0; - virtual Int getCurrentStagingRoomID( void ) = 0; - - virtual void setDisallowAsianText( Bool val ) = 0; - virtual void setDisallowNonAsianText( Bool val ) = 0; - virtual Bool getDisallowAsianText( void ) = 0; - virtual Bool getDisallowNonAsianText(void ) = 0; - - // chat - virtual void registerTextWindow( GameWindow *win ) = 0; - virtual void unregisterTextWindow( GameWindow *win ) = 0; - virtual Int addText( UnicodeString message, Color c, GameWindow *win ) = 0; - virtual void addChat( PlayerInfo p, UnicodeString msg, Bool isPublic, Bool isAction, GameWindow *win ) = 0; - virtual void addChat( AsciiString nick, Int profileID, UnicodeString msg, Bool isPublic, Bool isAction, GameWindow *win ) = 0; - virtual Bool sendChat( UnicodeString message, Bool isAction, GameWindow *playerListbox ) = 0; - - virtual void setMOTD( const AsciiString& motd ) = 0; - virtual const AsciiString& getMOTD( void ) = 0; - - virtual void setConfig( const AsciiString& config ) = 0; - virtual const AsciiString& getConfig( void ) = 0; - - virtual void setPingString( const AsciiString& ping ) = 0; - virtual const AsciiString& getPingString( void ) = 0; - virtual Int getPingValue( const AsciiString& otherPing ) = 0; - - static GameSpyInfoInterface* createNewGameSpyInfoInterface( void ); - - virtual void addToSavedIgnoreList( Int profileID, AsciiString nick ) = 0; - virtual void removeFromSavedIgnoreList( Int profileID ) = 0; - virtual Bool isSavedIgnored( Int profileID ) = 0; - virtual SavedIgnoreMap returnSavedIgnoreList( void ) = 0; - virtual void loadSavedIgnoreList( void ) = 0; - - virtual IgnoreList returnIgnoreList( void ) = 0; - virtual void addToIgnoreList( AsciiString nick ) = 0; - virtual void removeFromIgnoreList( AsciiString nick ) = 0; - virtual Bool isIgnored( AsciiString nick ) = 0; - - virtual void setLocalIPs(UnsignedInt internalIP, UnsignedInt externalIP) = 0; - virtual UnsignedInt getInternalIP(void) = 0; - virtual UnsignedInt getExternalIP(void) = 0; - - virtual Bool isDisconnectedAfterGameStart(Int *reason) const = 0; - virtual void markAsDisconnectedAfterGameStart(Int reason) = 0; - - virtual Bool didPlayerPreorder( Int profileID ) const = 0; - virtual void markPlayerAsPreorder( Int profileID ) = 0; - - virtual void setMaxMessagesPerUpdate( Int num ) = 0; - virtual Int getMaxMessagesPerUpdate( void ) = 0; - - virtual Int getAdditionalDisconnects( void ) = 0; - virtual void clearAdditionalDisconnects( void ) = 0; - virtual void readAdditionalDisconnects( void ) = 0; - virtual void updateAdditionalGameSpyDisconnections(Int count) = 0; -}; - -extern GameSpyInfoInterface *TheGameSpyInfo; - -void WOLDisplayGameOptions( void ); -void WOLDisplaySlotList( void ); -Bool GetLocalChatConnectionAddress(AsciiString serverName, UnsignedShort serverPort, UnsignedInt& localIP); -void SetLobbyAttemptHostJoin(Bool start); -void SendStatsToOtherPlayers(const GameInfo *game); - -class PSPlayerStats; -void GetAdditionalDisconnectsFromUserFile(PSPlayerStats *stats); -extern Int GetAdditionalDisconnectsFromUserFile(Int playerID); - -//------------------------------------------------------------------------- -// These functions set up the globals and threads neccessary for our GameSpy impl. - -void SetUpGameSpy( const char *motdBuffer, const char *configBuffer ); -void TearDownGameSpy( void ); - -#endif // __PEERDEFS_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefsImplementation.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefsImplementation.h deleted file mode 100644 index 30c7fcb3b06..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefsImplementation.h +++ /dev/null @@ -1,182 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PeerDefsImplementation.h ////////////////////////////////////////////////////// -// Generals GameSpy Peer (chat) implementation definitions -// Author: Matthew D. Campbell, Sept 2002 - -#pragma once - -#ifndef __PEERDEFSIMPLEMENTATION_H__ -#define __PEERDEFSIMPLEMENTATION_H__ - -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" - - -class GameSpyInfo : public GameSpyInfoInterface -{ -public: - GameSpyInfo(); - virtual ~GameSpyInfo(); - virtual void reset( void ); - virtual void clearGroupRoomList( void ) { m_groupRooms.clear(); m_gotGroupRoomList = false; } - virtual GroupRoomMap* getGroupRoomList( void ) { return &m_groupRooms; } - virtual void addGroupRoom( GameSpyGroupRoom room ); - virtual Bool gotGroupRoomList( void ) { return m_gotGroupRoomList; } - virtual void joinGroupRoom( Int groupID ); - virtual void leaveGroupRoom( void ); - virtual void joinBestGroupRoom( void ); - virtual void setCurrentGroupRoom( Int groupID ) { m_currentGroupRoomID = groupID; m_playerInfoMap.clear(); } - virtual Int getCurrentGroupRoom( void ) { return m_currentGroupRoomID; } - virtual void updatePlayerInfo( PlayerInfo pi, AsciiString oldNick = AsciiString::TheEmptyString ); - virtual void playerLeftGroupRoom( AsciiString nick ); - virtual PlayerInfoMap* getPlayerInfoMap( void ) { return &m_playerInfoMap; } - - virtual void setLocalName( AsciiString name ) { m_localName = name; } - virtual AsciiString getLocalName( void ) { return m_localName; } - virtual void setLocalProfileID( Int profileID ) { m_localProfileID = profileID; } - virtual Int getLocalProfileID( void ) { return m_localProfileID; } - virtual AsciiString getLocalEmail( void ) { return m_localEmail; } - virtual void setLocalEmail( AsciiString email ) { m_localEmail = email; } - virtual AsciiString getLocalPassword( void ){ return m_localPasswd; } - virtual void setLocalPassword( AsciiString passwd ) { m_localPasswd = passwd; } - virtual void setLocalBaseName( AsciiString name ) { m_localBaseName = name; } - virtual AsciiString getLocalBaseName( void ){ return m_localBaseName; } - virtual void setCachedLocalPlayerStats( PSPlayerStats stats ) {m_cachedLocalPlayerStats = stats; } - virtual PSPlayerStats getCachedLocalPlayerStats( void ){ return m_cachedLocalPlayerStats; } - - virtual BuddyInfoMap* getBuddyMap( void ) { return &m_buddyMap; } - virtual BuddyInfoMap* getBuddyRequestMap( void ) { return &m_buddyRequestMap; } - virtual BuddyMessageList* getBuddyMessages( void ) { return &m_buddyMessages; } - virtual Bool isBuddy( Int id ); - - virtual void clearStagingRoomList( void ); - virtual StagingRoomMap* getStagingRoomList( void ) { return &m_stagingRooms; } - virtual GameSpyStagingRoom* findStagingRoomByID( Int id ); - virtual void addStagingRoom( GameSpyStagingRoom room ); - virtual void updateStagingRoom( GameSpyStagingRoom room ); - virtual void removeStagingRoom( GameSpyStagingRoom room ); - virtual Bool hasStagingRoomListChanged( void ); - virtual void leaveStagingRoom( void ); - virtual void markAsStagingRoomHost( void ); - virtual void markAsStagingRoomJoiner( Int game ); - virtual Int getCurrentStagingRoomID( void ) { return m_localStagingRoomID; } - - virtual void sawFullGameList( void ) { m_sawFullGameList = TRUE; } - - virtual void setDisallowAsianText( Bool val ); - virtual void setDisallowNonAsianText( Bool val ); - virtual Bool getDisallowAsianText( void ); - virtual Bool getDisallowNonAsianText(void ); - // chat - virtual void registerTextWindow( GameWindow *win ); - virtual void unregisterTextWindow( GameWindow *win ); - virtual Int addText( UnicodeString message, Color c, GameWindow *win ); - virtual void addChat( PlayerInfo p, UnicodeString msg, Bool isPublic, Bool isAction, GameWindow *win ); - virtual void addChat( AsciiString nick, Int profileID, UnicodeString msg, Bool isPublic, Bool isAction, GameWindow *win ); - virtual Bool sendChat( UnicodeString message, Bool isAction, GameWindow *playerListbox ); - - virtual void setMOTD( const AsciiString& motd ); - virtual const AsciiString& getMOTD( void ); - virtual void setConfig( const AsciiString& config ); - virtual const AsciiString& getConfig( void ); - - virtual void setPingString( const AsciiString& ping ) { m_pingString = ping; } - virtual const AsciiString& getPingString( void ) { return m_pingString; } - virtual Int getPingValue( const AsciiString& otherPing ); - - virtual Bool amIHost( void ); - virtual GameSpyStagingRoom* getCurrentStagingRoom( void ); - virtual void setGameOptions( void ); - - virtual void addToIgnoreList( AsciiString nick ); - virtual void removeFromIgnoreList( AsciiString nick ); - virtual Bool isIgnored( AsciiString nick ); - virtual IgnoreList returnIgnoreList( void ); - - virtual void loadSavedIgnoreList( void ); - virtual SavedIgnoreMap returnSavedIgnoreList( void ); - virtual void addToSavedIgnoreList( Int profileID, AsciiString nick); - virtual void removeFromSavedIgnoreList( Int profileID ); - virtual Bool isSavedIgnored( Int profileID ); - virtual void setLocalIPs(UnsignedInt internalIP, UnsignedInt externalIP); - virtual UnsignedInt getInternalIP(void) { return m_internalIP; } - virtual UnsignedInt getExternalIP(void) { return m_externalIP; } - - virtual Bool isDisconnectedAfterGameStart(Int *reason) const { if (reason) *reason = m_disconReason; return m_isDisconAfterGameStart; } - virtual void markAsDisconnectedAfterGameStart(Int reason) { m_isDisconAfterGameStart = TRUE; m_disconReason = reason; } - - virtual Bool didPlayerPreorder( Int profileID ) const; - virtual void markPlayerAsPreorder( Int profileID ); - - virtual void setMaxMessagesPerUpdate( Int num ); - virtual Int getMaxMessagesPerUpdate( void ); - - virtual Int getAdditionalDisconnects( void ); - virtual void clearAdditionalDisconnects( void ); - virtual void readAdditionalDisconnects( void ); - virtual void updateAdditionalGameSpyDisconnections(Int count); -private: - Bool m_sawFullGameList; - Bool m_isDisconAfterGameStart; - Int m_disconReason; - AsciiString m_rawMotd; - AsciiString m_rawConfig; - AsciiString m_pingString; - GroupRoomMap m_groupRooms; - StagingRoomMap m_stagingRooms; - Bool m_stagingRoomsDirty; - BuddyInfoMap m_buddyMap; - BuddyInfoMap m_buddyRequestMap; - PlayerInfoMap m_playerInfoMap; - BuddyMessageList m_buddyMessages; - Int m_currentGroupRoomID; - Bool m_gotGroupRoomList; - AsciiString m_localName; - Int m_localProfileID; - AsciiString m_localPasswd; - AsciiString m_localEmail; - AsciiString m_localBaseName; - PSPlayerStats m_cachedLocalPlayerStats; - Bool m_disallowAsainText; - Bool m_disallowNonAsianText; - UnsignedInt m_internalIP, m_externalIP; - Int m_maxMessagesPerUpdate; - - Int m_joinedStagingRoom; // if we join a staging room, this holds its ID (0 otherwise) - Bool m_isHosting; // if we host, this is true, and - GameSpyStagingRoom m_localStagingRoom; // this holds the GameInfo for it. - Int m_localStagingRoomID; - - IgnoreList m_ignoreList; - SavedIgnoreMap m_savedIgnoreMap; - - std::set m_textWindows; - - std::set m_preorderPlayers; - Int m_additionalDisconnects; -}; - -#endif // __PEERDEFS_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PeerThread.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PeerThread.h deleted file mode 100644 index 0b00d8375fd..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PeerThread.h +++ /dev/null @@ -1,392 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PeerThread.h ////////////////////////////////////////////////////// -// Generals GameSpy Peer-to-peer chat thread class interface -// Author: Matthew D. Campbell, June 2002 - -#pragma once - -#ifndef __PEERTHREAD_H__ -#define __PEERTHREAD_H__ - -#include "GameSpy/Peer/Peer.h" -#include "GameNetwork/NetworkDefs.h" - -enum SerialAuthResult -{ - SERIAL_NONEXISTENT, - SERIAL_AUTHFAILED, - SERIAL_BANNED, - SERIAL_OK -}; - -// this class encapsulates a request for the peer thread -class PeerRequest -{ -public: - enum - { - PEERREQUEST_LOGIN, // attempt to login - PEERREQUEST_LOGOUT, // log out if connected - PEERREQUEST_MESSAGEPLAYER, - PEERREQUEST_MESSAGEROOM, - PEERREQUEST_JOINGROUPROOM, - PEERREQUEST_LEAVEGROUPROOM, - PEERREQUEST_STARTGAMELIST, - PEERREQUEST_STOPGAMELIST, - PEERREQUEST_CREATESTAGINGROOM, - PEERREQUEST_SETGAMEOPTIONS, - PEERREQUEST_JOINSTAGINGROOM, - PEERREQUEST_LEAVESTAGINGROOM, - PEERREQUEST_UTMPLAYER, - PEERREQUEST_UTMROOM, - PEERREQUEST_STARTGAME, - PEERREQUEST_STARTQUICKMATCH, - PEERREQUEST_WIDENQUICKMATCHSEARCH, - PEERREQUEST_STOPQUICKMATCH, - PEERREQUEST_PUSHSTATS, - PEERREQUEST_GETEXTENDEDSTAGINGROOMINFO, - PEERREQUEST_MAX - } peerRequestType; - - std::string nick; // only used by login, but must be outside the union b/c of copy constructor - std::wstring text; // can't be in a union - std::string password; - std::string email; - std::string id; - - // gameopts - std::string options; // full string for UTMs - std::string ladderIP; - std::string hostPingStr; - std::string gameOptsMapName; - std::string gameOptsPlayerNames[MAX_SLOTS]; - - std::vector qmMaps; - - union - { - struct - { - Int profileID; - } login; - - struct - { - Int id; - } groupRoom; - - struct - { - Bool restrictGameList; - } gameList; - - struct - { - Bool isAction; - } message; - - struct - { - Int id; - } stagingRoom; - - struct - { - UnsignedInt exeCRC; - UnsignedInt iniCRC; - UnsignedInt gameVersion; - Bool allowObservers; - Bool useStats; - UnsignedShort ladPort; - UnsignedInt ladPassCRC; - Bool restrictGameList; - } stagingRoomCreation; - - struct - { - Int wins[MAX_SLOTS]; - Int losses[MAX_SLOTS]; - Int profileID[MAX_SLOTS]; - Int faction[MAX_SLOTS]; - Int color[MAX_SLOTS]; - Int numPlayers; - Int maxPlayers; - Int numObservers; - } gameOptions; - - struct - { - Bool isStagingRoom; - } UTM; - - struct - { - Int minPointPercentage, maxPointPercentage, points; - Int widenTime; - Int ladderID; - UnsignedInt ladderPassCRC; - Int maxPing; - Int maxDiscons, discons; - char pings[17]; // 8 servers (0-ff), 1 NULL - Int numPlayers; - Int botID; - Int roomID; - Int side; - Int color; - Int NAT; - UnsignedInt exeCRC; - UnsignedInt iniCRC; - } QM; - - struct - { - Int locale; - Int wins; - Int losses; - Int rankPoints; - Int side; - Bool preorder; - } statsToPush; - - }; -}; - -//------------------------------------------------------------------------- - -enum DisconnectReason -{ - DISCONNECT_NICKTAKEN = 1, - DISCONNECT_BADNICK, - DISCONNECT_LOSTCON, - DISCONNECT_COULDNOTCONNECT, - DISCONNECT_GP_LOGIN_TIMEOUT, - DISCONNECT_GP_LOGIN_BAD_NICK, - DISCONNECT_GP_LOGIN_BAD_EMAIL, - DISCONNECT_GP_LOGIN_BAD_PASSWORD, - DISCONNECT_GP_LOGIN_BAD_PROFILE, - DISCONNECT_GP_LOGIN_PROFILE_DELETED, - DISCONNECT_GP_LOGIN_CONNECTION_FAILED, - DISCONNECT_GP_LOGIN_SERVER_AUTH_FAILED, - DISCONNECT_SERIAL_INVALID, - DISCONNECT_SERIAL_NOT_PRESENT, - DISCONNECT_SERIAL_BANNED, - DISCONNECT_GP_NEWUSER_BAD_NICK, - DISCONNECT_GP_NEWUSER_BAD_PASSWORD, - DISCONNECT_GP_NEWPROFILE_BAD_NICK, - DISCONNECT_GP_NEWPROFILE_BAD_OLD_NICK, - DISCONNECT_MAX, -}; - -enum QMStatus -{ - QM_IDLE, - QM_JOININGQMCHANNEL, - QM_LOOKINGFORBOT, - QM_SENTINFO, - QM_WORKING, - QM_POOLSIZE, - QM_WIDENINGSEARCH, - QM_MATCHED, - QM_INCHANNEL, - QM_NEGOTIATINGFIREWALLS, - QM_STARTINGGAME, - QM_COULDNOTFINDBOT, - QM_COULDNOTFINDCHANNEL, - QM_COULDNOTNEGOTIATEFIREWALLS, - QM_STOPPED, -}; - -// this class encapsulates an action the peer thread wants from the UI -class PeerResponse -{ -public: - enum - { - PEERRESPONSE_LOGIN, - PEERRESPONSE_DISCONNECT, - PEERRESPONSE_MESSAGE, - PEERRESPONSE_GROUPROOM, - PEERRESPONSE_STAGINGROOM, - PEERRESPONSE_STAGINGROOMLISTCOMPLETE, - PEERRESPONSE_STAGINGROOMPLAYERINFO, - PEERRESPONSE_JOINGROUPROOM, - PEERRESPONSE_CREATESTAGINGROOM, - PEERRESPONSE_JOINSTAGINGROOM, - PEERRESPONSE_PLAYERJOIN, - PEERRESPONSE_PLAYERLEFT, - PEERRESPONSE_PLAYERCHANGEDNICK, - PEERRESPONSE_PLAYERINFO, - PEERRESPONSE_PLAYERCHANGEDFLAGS, - PEERRESPONSE_ROOMUTM, - PEERRESPONSE_PLAYERUTM, - PEERRESPONSE_QUICKMATCHSTATUS, - PEERRESPONSE_GAMESTART, - PEERRESPONSE_FAILEDTOHOST, - PEERRESPONSE_MAX - } peerResponseType; - - std::string groupRoomName; // can't be in union - - std::string nick; // can't be in a union - std::string oldNick; // can't be in a union - std::wstring text; // can't be in a union - std::string locale; // can't be in a union - - std::string stagingServerGameOptions; // full string from UTMs - - // game opts sent with PEERRESPONSE_STAGINGROOM - std::wstring stagingServerName; - std::string stagingServerPingString; - std::string stagingServerLadderIP; - std::string stagingRoomMapName; - - // game opts sent with PEERRESPONSE_STAGINGROOMPLAYERINFO - std::string stagingRoomPlayerNames[MAX_SLOTS]; - - std::string command; - std::string commandOptions; - - union - { - struct - { - DisconnectReason reason; - } discon; - - struct - { - Int id; - Int numWaiting; - Int maxWaiting; - Int numGames; - Int numPlaying; - } groupRoom; - - struct - { - Int id; - Bool ok; - } joinGroupRoom; - - struct - { - Int result; - } createStagingRoom; - - struct - { - Int id; - Bool ok; - Bool isHostPresent; - Int result; // for failures - } joinStagingRoom; - - struct - { - Bool isPrivate; - Bool isAction; - Int profileID; - } message; - - struct - { - Int profileID; - Int wins; - Int losses; - RoomType roomType; - Int flags; - UnsignedInt IP; - Int rankPoints; - Int side; - Int preorder; - UnsignedInt internalIP; // for us, on connection - UnsignedInt externalIP; // for us, on connection - } player; - - struct - { - Int id; - Int action; - Bool isStaging; - Bool requiresPassword; - Bool allowObservers; - Bool useStats; - UnsignedInt version; - UnsignedInt exeCRC; - UnsignedInt iniCRC; - UnsignedShort ladderPort; - Int wins[MAX_SLOTS]; - Int losses[MAX_SLOTS]; - Int profileID[MAX_SLOTS]; - Int faction[MAX_SLOTS]; - Int color[MAX_SLOTS]; - Int numPlayers; - Int numObservers; - Int maxPlayers; - Int percentComplete; - } stagingRoom; - - struct - { - QMStatus status; - Int poolSize; - Int mapIdx; // when matched - Int seed; // when matched - UnsignedInt IP[MAX_SLOTS]; // when matched - Int side[MAX_SLOTS]; // when matched - Int color[MAX_SLOTS]; // when matched - Int nat[MAX_SLOTS]; - } qmStatus; - }; -}; - -//------------------------------------------------------------------------- - -// this is the actual message queue used to pass messages between threads -class GameSpyPeerMessageQueueInterface -{ -public: - virtual ~GameSpyPeerMessageQueueInterface() {} - virtual void startThread( void ) = 0; - virtual void endThread( void ) = 0; - virtual Bool isThreadRunning( void ) = 0; - virtual Bool isConnected( void ) = 0; - virtual Bool isConnecting( void ) = 0; - - virtual void addRequest( const PeerRequest& req ) = 0; - virtual Bool getRequest( PeerRequest& req ) = 0; - - virtual void addResponse( const PeerResponse& resp ) = 0; - virtual Bool getResponse( PeerResponse& resp ) = 0; - - virtual SerialAuthResult getSerialAuthResult( void ) = 0; - - static GameSpyPeerMessageQueueInterface* createNewMessageQueue( void ); -}; - -extern GameSpyPeerMessageQueueInterface *TheGameSpyPeerMessageQueue; - -#endif // __PEERTHREAD_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageDefs.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageDefs.h deleted file mode 100644 index a480f8a9750..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageDefs.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PersistentStorageDefs.h ////////////////////////////////////////////////////// -// Generals GameSpy Persistent Storage definitions -// Author: Matthew D. Campbell, July 2002 - -#pragma once - -#ifndef __PERSISTENTSTORAGEDEFS_H__ -#define __PERSISTENTSTORAGEDEFS_H__ - -enum LocaleType -{ - LOC_UNKNOWN = 0, - LOC_MIN = 1, - LOC_MAX = 37 -}; - -void HandlePersistentStorageResponses(void); -void UpdateLocalPlayerStats(void); - -void SetLookAtPlayer( Int id, AsciiString nick ); -void PopulatePlayerInfoWindows( AsciiString parentWindowName ); - -#endif // __PERSISTENTSTORAGEDEFS_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageThread.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageThread.h deleted file mode 100644 index 91c04dc0278..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageThread.h +++ /dev/null @@ -1,187 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PersistentStorageThread.h ////////////////////////////////////////////////////// -// Generals GameSpy Persistent Storage thread class interface -// Author: Matthew D. Campbell, July 2002 - -#pragma once - -#ifndef __PERSISTENTSTORAGETHREAD_H__ -#define __PERSISTENTSTORAGETHREAD_H__ - -#include "GameSpy/gstats/gpersist.h" - -#define MAX_BUDDY_CHAT_LEN 128 - -typedef std::map PerGeneralMap; -// this structure holds all info on a player that is stored online -class PSPlayerStats -{ -public: - PSPlayerStats( void ); - PSPlayerStats( const PSPlayerStats& other ); - void reset(void); - - Int id; - PerGeneralMap wins; - PerGeneralMap losses; - PerGeneralMap games; //first: playerTemplate #, second: #games played (see also gamesAsRandom) - PerGeneralMap duration; - PerGeneralMap unitsKilled; - PerGeneralMap unitsLost; - PerGeneralMap unitsBuilt; - PerGeneralMap buildingsKilled; - PerGeneralMap buildingsLost; - PerGeneralMap buildingsBuilt; - PerGeneralMap earnings; - PerGeneralMap techCaptured; - PerGeneralMap discons; - PerGeneralMap desyncs; - PerGeneralMap surrenders; - PerGeneralMap gamesOf2p; - PerGeneralMap gamesOf3p; - PerGeneralMap gamesOf4p; - PerGeneralMap gamesOf5p; - PerGeneralMap gamesOf6p; - PerGeneralMap gamesOf7p; - PerGeneralMap gamesOf8p; - PerGeneralMap customGames; - PerGeneralMap QMGames; - Int locale; - Int gamesAsRandom; - std::string options; - std::string systemSpec; - Real lastFPS; - Int lastGeneral; - Int gamesInRowWithLastGeneral; - Int challengeMedals; - Int battleHonors; - Int QMwinsInARow; - Int maxQMwinsInARow; - - Int winsInARow; - Int maxWinsInARow; - Int lossesInARow; - Int maxLossesInARow; - Int disconsInARow; - Int maxDisconsInARow; - Int desyncsInARow; - Int maxDesyncsInARow; - - Int builtParticleCannon; - Int builtNuke; - Int builtSCUD; - - Int lastLadderPort; - std::string lastLadderHost; - - void incorporate( const PSPlayerStats& other ); -}; - -// this class encapsulates a request for the thread -class PSRequest -{ -public: - PSRequest(); - enum - { - PSREQUEST_READPLAYERSTATS, // read stats for a player - PSREQUEST_UPDATEPLAYERSTATS, // update stats on the server - PSREQUEST_UPDATEPLAYERLOCALE, // update locale on the server - PSREQUEST_READCDKEYSTATS, // read stats for a cdkey - PSREQUEST_SENDGAMERESTOGAMESPY, // report game results to GameSpy - PSREQUEST_MAX - } requestType; - - // player stats for the *PLAYERSTATS - PSPlayerStats player; - - // cdkey for READCDKEYSTATS; - std::string cdkey; - - // our info for UPDATEPLAYERSTATS - std::string nick; - std::string password; - std::string email; - Bool addDiscon; - Bool addDesync; - Int lastHouse; - - // for GameRes - std::string results; -}; - -//------------------------------------------------------------------------- - -// this class encapsulates a response from the thread -class PSResponse -{ -public: - enum - { - PSRESPONSE_PLAYERSTATS, - PSRESPONSE_COULDNOTCONNECT, - PSRESPONSE_PREORDER, - PSRESPONSE_MAX - } responseType; - - // player stats for the *PLAYERSTATS - PSPlayerStats player; - - // preorder flag - Bool preorder; -}; - -//------------------------------------------------------------------------- - -// this is the actual message queue used to pass messages between threads -class GameSpyPSMessageQueueInterface -{ -public: - virtual ~GameSpyPSMessageQueueInterface() {} - virtual void startThread( void ) = 0; - virtual void endThread( void ) = 0; - virtual Bool isThreadRunning( void ) = 0; - - virtual void addRequest( const PSRequest& req ) = 0; - virtual Bool getRequest( PSRequest& req ) = 0; - - virtual void addResponse( const PSResponse& resp ) = 0; - virtual Bool getResponse( PSResponse& resp ) = 0; - - // called from the main thread - virtual void trackPlayerStats( PSPlayerStats stats ) = 0; - virtual PSPlayerStats findPlayerStatsByID( Int id ) = 0; - - static GameSpyPSMessageQueueInterface* createNewMessageQueue( void ); - - static std::string formatPlayerKVPairs( PSPlayerStats stats ); - static PSPlayerStats parsePlayerKVPairs( std::string kvPairs ); -}; - -extern GameSpyPSMessageQueueInterface *TheGameSpyPSMessageQueue; - - -#endif // __PERSISTENTSTORAGETHREAD_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PingThread.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PingThread.h deleted file mode 100644 index 4661de891bb..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PingThread.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PingThread.h ////////////////////////////////////////////////////// -// Generals ping thread class interface -// Author: Matthew D. Campbell, August 2002 -// Note: adapted from WOLAPI - -#pragma once - -#ifndef __PINGTHREAD_H__ -#define __PINGTHREAD_H__ - -// this class encapsulates a request for the thread -class PingRequest -{ -public: - std::string hostname; - Int repetitions; - Int timeout; -}; - -//------------------------------------------------------------------------- - -// this class encapsulates a response from the thread -class PingResponse -{ -public: - std::string hostname; - Int avgPing; - Int repetitions; -}; - -//------------------------------------------------------------------------- - -// this is the actual message queue used to pass messages between threads -class PingerInterface -{ -public: - virtual ~PingerInterface() {} - virtual void startThreads( void ) = 0; - virtual void endThreads( void ) = 0; - virtual Bool areThreadsRunning( void ) = 0; - - virtual void addRequest( const PingRequest& req ) = 0; - virtual Bool getRequest( PingRequest& resp ) = 0; - - virtual void addResponse( const PingResponse& resp ) = 0; - virtual Bool getResponse( PingResponse& resp ) = 0; - - static PingerInterface* createNewPingerInterface( void ); - - virtual Bool arePingsInProgress( void ) = 0; - virtual Int getPing( AsciiString hostname ) = 0; - virtual void clearPingMap( void ) = 0; - virtual AsciiString getPingString( Int timeout ) = 0; -}; - -extern PingerInterface *ThePinger; - - -#endif // __PINGTHREAD_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/StagingRoomGameInfo.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/StagingRoomGameInfo.h deleted file mode 100644 index e7cd2bd4e4b..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/StagingRoomGameInfo.h +++ /dev/null @@ -1,161 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: StagingRoomGameInfo.h ////////////////////////////////////////////////////// -// Generals GameSpy GameInfo -// Author: Matthew D. Campbell, Sept 2002 - -#pragma once - -#ifndef __STAGINGROOMGAMEINFO_H__ -#define __STAGINGROOMGAMEINFO_H__ - -#include "GameNetwork/GameInfo.h" -#include "GameNetwork/Transport.h" - -class GameSpyGameSlot : public GameSlot -{ -public: - GameSpyGameSlot(); - Int getProfileID( void ) const { return m_profileID; } - void setProfileID( Int id ) { m_profileID = id; } - AsciiString getLoginName( void ) const { return m_gameSpyLogin; } - void setLoginName( AsciiString name ) { m_gameSpyLogin = name; } - AsciiString getLocale( void ) const { return m_gameSpyLocale; } - void setLocale( AsciiString name ) { m_gameSpyLocale = name; } - Int getWins( void ) const { return m_wins; } - Int getLosses( void ) const { return m_losses; } - void setWins( Int wins ) { m_wins = wins; } - void setLosses( Int losses ) { m_losses = losses; } - - Int getSlotRankPoints( void ) const { return m_rankPoints; } - Int getFavoriteSide( void ) const { return m_favoriteSide; } - void setSlotRankPoints( Int val ) { m_rankPoints = val; } - void setFavoriteSide( Int val ) { m_favoriteSide = val; } - - void setPingString( AsciiString pingStr ); - inline AsciiString getPingString( void ) const { return m_pingStr; } - inline Int getPingAsInt( void ) const { return m_pingInt; } - -protected: - Int m_profileID; - AsciiString m_gameSpyLogin; - AsciiString m_gameSpyLocale; - - AsciiString m_pingStr; - Int m_pingInt; - Int m_wins, m_losses; - Int m_rankPoints, m_favoriteSide; -}; - -/** - * GameSpyStagingRoom class - maintains information about the GameSpy game and - * the contents of its slot list throughout the game. - */ -class GameSpyStagingRoom : public GameInfo -{ -private: - GameSpyGameSlot m_GameSpySlot[MAX_SLOTS]; ///< The GameSpy Games Slot List - UnicodeString m_gameName; - Int m_id; - Transport *m_transport; - AsciiString m_localName; - Bool m_requiresPassword; - Bool m_allowObservers; - UnsignedInt m_version; - UnsignedInt m_exeCRC; - UnsignedInt m_iniCRC; - Bool m_isQM; - - AsciiString m_ladderIP; - AsciiString m_pingStr; - Int m_pingInt; - UnsignedShort m_ladderPort; - - Int m_reportedNumPlayers; - Int m_reportedMaxPlayers; - Int m_reportedNumObservers; - -public: - GameSpyStagingRoom(); - virtual void reset( void ); - - void cleanUpSlotPointers(void); - inline void setID(Int id) { m_id = id; } - inline Int getID( void ) const { return m_id; } - - inline void setHasPassword(Bool val) { m_requiresPassword = val; } - inline Bool getHasPassword(void) const { return m_requiresPassword; } - inline void setAllowObservers(Bool val) { m_allowObservers = val; } - inline Bool getAllowObservers(void) const { return m_allowObservers; } - - inline void setVersion(UnsignedInt val) { m_version = val; } - inline UnsignedInt getVersion(void) const { return m_version; } - inline void setExeCRC(UnsignedInt val) { m_exeCRC = val; } - inline UnsignedInt getExeCRC(void) const { return m_exeCRC; } - inline void setIniCRC(UnsignedInt val) { m_iniCRC = val; } - inline UnsignedInt getIniCRC(void) const { return m_iniCRC; } - - inline void setReportedNumPlayers(Int val) { m_reportedNumPlayers = val; } - inline Int getReportedNumPlayers(void) const { return m_reportedNumPlayers; } - - inline void setReportedMaxPlayers(Int val) { m_reportedMaxPlayers = val; } - inline Int getReportedMaxPlayers(void) const { return m_reportedMaxPlayers; } - - inline void setReportedNumObservers(Int val) { m_reportedNumObservers = val; } - inline Int getReportedNumObservers(void) const { return m_reportedNumObservers; } - - inline void setLadderIP( AsciiString ladderIP ) { m_ladderIP = ladderIP; } - inline AsciiString getLadderIP( void ) const { return m_ladderIP; } - inline void setLadderPort( UnsignedShort ladderPort ) { m_ladderPort = ladderPort; } - inline UnsignedShort getLadderPort( void ) const { return m_ladderPort; } - void setPingString( AsciiString pingStr ); - inline AsciiString getPingString( void ) const { return m_pingStr; } - inline Int getPingAsInt( void ) const { return m_pingInt; } - - virtual Bool amIHost( void ) const; ///< Convenience function - is the local player the game host? - - GameSpyGameSlot *getGameSpySlot( Int index ); - - AsciiString generateGameSpyGameResultsPacket( void ); - AsciiString generateLadderGameResultsPacket( void ); - void markGameAsQM( void ) { m_isQM = TRUE; } - Bool isQMGame( void ) { return m_isQM; } - - virtual void init(void); - virtual void resetAccepted(void); ///< Reset the accepted flag on all players - - virtual void startGame(Int gameID); ///< Mark our game as started and record the game ID. - void launchGame( void ); ///< NAT negotiation has finished - really start - virtual Int getLocalSlotNum( void ) const; ///< Get the local slot number, or -1 if we're not present - - inline void setGameName( UnicodeString name ) { m_gameName = name; } - inline UnicodeString getGameName( void ) const { return m_gameName; } - - inline void setLocalName( AsciiString name ) { m_localName = name; } -}; - -extern GameSpyStagingRoom *TheGameSpyGame; - -#endif // __STAGINGROOMGAMEINFO_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/ThreadUtils.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/ThreadUtils.h deleted file mode 100644 index 7dd7c6fa3fc..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/ThreadUtils.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ThreadUtils.h ////////////////////////////////////////////////////// -// Generals GameSpy thread utils -// Author: Matthew D. Campbell, July 2002 - -#pragma once - -#ifndef __GAMESPY_THREADUTILS_H__ -#define __GAMESPY_THREADUTILS_H__ - -std::wstring MultiByteToWideCharSingleLine( const char *orig ); -std::string WideCharStringToMultiByte( const WideChar *orig ); - -#endif // __GAMESPY_THREADUTILS_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyChat.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyChat.h deleted file mode 100644 index 1d3bca8f550..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyChat.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameSpyChat.h ////////////////////////////////////////////////////// -// Generals GameSpy Chat -// Author: Matthew D. Campbell, February 2002 - -#pragma once - -#ifndef __GAMESPYCHAT_H__ -#define __GAMESPYCHAT_H__ - -#include "GameSpy/Peer/Peer.h" - -class GameWindow; -class WindowLayout; - -Bool GameSpySendChat(UnicodeString message, Bool isEmote, GameWindow *playerListbox = NULL); -void GameSpyAddText( UnicodeString message, GameSpyColors color = GSCOLOR_DEFAULT ); - -extern GameWindow *progressTextWindow; ///< Text box on the progress screen -extern GameWindow *quickmatchTextWindow; ///< Text box on the quickmatch screen -extern GameWindow *quickmatchTextWindow; ///< Text box on the quickmatch screen -extern GameWindow *listboxLobbyChat; ///< Chat box on the custom lobby screen -extern GameWindow *listboxLobbyPlayers; ///< Player box on the custom lobby screen -extern GameWindow *listboxLobbyGames; ///< Game box on the custom lobby screen -extern GameWindow *listboxLobbyChatChannels; ///< Chat channel box on the custom lobby screen -extern GameWindow *listboxGameSetupChat; ///< Chat box on the custom game setup screen -extern WindowLayout *WOLMapSelectLayout; ///< Map selection overlay - -void RoomMessageCallback(PEER peer, RoomType roomType, - const char * nick, const char * message, - MessageType messageType, void * param); ///< Called when a message arrives in a room. - -void PlayerMessageCallback(PEER peer, const char * nick, - const char * message, MessageType messageType, - void * param); ///< Called when a private message is received from another player. - -#endif // __GAMESPYCHAT_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyGP.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyGP.h deleted file mode 100644 index 79c4d825fd2..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyGP.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameSpyGP.h ////////////////////////////////////////////////////// -// Generals GameSpy GP (Buddy) -// Author: Matthew D. Campbell, March 2002 - -#pragma once - -#ifndef __GAMESPYGP_H__ -#define __GAMESPYGP_H__ - -#include "GameSpy/GP/GP.h" - -void GPRecvBuddyRequestCallback(GPConnection * connection, GPRecvBuddyRequestArg * arg, void * param); -void GPRecvBuddyMessageCallback(GPConnection * pconnection, GPRecvBuddyMessageArg * arg, void * param); -void GPRecvBuddyStatusCallback(GPConnection * connection, GPRecvBuddyStatusArg * arg, void * param); -void GPErrorCallback(GPConnection * pconnection, GPErrorArg * arg, void * param); -void GPConnectCallback(GPConnection * pconnection, GPConnectResponseArg * arg, void * param); -void GameSpyUpdateBuddyOverlay(void); - -extern GPConnection *TheGPConnection; - -Bool IsGameSpyBuddy(GPProfile id); - -#endif // __GAMESPYGP_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyGameInfo.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyGameInfo.h deleted file mode 100644 index 0652c08be0d..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyGameInfo.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameSpyGameInfo.h ////////////////////////////////////////////////////// -// Generals GameSpy game setup information -// Author: Matthew D. Campbell, February 2002 - -#pragma once - -#error this file is obsolete - -#ifndef __GAMESPYGAMEINFO_H__ -#define __GAMESPYGAMEINFO_H__ - -#include "GameSpy/Peer/Peer.h" - -#include "GameNetwork/GameInfo.h" - -class Transport; -class NAT; - -class GameSpyGameSlot : public GameSlot -{ -public: - GameSpyGameSlot(); - Int getProfileID( void ) { return m_profileID; } - void setProfileID( Int id ) { m_profileID = id; } - AsciiString getLoginName( void ) { return m_gameSpyLogin; } - void setLoginName( AsciiString name ) { m_gameSpyLogin = name; } - AsciiString getLocale( void ) { return m_gameSpyLocale; } - void setLocale( AsciiString name ) { m_gameSpyLocale = name; } -protected: - Int m_profileID; - AsciiString m_gameSpyLogin; - AsciiString m_gameSpyLocale; -}; - -/** - * GameSpyGameInfo class - maintains information about the GameSpy game and - * the contents of its slot list throughout the game. - */ -class GameSpyGameInfo : public GameInfo -{ -private: - GameSpyGameSlot m_GameSpySlot[MAX_SLOTS]; ///< The GameSpy Games Slot List - SBServer m_server; - Bool m_hasBeenQueried; - Transport *m_transport; - Bool m_isQM; - -public: - GameSpyGameInfo(); - - inline void setServer(SBServer server) { m_server = server; } - inline SBServer getServer( void ) { return m_server; } - - AsciiString generateGameResultsPacket( void ); - - virtual void init(void); - virtual void resetAccepted(void); ///< Reset the accepted flag on all players - - void markGameAsQM( void ) { m_isQM = TRUE; } - virtual void startGame(Int gameID); ///< Mark our game as started and record the game ID. - virtual Int getLocalSlotNum( void ) const; ///< Get the local slot number, or -1 if we're not present - - void gotGOACall( void ); ///< Mark the game info as having been queried -}; - -extern GameSpyGameInfo *TheGameSpyGame; - -void WOLDisplayGameOptions( void ); -void WOLDisplaySlotList( void ); -void GameSpyStartGame( void ); -void GameSpyLaunchGame( void ); -Bool GetLocalChatConnectionAddress(AsciiString serverName, UnsignedShort serverPort, UnsignedInt& localIP); - -#endif // __LANGAMEINFO_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyOverlay.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyOverlay.h deleted file mode 100644 index d41f96a57a8..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyOverlay.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GamespyOverlay.h ////////////////////////////////////////////////////// -// Generals GameSpy overlay screens -// Author: Matthew D. Campbell, March 2002 - -#pragma once - -#ifndef __GAMESPYOVERLAY_H__ -#define __GAMESPYOVERLAY_H__ - -#include "Common/NameKeyGenerator.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" - -void ClearGSMessageBoxes( void ); ///< Tear down any GS message boxes (e.g. in case we have a new one to put up) -void GSMessageBoxOk(UnicodeString titleString,UnicodeString bodyString, GameWinMsgBoxFunc okFunc = NULL); ///< Display a Message box with Ok button and track it -void GSMessageBoxOkCancel(UnicodeString title, UnicodeString message, GameWinMsgBoxFunc okFunc, GameWinMsgBoxFunc cancelFunc); ///< Display a Message box with Ok/Cancel buttons and track it -void GSMessageBoxYesNo(UnicodeString title, UnicodeString message, GameWinMsgBoxFunc yesFunc, GameWinMsgBoxFunc noFunc); ///< Display a Message box with Yes/No buttons and track it -void RaiseGSMessageBox( void ); ///< Bring GS message box to the foreground (if we transition screens while a message box is up) - -enum GSOverlayType -{ - GSOVERLAY_PLAYERINFO, - GSOVERLAY_MAPSELECT, - GSOVERLAY_BUDDY, - GSOVERLAY_PAGE, - GSOVERLAY_GAMEOPTIONS, - GSOVERLAY_GAMEPASSWORD, - GSOVERLAY_LADDERSELECT, - GSOVERLAY_LOCALESELECT, - GSOVERLAY_OPTIONS, - GSOVERLAY_MAX -}; - -void GameSpyOpenOverlay( GSOverlayType ); -void GameSpyCloseOverlay( GSOverlayType ); -void GameSpyCloseAllOverlays( void ); -Bool GameSpyIsOverlayOpen( GSOverlayType ); -void GameSpyToggleOverlay( GSOverlayType ); -void GameSpyUpdateOverlays( void ); -void ReOpenPlayerInfo( void ); -void CheckReOpenPlayerInfo(void ); -#endif // __GAMESPYOVERLAY_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyThread.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyThread.h deleted file mode 100644 index 11e8040027c..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyThread.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameSpyThread.h ////////////////////////////////////////////////////// -// Generals GameSpy thread class -// Author: Matthew D. Campbell, March 2002 - -#pragma once - -#ifndef __GAMESPYTHREAD_H__ -#define __GAMESPYTHREAD_H__ - -#include "mutex.h" -#include "thread.h" - -class GameSpyThreadClass : public ThreadClass -{ - -public: - GameSpyThreadClass::GameSpyThreadClass() : ThreadClass() { m_doLogin = false; m_readStats = false; m_updateWins = false; m_updateLosses = false; m_updateLocale = false; m_showLocaleSelect = false; m_nextShellScreen.clear(); } - void queueLogin(AsciiString nick, AsciiString pass, AsciiString email) { m_nick = nick; m_pass = pass; m_email = email; m_doLogin = true; } - void queueReadPersistentStatsFromServer( void ) { m_readStats = true; } - void queueUpdateLocale( AsciiString locale ) { m_locale = locale; m_updateLocale = true; } - void queueUpdateWins ( AsciiString wins ) { m_wins = wins; m_updateWins = true; } - void queueUpdateLosses( AsciiString losses ) { m_losses = losses; m_updateLosses = true; } - - void Thread_Function(); - - AsciiString getNextShellScreen( void ); - Bool showLocaleSelect( void ); - - void setNextShellScreen( AsciiString nextShellScreen ); - void setShowLocaleSelect( Bool val ); - -private: - AsciiString m_nick, m_pass, m_email; - Bool m_doLogin, m_readStats, m_updateWins, m_updateLosses, m_updateLocale; - AsciiString m_locale, m_wins, m_losses; - AsciiString m_nextShellScreen; - Bool m_showLocaleSelect; -}; - -extern GameSpyThreadClass *TheGameSpyThread; -extern MutexClass TheGameSpyMutex; - -#endif // __GAMESPYTHREAD_H__ diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/NAT.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/NAT.h deleted file mode 100644 index 3f8e2cac3a3..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/NAT.h +++ /dev/null @@ -1,162 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: NAT.h ///////////////////////////////////////////////////////////////////////////////// -// Author: Bryan Cleveland April 2002 -// Desc: Resolves NAT'd IPs and port numbers for the other players in a game. -/////////////////////////////////////////////////////////////////////////////////////////////////// - -#pragma once - -#ifndef __NAT_H -#define __NAT_H - -#include "Lib\BaseType.h" -#include "GameNetwork/NetworkInterface.h" -#include "GameNetwork/FirewallHelper.h" - -class Transport; -class GameSlot; - -enum NATStateType { - NATSTATE_IDLE, - NATSTATE_DOCONNECTIONPATHS, - NATSTATE_WAITFORSTATS, - NATSTATE_DONE, - NATSTATE_FAILED -}; - -enum NATConnectionState { - NATCONNECTIONSTATE_NOSTATE, - NATCONNECTIONSTATE_WAITINGTOBEGIN, -// NATCONNECTIONSTATE_NETGEARDELAY, - NATCONNECTIONSTATE_WAITINGFORMANGLERRESPONSE, - NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT, - NATCONNECTIONSTATE_WAITINGFORRESPONSE, - NATCONNECTIONSTATE_DONE, - NATCONNECTIONSTATE_FAILED -}; - -struct ConnectionNodeType { - FirewallHelperClass::tFirewallBehaviorType m_behavior; ///< the NAT/Firewall behavior of this node. - UnsignedInt m_slotIndex; ///< the player list index of this node. -}; - -class NAT { -public: - NAT(); - virtual ~NAT(); - - NATStateType update(); - - void attachSlotList(GameSlot **slotList, Int localSlot, UnsignedInt localIP); - void establishConnectionPaths(); - - Int getSlotPort(Int slot); - Transport * getTransport(); ///< return the newly created Transport layer that has all the connections and whatnot. - - // Notification messages from GameSpy - void processGlobalMessage(Int slotNum, const char *options); - -protected: - NATConnectionState connectionUpdate(); ///< the update function for the connections. - void sendMangledSourcePort(); ///< starts the process to get the next mangled source port. - void processManglerResponse(UnsignedShort mangledPort); - - Bool allConnectionsDoneThisRound(); - Bool allConnectionsDone(); - - void generatePortNumbers(GameSlot **slotList, Int localSlot); ///< generate all of the slots' port numbers to be used. - - void doThisConnectionRound(); ///< compute who will connect with who for this round. - void setConnectionState(Int nodeNumber, NATConnectionState state); ///< central point for changing a connection's state. - void sendAProbe(UnsignedInt ip, UnsignedShort port, Int fromNode); ///< send a "PROBE" packet to this IP and port. - void notifyTargetOfProbe(GameSlot *targetSlot); - void notifyUsersOfConnectionDone(Int nodeIndex); - void notifyUsersOfConnectionFailed(Int nodeIndex); - void sendMangledPortNumberToTarget(UnsignedShort mangledPort, GameSlot *targetSlot); - - void probed(Int nodeNumber); - void gotMangledPort(Int nodeNumber, UnsignedShort mangledPort); - void gotInternalAddress(Int nodeNumber, UnsignedInt address); - void connectionComplete(Int slotIndex); - void connectionFailed(Int slotIndex); - - Transport *m_transport; - GameSlot **m_slotList; - NATStateType m_NATState; - Int m_localNodeNumber; ///< The node number of the local player. - Int m_targetNodeNumber; ///< The node number of the player we are connecting to this round. - UnsignedInt m_localIP; ///< The IP of the local computer. - UnsignedInt m_numNodes; ///< The number of players we have to connect together. - UnsignedInt m_connectionRound; ///< The "round" of connections we are currently on. - - Int m_numRetries; - Int m_maxNumRetriesAllowed; - - UnsignedShort m_packetID; - UnsignedShort m_spareSocketPort; - time_t m_manglerRetryTime; - Int m_manglerRetries; - UnsignedShort m_previousSourcePort; - - Bool m_beenProbed; ///< have I been notified that I've been probed this round? - - UnsignedInt m_manglerAddress; - - time_t m_timeTillNextSend; ///< The number of milliseconds till we send to the other guy's port again. - NATConnectionState m_connectionStates[MAX_SLOTS]; ///< connection states for this round for all the nodes. - - ConnectionNodeType m_connectionNodes[MAX_SLOTS]; ///< info regarding the nodes that are being connected. - - UnsignedShort m_sourcePorts[MAX_SLOTS]; ///< the source ports that the other players communicate to us on. - - Bool m_myConnections[MAX_SLOTS]; ///< keeps track of all the nodes I've connected to. For keepalive. - time_t m_nextKeepaliveTime; ///< the next time we will send out our keepalive packets. - - static Int m_connectionPairs[MAX_SLOTS-1][MAX_SLOTS-1][MAX_SLOTS]; - Int m_connectionPairIndex; - - UnsignedShort m_startingPortNumber; ///< the starting port number for this game. The slots all get port numbers with their port numbers based on this number. - ///< this is done so that games that are played right after each other with the same players in the same - ///< slot order will not use the old source port allocation scheme in case their NAT - ///< hasn't timed out that connection. - - time_t m_nextPortSendTime; ///< Last time we sent our mangled port number to our target this round. - - time_t m_timeoutTime; ///< the time at which we will time out waiting for the other player's port number. - time_t m_roundTimeout; ///< the time at which we will time out this connection round. - - static Int m_timeBetweenRetries; // 1 second between retries sounds good to me. - static time_t m_manglerRetryTimeInterval; // sounds good to me. - static Int m_maxAllowedManglerRetries; // works for me. - static time_t m_keepaliveInterval; // 15 seconds between keepalive packets seems good. - static time_t m_timeToWaitForPort; // wait for ten seconds for the other player's port number. - static time_t m_timeForRoundTimeout; // wait for at most ten seconds for each connection round to finish. - -}; - -extern NAT *TheNAT; - -#endif // #ifndef __NAT_H \ No newline at end of file diff --git a/GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp b/GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp index ba20321e594..9807c695e97 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp @@ -103,7 +103,6 @@ #include "GameNetwork/NetworkInterface.h" #include "GameNetwork/LANAPI.h" -#include "GameNetwork/GameSpy/GameResultsThread.h" #include "Common/Version.h" diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/FunctionLexicon.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/FunctionLexicon.cpp index 2f6a9569dc3..74db38eddf5 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/System/FunctionLexicon.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/System/FunctionLexicon.cpp @@ -121,7 +121,6 @@ static FunctionLexicon::TableEntry gameWinSystemTable[] = { NAMEKEY_INVALID, "WOLBuddyOverlaySystem", WOLBuddyOverlaySystem }, { NAMEKEY_INVALID, "WOLBuddyOverlayRCMenuSystem", WOLBuddyOverlayRCMenuSystem }, { NAMEKEY_INVALID, "RCGameDetailsMenuSystem", RCGameDetailsMenuSystem }, - { NAMEKEY_INVALID, "GameSpyPlayerInfoOverlaySystem",GameSpyPlayerInfoOverlaySystem }, { NAMEKEY_INVALID, "WOLMessageWindowSystem", WOLMessageWindowSystem }, { NAMEKEY_INVALID, "WOLQuickMatchMenuSystem", WOLQuickMatchMenuSystem }, { NAMEKEY_INVALID, "WOLWelcomeMenuSystem", WOLWelcomeMenuSystem }, @@ -192,7 +191,6 @@ static FunctionLexicon::TableEntry gameWinInputTable[] = { NAMEKEY_INVALID, "WOLGameSetupMenuInput", WOLGameSetupMenuInput }, { NAMEKEY_INVALID, "WOLMapSelectMenuInput", WOLMapSelectMenuInput }, { NAMEKEY_INVALID, "WOLBuddyOverlayInput", WOLBuddyOverlayInput }, - { NAMEKEY_INVALID, "GameSpyPlayerInfoOverlayInput", GameSpyPlayerInfoOverlayInput }, { NAMEKEY_INVALID, "WOLMessageWindowInput", WOLMessageWindowInput }, { NAMEKEY_INVALID, "WOLQuickMatchMenuInput", WOLQuickMatchMenuInput }, { NAMEKEY_INVALID, "WOLWelcomeMenuInput", WOLWelcomeMenuInput }, @@ -266,7 +264,6 @@ static FunctionLexicon::TableEntry winLayoutInitTable[] = { NAMEKEY_INVALID, "WOLBuddyOverlayInit", WOLBuddyOverlayInit }, { NAMEKEY_INVALID, "WOLBuddyOverlayRCMenuInit", WOLBuddyOverlayRCMenuInit }, { NAMEKEY_INVALID, "RCGameDetailsMenuInit", RCGameDetailsMenuInit }, - { NAMEKEY_INVALID, "GameSpyPlayerInfoOverlayInit", GameSpyPlayerInfoOverlayInit }, { NAMEKEY_INVALID, "WOLMessageWindowInit", WOLMessageWindowInit }, { NAMEKEY_INVALID, "WOLQuickMatchMenuInit", WOLQuickMatchMenuInit }, { NAMEKEY_INVALID, "WOLWelcomeMenuInit", WOLWelcomeMenuInit }, @@ -314,7 +311,6 @@ static FunctionLexicon::TableEntry winLayoutUpdateTable[] = { NAMEKEY_INVALID, "PopupHostGameUpdate", PopupHostGameUpdate }, { NAMEKEY_INVALID, "WOLMapSelectMenuUpdate", WOLMapSelectMenuUpdate }, { NAMEKEY_INVALID, "WOLBuddyOverlayUpdate", WOLBuddyOverlayUpdate }, - { NAMEKEY_INVALID, "GameSpyPlayerInfoOverlayUpdate",GameSpyPlayerInfoOverlayUpdate }, { NAMEKEY_INVALID, "WOLMessageWindowUpdate", WOLMessageWindowUpdate }, { NAMEKEY_INVALID, "WOLQuickMatchMenuUpdate", WOLQuickMatchMenuUpdate }, { NAMEKEY_INVALID, "WOLWelcomeMenuUpdate", WOLWelcomeMenuUpdate }, @@ -355,7 +351,6 @@ static FunctionLexicon::TableEntry winLayoutShutdownTable[] = { NAMEKEY_INVALID, "WOLGameSetupMenuShutdown", WOLGameSetupMenuShutdown }, { NAMEKEY_INVALID, "WOLMapSelectMenuShutdown", WOLMapSelectMenuShutdown }, { NAMEKEY_INVALID, "WOLBuddyOverlayShutdown", WOLBuddyOverlayShutdown }, - { NAMEKEY_INVALID, "GameSpyPlayerInfoOverlayShutdown",GameSpyPlayerInfoOverlayShutdown }, { NAMEKEY_INVALID, "WOLMessageWindowShutdown", WOLMessageWindowShutdown }, { NAMEKEY_INVALID, "WOLQuickMatchMenuShutdown", WOLQuickMatchMenuShutdown }, { NAMEKEY_INVALID, "WOLWelcomeMenuShutdown", WOLWelcomeMenuShutdown }, diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Diplomacy.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Diplomacy.cpp index 5118a563afe..5088549b456 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Diplomacy.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Diplomacy.cpp @@ -54,8 +54,6 @@ #include "GameLogic/VictoryConditions.h" #include "GameNetwork/GameInfo.h" #include "GameNetwork/NetworkInterface.h" -#include "GameNetwork/GameSpy/BuddyDefs.h" -#include "GameNetwork/GameSpy/peerDefs.h" #ifdef _INTERNAL // for occasional debugging... diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/DownloadMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/DownloadMenu.cpp deleted file mode 100644 index 701030bc064..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/DownloadMenu.cpp +++ /dev/null @@ -1,436 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: DownloadMenu.cpp ///////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -// -// Electronic Arts Pacific. -// -// Confidential Information -// Copyright (C) 2002 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// Project: RTS3 -// -// File name: DownloadMenu.cpp -// -// Created: Matthew D. Campbell, July 2002 -// -// Desc: the Patch Download window control -// -//----------------------------------------------------------------------------- -/////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "Common/NameKeyGenerator.h" -#include "GameClient/GUICallbacks.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/GadgetProgressBar.h" -#include "GameClient/GameText.h" -#include "GameClient/MessageBox.h" - -#include "GameLogic/GameLogic.h" - -#include "GameNetwork/DownloadManager.h" -#include "GameNetwork/GameSpy/MainMenuUtils.h" - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -static NameKeyType buttonCancelID = NAMEKEY_INVALID; -static NameKeyType staticTextSizeID = NAMEKEY_INVALID; -static NameKeyType staticTextTimeID = NAMEKEY_INVALID; -static NameKeyType staticTextFileID = NAMEKEY_INVALID; -static NameKeyType staticTextStatusID = NAMEKEY_INVALID; -static NameKeyType progressBarMunkeeID = NAMEKEY_INVALID; - -static GameWindow * staticTextSize = NULL; -static GameWindow * staticTextTime = NULL; -static GameWindow * staticTextFile = NULL; -static GameWindow * staticTextStatus = NULL; -static GameWindow * progressBarMunkee = NULL; - -static GameWindow *parent = NULL; - -static void closeDownloadWindow( void ) -{ - DEBUG_ASSERTCRASH(parent, ("No Parent")); - if (!parent) - return; - - WindowLayout *menuLayout = parent->winGetLayout(); - menuLayout->runShutdown(); - menuLayout->destroyWindows(); - menuLayout->deleteInstance(); - menuLayout = NULL; - - GameWindow *mainWin = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("MainMenu.wnd:MainMenuParent") ); - if (mainWin) - TheWindowManager->winSetFocus( mainWin ); -} - -static void errorCallback( void ) -{ - HandleCanceledDownload(); - closeDownloadWindow(); -} - -static void successQuitCallback( void ) -{ - TheGameEngine->setQuitting( TRUE ); - closeDownloadWindow(); - - // Clean up game data. No crashy-crash for you! - if (TheGameLogic->isInGame()) - TheMessageStream->appendMessage( GameMessage::MSG_CLEAR_GAME_DATA ); -} - -static void successNoQuitCallback( void ) -{ - HandleCanceledDownload(); - closeDownloadWindow(); -} - -class DownloadManagerMunkee : public DownloadManager -{ -public: - DownloadManagerMunkee() {m_shouldQuitOnSuccess = true; m_shouldQuitOnSuccess = false;} - virtual HRESULT OnError( Int error ); - virtual HRESULT OnEnd(); - virtual HRESULT OnProgressUpdate( Int bytesread, Int totalsize, Int timetaken, Int timeleft ); - virtual HRESULT OnStatusUpdate( Int status ); - virtual HRESULT downloadFile( AsciiString server, AsciiString username, AsciiString password, AsciiString file, AsciiString localfile, AsciiString regkey, Bool tryResume ); - -private: - Bool m_shouldQuitOnSuccess; -}; - -HRESULT DownloadManagerMunkee::downloadFile( AsciiString server, AsciiString username, AsciiString password, AsciiString file, AsciiString localfile, AsciiString regkey, Bool tryResume ) -{ - // see if we'll need to restart - if (strstr(localfile.str(), "patches\\") != NULL) - { - m_shouldQuitOnSuccess = true; - } - - if (staticTextFile) - { - AsciiString bob = file; - - // just get the filename, not the pathname - const char *tmp = bob.reverseFind('/'); - if (tmp) - bob = tmp+1; - tmp = bob.reverseFind('\\'); - if (tmp) - bob = tmp+1; - - UnicodeString fileString; - fileString.translate(bob); - GadgetStaticTextSetText(staticTextFile, fileString); - } - - password.format("-%s", password.str()); - return DownloadManager::downloadFile( server, username, password, file, localfile, regkey, tryResume ); -} -HRESULT DownloadManagerMunkee::OnError( Int error ) -{ - HRESULT ret = DownloadManager::OnError( error ); - - MessageBoxOk(TheGameText->fetch("GUI:DownloadErrorTitle"), getErrorString(), errorCallback); - return ret; -} -HRESULT DownloadManagerMunkee::OnEnd() -{ - HRESULT ret = DownloadManager::OnEnd(); - - if (isFileQueuedForDownload()) - { - return downloadNextQueuedFile(); - } - if (m_shouldQuitOnSuccess) - MessageBoxOk(TheGameText->fetch("GUI:DownloadSuccessTitle"), TheGameText->fetch("GUI:DownloadSuccessMustQuit"), successQuitCallback); - else - MessageBoxOk(TheGameText->fetch("GUI:DownloadSuccessTitle"), TheGameText->fetch("GUI:DownloadSuccess"), successNoQuitCallback); - return ret; -} - -static time_t lastUpdate = 0; -static Int timeLeft = 0; -HRESULT DownloadManagerMunkee::OnProgressUpdate( Int bytesread, Int totalsize, Int timetaken, Int timeleft ) -{ - HRESULT ret = DownloadManager::OnProgressUpdate( bytesread, totalsize, timetaken, timeleft ); - - if (progressBarMunkee) - { - Int percent = bytesread * 100 / totalsize; - GadgetProgressBarSetProgress( progressBarMunkee, percent ); - } - - if (staticTextSize) - { - UnicodeString sizeString; - sizeString.format(TheGameText->fetch("GUI:DownloadBytesRatio"), bytesread, totalsize); - GadgetStaticTextSetText(staticTextSize, sizeString); - } - timeLeft = timeleft; - if (staticTextTime && GadgetStaticTextGetText(staticTextTime).isEmpty()) // only update immediately the first time - { - lastUpdate = time(NULL); - UnicodeString timeString; - if (timeleft) - { - DEBUG_ASSERTCRASH(timeleft > 0, ("Time left is negative!")); - timeleft = max(1, timeleft); - Int takenHour, takenMin, takenSec; - takenHour = timeleft / 60 / 60; - takenMin = timeleft / 60; - takenSec = timeleft % 60; - timeString.format(TheGameText->fetch("GUI:DownloadTimeLeft"), takenHour, takenMin, takenSec); - } - else - { - timeString = TheGameText->fetch("GUI:DownloadUnknownTime"); - } - GadgetStaticTextSetText(staticTextTime, timeString); - } - return ret; -} - -HRESULT DownloadManagerMunkee::OnStatusUpdate( Int status ) -{ - HRESULT ret = DownloadManager::OnStatusUpdate( status ); - - if (staticTextStatus) - { - GadgetStaticTextSetText(staticTextStatus, getStatusString()); - } - return ret; -} - -// PUBLIC FUNCTIONS /////////////////////////////////////////////////////////////////////////////// - -//------------------------------------------------------------------------------------------------- -/** Initialize the menu */ -//------------------------------------------------------------------------------------------------- -void DownloadMenuInit( WindowLayout *layout, void *userData ) -{ - - //set keyboard focus to main parent and set modal - NameKeyType parentID = TheNameKeyGenerator->nameToKey("DownloadMenu.wnd:ParentDownload"); - parent = TheWindowManager->winGetWindowFromId( NULL, parentID ); - - // get ids for our children controls - buttonCancelID = TheNameKeyGenerator->nameToKey( "DownloadMenu.wnd:ButtonCancel" ); - staticTextSizeID = TheNameKeyGenerator->nameToKey( "DownloadMenu.wnd:StaticTextSize" ); - staticTextTimeID = TheNameKeyGenerator->nameToKey( "DownloadMenu.wnd:StaticTextTime" ); - staticTextFileID = TheNameKeyGenerator->nameToKey( "DownloadMenu.wnd:StaticTextFile" ); - staticTextStatusID = TheNameKeyGenerator->nameToKey( "DownloadMenu.wnd:StaticTextStatus" ); - progressBarMunkeeID = TheNameKeyGenerator->nameToKey( "DownloadMenu.wnd:ProgressBarMunkee" ); - - staticTextSize = TheWindowManager->winGetWindowFromId( parent, staticTextSizeID ); - staticTextTime = TheWindowManager->winGetWindowFromId( parent, staticTextTimeID ); - staticTextFile = TheWindowManager->winGetWindowFromId( parent, staticTextFileID ); - staticTextStatus = TheWindowManager->winGetWindowFromId( parent, staticTextStatusID ); - progressBarMunkee = TheWindowManager->winGetWindowFromId( parent, progressBarMunkeeID ); - - DEBUG_ASSERTCRASH(!TheDownloadManager, ("Download manager already exists")); - if (TheDownloadManager) - { - delete TheDownloadManager; - } - TheDownloadManager = NEW DownloadManagerMunkee; - -} // end DownloadMenuInit - -//------------------------------------------------------------------------------------------------- -/** menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void DownloadMenuShutdown( WindowLayout *layout, void *userData ) -{ - DEBUG_ASSERTCRASH(TheDownloadManager, ("No download manager")); - if (TheDownloadManager) - { - delete TheDownloadManager; - TheDownloadManager = NULL; - } - - staticTextSize = NULL; - staticTextTime = NULL; - staticTextFile = NULL; - staticTextStatus = NULL; - progressBarMunkee = NULL; - parent = NULL; - -} // end DownloadMenuShutdown - -//------------------------------------------------------------------------------------------------- -/** menu update method */ -//------------------------------------------------------------------------------------------------- -void DownloadMenuUpdate( WindowLayout *layout, void *userData ) -{ - if (staticTextTime && !GadgetStaticTextGetText(staticTextTime).isEmpty()) - { - time_t now = time(NULL); - if (now <= lastUpdate) - return; - - lastUpdate = now; - - UnicodeString timeString; - if (timeLeft) - { - DEBUG_ASSERTCRASH(timeLeft > 0, ("Time left is negative!")); - timeLeft = max(1, timeLeft); - Int takenHour, takenMin, takenSec; - takenHour = timeLeft / 60 / 60; - takenMin = timeLeft / 60; - takenSec = timeLeft % 60; - timeString.format(TheGameText->fetch("GUI:DownloadTimeLeft"), takenHour, takenMin, takenSec); - } - else - { - timeString = TheGameText->fetch("GUI:DownloadUnknownTime"); - } - GadgetStaticTextSetText(staticTextTime, timeString); - } - -} // end DownloadMenuUpdate - -//------------------------------------------------------------------------------------------------- -/** menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType DownloadMenuInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - AsciiString buttonName( "DownloadMenu.wnd:ButtonCancel" ); - NameKeyType buttonID = TheNameKeyGenerator->nameToKey( buttonName ); - GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonID ); - - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)button, buttonID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; - -} // end DownloadMenuInput - -//------------------------------------------------------------------------------------------------- -/** menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType DownloadMenuSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CREATE: - { - - break; - - } // end create - //--------------------------------------------------------------------------------------------- - case GWM_DESTROY: - { - - break; - - } // end case - - //---------------------------------------------------------------------------------------------- - case GWM_INPUT_FOCUS: - { - - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - break; - - } // end input - //--------------------------------------------------------------------------------------------- - case GBM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if( controlID == buttonCancelID ) - { - HandleCanceledDownload(); - closeDownloadWindow(); - } // end if - - break; - - } // end selected - - default: - return MSG_IGNORED; - - } // end switch - - return MSG_HANDLED; - -} // end DownloadMenuSystem \ No newline at end of file diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MainMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MainMenu.cpp index e9517dd6593..f10bd6dcc38 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MainMenu.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MainMenu.cpp @@ -30,8 +30,6 @@ // INCLUDES /////////////////////////////////////////////////////////////////////////////////////// #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine -#include "GameSpy/ghttp/ghttp.h" - #include "Lib/BaseType.h" #include "Common/GameEngine.h" #include "Common/GameState.h" @@ -62,16 +60,11 @@ #include "GameClient/GameClient.h" #include "GameLogic/GameLogic.h" #include "GameLogic/ScriptEngine.h" -#include "GameNetwork/GameSpyOverlay.h" #include "GameClient/GameWindowTransitions.h" #include "GameClient/ChallengeGenerals.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/BuddyThread.h" #include "GameNetwork/DownloadManager.h" -#include "GameNetwork/GameSpy/MainMenuUtils.h" //Added By Saad //for accessing the InGameUI @@ -481,7 +474,9 @@ void MainMenuInit( WindowLayout *layout, void *userData ) buttonSinglePlayer = TheWindowManager->winGetWindowFromId( parentMainMenu, buttonSinglePlayerID ); buttonMultiPlayer = TheWindowManager->winGetWindowFromId( parentMainMenu, buttonMultiPlayerID ); buttonSkirmish = TheWindowManager->winGetWindowFromId( parentMainMenu, skirmishID ); - buttonOnline = TheWindowManager->winGetWindowFromId( parentMainMenu, onlineID ); + buttonOnline = TheWindowManager->winGetWindowFromId( parentMainMenu, onlineID ); + if (buttonOnline) + buttonOnline->winHide(TRUE); buttonNetwork = TheWindowManager->winGetWindowFromId( parentMainMenu, networkID ); buttonOptions = TheWindowManager->winGetWindowFromId( parentMainMenu, optionsID ); buttonExit = TheWindowManager->winGetWindowFromId( parentMainMenu, exitID ); @@ -595,12 +590,6 @@ void MainMenuInit( WindowLayout *layout, void *userData ) //getUpdate->winEnable( FALSE ); } /**/ - - if (TheGameSpyPeerMessageQueue && !TheGameSpyPeerMessageQueue->isConnected()) - { - DEBUG_LOG(("Tearing down GameSpy from MainMenuInit()\n")); - TearDownGameSpy(); - } if (TheMapCache) TheMapCache->updateCache(); @@ -901,7 +890,6 @@ void MainMenuUpdate( WindowLayout *layout, void *userData ) } HTTPThinkWrapper(); - GameSpyUpdateOverlays(); // if(localAnimateWindowManager) // localAnimateWindowManager->update(); // if(localAnimateWindowManager && pendingDropDown != DROPDOWN_NONE && localAnimateWindowManager->isFinished()) @@ -1031,15 +1019,12 @@ WindowMsgHandledType MainMenuSystem( GameWindow *window, UnsignedInt msg, } // end case //--------------------------------------------------------------------------------------------- - case GWM_DESTROY: - { - ghttpCleanup(); - DEBUG_LOG(("Tearing down GameSpy from MainMenuSystem(GWM_DESTROY)\n")); - TearDownGameSpy(); - StopAsyncDNSCheck(); // kill off the async DNS check thread in case it is still running - break; + case GWM_DESTROY: + { + StopAsyncDNSCheck(); // kill off the async DNS check thread in case it is still running + break; - } // end case + } // end case // -------------------------------------------------------------------------------------------- case GWM_INPUT_FOCUS: @@ -1055,13 +1040,9 @@ WindowMsgHandledType MainMenuSystem( GameWindow *window, UnsignedInt msg, //--------------------------------------------------------------------------------------------- case GBM_MOUSE_ENTERING: { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if(controlID == onlineID) - { - TheScriptEngine->signalUIInteract(TheShellHookNames[SHELL_SCRIPT_HOOK_MAIN_MENU_ONLINE_HIGHLIGHTED]); - } - else if(controlID == networkID) +GameWindow *control = (GameWindow *)mData1; +Int controlID = control->winGetWindowId(); +if(controlID == networkID) { TheScriptEngine->signalUIInteract(TheShellHookNames[SHELL_SCRIPT_HOOK_MAIN_MENU_NETWORK_HIGHLIGHTED]); } @@ -1173,14 +1154,10 @@ WindowMsgHandledType MainMenuSystem( GameWindow *window, UnsignedInt msg, //--------------------------------------------------------------------------------------------- case GBM_MOUSE_LEAVING: { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); +GameWindow *control = (GameWindow *)mData1; +Int controlID = control->winGetWindowId(); - if(controlID == onlineID) - { - TheScriptEngine->signalUIInteract(TheShellHookNames[SHELL_SCRIPT_HOOK_MAIN_MENU_ONLINE_UNHIGHLIGHTED]); - } - else if(controlID == networkID) +if(controlID == networkID) { TheScriptEngine->signalUIInteract(TheShellHookNames[SHELL_SCRIPT_HOOK_MAIN_MENU_NETWORK_UNHIGHLIGHTED]); } @@ -1437,20 +1414,6 @@ WindowMsgHandledType MainMenuSystem( GameWindow *window, UnsignedInt msg, TheShell->push( AsciiString("Menus/SkirmishGameOptionsMenu.wnd") ); TheScriptEngine->signalUIInteract(TheShellHookNames[SHELL_SCRIPT_HOOK_MAIN_MENU_SKIRMISH_SELECTED]); } - else if( controlID == onlineID ) - { - if(dontAllowTransitions) - break; - dontAllowTransitions = TRUE; - buttonPushed = TRUE; - dropDownWindows[DROPDOWN_MULTIPLAYER]->winHide(FALSE); - TheTransitionHandler->reverse("MainMenuMultiPlayerMenuTransitionToNext"); - - StartPatchCheck(); -// localAnimateWindowManager->reverseAnimateWindow(); - dropDown = DROPDOWN_NONE; - - } // end else if else if( controlID == networkID ) { if(dontAllowTransitions) diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp deleted file mode 100644 index 48492f0740f..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp +++ /dev/null @@ -1,537 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: NetworkDirectConnect.cpp -// Author: Bryan Cleveland, November 2001 -// Description: Lan Lobby Menu -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "GameSpy/peer/peer.h" - -#include "Common/QuotedPrintable.h" -#include "Common/UserPreferences.h" -#include "GameClient/AnimateWindowManager.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/GameText.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetComboBox.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/Shell.h" -#include "GameClient/GameWindowTransitions.h" - -#include "GameNetwork/IPEnumeration.h" -#include "GameNetwork/LANAPI.h" -#include "GameNetwork/LANAPICallbacks.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -// window ids ------------------------------------------------------------------------------ - -// Window Pointers ------------------------------------------------------------------------ - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// - -extern Bool LANbuttonPushed; -extern Bool LANisShuttingDown; - -static Bool isShuttingDown = false; -static Bool buttonPushed = false; - -static NameKeyType buttonBackID = NAMEKEY_INVALID; -static NameKeyType buttonHostID = NAMEKEY_INVALID; -static NameKeyType buttonJoinID = NAMEKEY_INVALID; -static NameKeyType editPlayerNameID = NAMEKEY_INVALID; -static NameKeyType comboboxRemoteIPID = NAMEKEY_INVALID; -static NameKeyType staticLocalIPID = NAMEKEY_INVALID; - -static GameWindow *buttonBack = NULL; -static GameWindow *buttonHost = NULL; -static GameWindow *buttonJoin = NULL; -static GameWindow *editPlayerName = NULL; -static GameWindow *comboboxRemoteIP = NULL; -static GameWindow *staticLocalIP = NULL; - -void PopulateRemoteIPComboBox() -{ - LANPreferences userprefs; - GadgetComboBoxReset(comboboxRemoteIP); - - Int numRemoteIPs = userprefs.getNumRemoteIPs(); - Color white = GameMakeColor(255,255,255,255); - - for (Int i = 0; i < numRemoteIPs; ++i) - { - UnicodeString entry; - entry = userprefs.getRemoteIPEntry(i); - GadgetComboBoxAddEntry(comboboxRemoteIP, entry, white); - } - - if (numRemoteIPs > 0) - { - GadgetComboBoxSetSelectedPos(comboboxRemoteIP, 0, TRUE); - } - userprefs.write(); -} - -void UpdateRemoteIPList() -{ - Int n1[4], n2[4]; - LANPreferences prefs; - Int numEntries = GadgetComboBoxGetLength(comboboxRemoteIP); - Int currentSelection = -1; - GadgetComboBoxGetSelectedPos(comboboxRemoteIP, ¤tSelection); - UnicodeString unisel = GadgetComboBoxGetText(comboboxRemoteIP); - AsciiString sel; - sel.translate(unisel); - -// UnicodeString newEntry = prefs.getRemoteIPEntry(0); - UnicodeString newEntry = unisel; - UnicodeString newIP; - newEntry.nextToken(&newIP, UnicodeString(L":")); - Int numFields = swscanf(newIP.str(), L"%d.%d.%d.%d", &(n1[0]), &(n1[1]), &(n1[2]), &(n1[3])); - - if (numFields != 4) { - // this is not a properly formatted IP, don't change a thing. - return; - } - - prefs["RemoteIP0"] = sel; - - Int currentINIEntry = 1; - - for (Int i = 0; i < numEntries; ++i) - { - if (i != currentSelection) - { - GadgetComboBoxSetSelectedPos(comboboxRemoteIP, i, FALSE); - UnicodeString uni; - uni = GadgetComboBoxGetText(comboboxRemoteIP); - AsciiString ascii; - ascii.translate(uni); - - // prevent more than one copy of an IP address from being put in the list. - if (currentSelection == -1) - { - UnicodeString oldEntry = uni; - UnicodeString oldIP; - oldEntry.nextToken(&oldIP, UnicodeString(L":")); - - swscanf(oldIP.str(), L"%d.%d.%d.%d", &(n2[0]), &(n2[1]), &(n2[2]), &(n2[3])); - - Bool isEqual = TRUE; - for (Int i = 0; (i < 4) && (isEqual == TRUE); ++i) { - if (n1[i] != n2[i]) { - isEqual = FALSE; - } - } - // check to see if this is a duplicate or if this is not a properly formatted IP address. - if (isEqual == TRUE) - { - --numEntries; - continue; - } - } - AsciiString temp; - temp.format("RemoteIP%d", currentINIEntry); - ++currentINIEntry; - prefs[temp.str()] = ascii; - } - } - - if (currentSelection == -1) - { - ++numEntries; - } - - AsciiString numRemoteIPs; - numRemoteIPs.format("%d", numEntries); - - prefs["NumRemoteIPs"] = numRemoteIPs; - - prefs.write(); -} - -void HostDirectConnectGame() -{ - // Init LAN API Singleton - DEBUG_ASSERTCRASH(TheLAN != NULL, ("TheLAN is NULL!")); - if (!TheLAN) - { - TheLAN = NEW LANAPI(); - } - - UnsignedInt localIP = TheLAN->GetLocalIP(); - UnicodeString localIPString; - localIPString.format(L"%d.%d.%d.%d", localIP >> 24, (localIP & 0xff0000) >> 16, (localIP & 0xff00) >> 8, localIP & 0xff); - - UnicodeString name; - name = GadgetTextEntryGetText(editPlayerName); - - LANPreferences prefs; - prefs["UserName"] = UnicodeStringToQuotedPrintable(name); - prefs.write(); - - while (name.getLength() > g_lanPlayerNameLength) - name.removeLastChar(); - TheLAN->RequestSetName(name); - TheLAN->RequestGameCreate(localIPString, TRUE); -} - -void JoinDirectConnectGame() -{ - // Init LAN API Singleton - - if (!TheLAN) - { - TheLAN = NEW LANAPI(); - } - - UnsignedInt ipaddress = 0; - UnicodeString ipunistring = GadgetComboBoxGetText(comboboxRemoteIP); - AsciiString asciientry; - asciientry.translate(ipunistring); - - AsciiString ipstring; - asciientry.nextToken(&ipstring, "("); - - char ipstr[16]; - strcpy(ipstr, ipstring.str()); - - Int ip1, ip2, ip3, ip4; - sscanf(ipstr, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4); - - DEBUG_LOG(("JoinDirectConnectGame - joining at %d.%d.%d.%d\n", ip1, ip2, ip3, ip4)); - - ipaddress = (ip1 << 24) + (ip2 << 16) + (ip3 << 8) + ip4; -// ipaddress = htonl(ipaddress); - - UnicodeString name; - name = GadgetTextEntryGetText(editPlayerName); - - LANPreferences prefs; - prefs["UserName"] = UnicodeStringToQuotedPrintable(name); - prefs.write(); - - UpdateRemoteIPList(); - PopulateRemoteIPComboBox(); - - while (name.getLength() > g_lanPlayerNameLength) - name.removeLastChar(); - TheLAN->RequestSetName(name); - - TheLAN->RequestGameJoinDirectConnect(ipaddress); -} - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Welcome Menu */ -//------------------------------------------------------------------------------------------------- -void NetworkDirectConnectInit( WindowLayout *layout, void *userData ) -{ - LANbuttonPushed = false; - LANisShuttingDown = false; - - if (TheLAN == NULL) - { - TheLAN = NEW LANAPI(); - TheLAN->init(); - } - TheLAN->reset(); - - buttonPushed = false; - isShuttingDown = false; - TheShell->showShellMap(TRUE); - buttonBackID = TheNameKeyGenerator->nameToKey( AsciiString( "NetworkDirectConnect.wnd:ButtonBack" ) ); - buttonHostID = TheNameKeyGenerator->nameToKey( AsciiString( "NetworkDirectConnect.wnd:ButtonHost" ) ); - buttonJoinID = TheNameKeyGenerator->nameToKey( AsciiString( "NetworkDirectConnect.wnd:ButtonJoin" ) ); - editPlayerNameID = TheNameKeyGenerator->nameToKey( AsciiString( "NetworkDirectConnect.wnd:EditPlayerName" ) ); - comboboxRemoteIPID = TheNameKeyGenerator->nameToKey( AsciiString( "NetworkDirectConnect.wnd:ComboboxRemoteIP" ) ); - staticLocalIPID = TheNameKeyGenerator->nameToKey( AsciiString( "NetworkDirectConnect.wnd:StaticLocalIP" ) ); - - buttonBack = TheWindowManager->winGetWindowFromId( NULL, buttonBackID); - buttonHost = TheWindowManager->winGetWindowFromId( NULL, buttonHostID); - buttonJoin = TheWindowManager->winGetWindowFromId( NULL, buttonJoinID); - editPlayerName = TheWindowManager->winGetWindowFromId( NULL, editPlayerNameID); - comboboxRemoteIP = TheWindowManager->winGetWindowFromId( NULL, comboboxRemoteIPID); - staticLocalIP = TheWindowManager->winGetWindowFromId( NULL, staticLocalIPID); - -// // animate controls -// TheShell->registerWithAnimateManager(buttonBack, WIN_ANIMATION_SLIDE_LEFT, TRUE, 800); -// TheShell->registerWithAnimateManager(buttonHost, WIN_ANIMATION_SLIDE_LEFT, TRUE, 600); -// TheShell->registerWithAnimateManager(buttonJoin, WIN_ANIMATION_SLIDE_LEFT, TRUE, 200); -// - LANPreferences userprefs; - UnicodeString name; - name = userprefs.getUserName(); - - if (name.getLength() == 0) - { - name = TheGameText->fetch("GUI:Player"); - } - - GadgetTextEntrySetText(editPlayerName, name); - - PopulateRemoteIPComboBox(); - - UnicodeString ipstr; - - delete TheLAN; - TheLAN = NULL; - - if (TheLAN == NULL) { -// DEBUG_ASSERTCRASH(TheLAN != NULL, ("TheLAN is null initializing the direct connect screen.")); - TheLAN = NEW LANAPI(); - - OptionPreferences prefs; - UnsignedInt IP = prefs.getOnlineIPAddress(); - - IPEnumeration IPs; - -// if (!IP) -// { - EnumeratedIP *IPlist = IPs.getAddresses(); - DEBUG_ASSERTCRASH(IPlist, ("No IP addresses found!")); - if (!IPlist) - { - /// @todo: display error and exit lan lobby if no IPs are found - } - - Bool foundIP = FALSE; - EnumeratedIP *tempIP = IPlist; - while ((tempIP != NULL) && (foundIP == FALSE)) { - if (IP == tempIP->getIP()) { - foundIP = TRUE; - } - tempIP = tempIP->getNext(); - } - - if (foundIP == FALSE) { - // The IP that we had no longer exists, we need to pick a new one. - IP = IPlist->getIP(); - } - -// IP = IPlist->getIP(); -// } - TheLAN->init(); - TheLAN->SetLocalIP(IP); - } - - UnsignedInt ip = TheLAN->GetLocalIP(); - ipstr.format(L"%d.%d.%d.%d", ip >> 24, (ip & 0xff0000) >> 16, (ip & 0xff00) >> 8, ip & 0xff); - GadgetStaticTextSetText(staticLocalIP, ipstr); - - TheLAN->RequestLobbyLeave(true); - layout->hide(FALSE); - layout->bringForward(); - TheTransitionHandler->setGroup("NetworkDirectConnectFade"); - - -} // NetworkDirectConnectInit - -//------------------------------------------------------------------------------------------------- -/** This is called when a shutdown is complete for this menu */ -//------------------------------------------------------------------------------------------------- -static void shutdownComplete( WindowLayout *layout ) -{ - - isShuttingDown = false; - - // hide the layout - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout ); - -} // end if - -//------------------------------------------------------------------------------------------------- -/** WOL Welcome Menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void NetworkDirectConnectShutdown( WindowLayout *layout, void *userData ) -{ - isShuttingDown = true; - - // if we are shutting down for an immediate pop, skip the animations - Bool popImmediate = *(Bool *)userData; - if( popImmediate ) - { - - shutdownComplete( layout ); - return; - - } //end if - - TheShell->reverseAnimatewindow(); - - TheTransitionHandler->reverse("NetworkDirectConnectFade"); -} // NetworkDirectConnectShutdown - - -//------------------------------------------------------------------------------------------------- -/** WOL Welcome Menu update method */ -//------------------------------------------------------------------------------------------------- -void NetworkDirectConnectUpdate( WindowLayout * layout, void *userData) -{ - // We'll only be successful if we've requested to - if(isShuttingDown && TheShell->isAnimFinished() && TheTransitionHandler->isFinished()) - shutdownComplete(layout); -}// NetworkDirectConnectUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Welcome Menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType NetworkDirectConnectInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - if (buttonPushed) - break; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonBack, buttonBackID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// NetworkDirectConnectInput - -//------------------------------------------------------------------------------------------------- -/** WOL Welcome Menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType NetworkDirectConnectSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - - switch( msg ) - { - - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - case GBM_SELECTED: - { - if (buttonPushed) - break; - - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if ( controlID == buttonBackID ) - { - UnicodeString name; - name = GadgetTextEntryGetText(editPlayerName); - - LANPreferences prefs; - prefs["UserName"] = UnicodeStringToQuotedPrintable(name); - prefs.write(); - - while (name.getLength() > g_lanPlayerNameLength) - name.removeLastChar(); - TheLAN->RequestSetName(name); - - buttonPushed = true; - LANbuttonPushed = true; - TheShell->pop(); - } //if ( controlID == buttonBack ) - else if (controlID == buttonHostID) - { - HostDirectConnectGame(); - } - else if (controlID == buttonJoinID) - { - JoinDirectConnectGame(); - } - break; - }// case GBM_SELECTED: - - case GEM_EDIT_DONE: - { - break; - } - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// NetworkDirectConnectSystem diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp index a5bfec7e6a4..b34e045aad9 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp @@ -30,8 +30,6 @@ // INCLUDES /////////////////////////////////////////////////////////////////////////////////////// #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine -#include "GameSpy/ghttp/ghttp.h" - #include "Common/AudioAffect.h" #include "Common/AudioSettings.h" #include "Common/GameAudio.h" @@ -63,8 +61,6 @@ #include "GameClient/GUICallbacks.h" #include "GameNetwork/FirewallHelper.h" #include "GameNetwork/IPEnumeration.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameNetwork/GameSpy/PeerDefs.h" #include "GameLogic/GameLogic.h" #include "GameLogic/ScriptEngine.h" #include "WWDownload/Registry.h" @@ -82,8 +78,6 @@ #endif -static NameKeyType comboBoxOnlineIPID = NAMEKEY_INVALID; -static GameWindow * comboBoxOnlineIP = NULL; static NameKeyType comboBoxLANIPID = NAMEKEY_INVALID; static GameWindow * comboBoxLANIP = NULL; @@ -807,7 +801,7 @@ static void setDefaults( void ) //------------------------------------------------------------------------------------------------- // Resolution //Find index of 800x600 mode. - if ((TheGameLogic->isInGame() == FALSE) || (TheGameLogic->isInShellGame() == TRUE) && !TheGameSpyInfo) { + if ((TheGameLogic->isInGame() == FALSE) || (TheGameLogic->isInShellGame() == TRUE)) { Int numResolutions = TheDisplay->getDisplayModeCount(); Int defaultResIndex=0; for( Int i = 0; i < numResolutions; ++i ) @@ -1128,13 +1122,6 @@ static void saveOptions( void ) TheWritableGlobalData->m_defaultIP = ip; pref->setLANIPAddress(ip); } - GadgetComboBoxGetSelectedPos(comboBoxOnlineIP, &index); - if (index>=0) - { - ip = (UnsignedInt)GadgetComboBoxGetItemData(comboBoxOnlineIP, index); - pref->setOnlineIPAddress(ip); - } - //------------------------------------------------------------------------------------------------- // HTTP Proxy GameWindow *textEntryHTTPProxy = TheWindowManager->winGetWindowFromId(NULL, NAMEKEY("OptionsMenu.wnd:TextEntryHTTPProxy")); @@ -1144,7 +1131,6 @@ static void saveOptions( void ) AsciiString aStr; aStr.translate(uStr); SetStringInRegistry("", "Proxy", aStr.str()); - ghttpSetProxy(aStr.str()); } //------------------------------------------------------------------------------------------------- @@ -1348,8 +1334,9 @@ void OptionsMenuInit( WindowLayout *layout, void *userData ) comboBoxLANIPID = TheNameKeyGenerator->nameToKey( AsciiString( "OptionsMenu.wnd:ComboBoxIP" ) ); comboBoxLANIP = TheWindowManager->winGetWindowFromId( NULL, comboBoxLANIPID); - comboBoxOnlineIPID = TheNameKeyGenerator->nameToKey( AsciiString( "OptionsMenu.wnd:ComboBoxOnlineIP" ) ); - comboBoxOnlineIP = TheWindowManager->winGetWindowFromId( NULL, comboBoxOnlineIPID); + NameKeyType comboBoxOnlineIPID = TheNameKeyGenerator->nameToKey( AsciiString( "OptionsMenu.wnd:ComboBoxOnlineIP" ) ); + if ( GameWindow *comboBoxOnlineIP = TheWindowManager->winGetWindowFromId( NULL, comboBoxOnlineIPID ) ) + comboBoxOnlineIP->winHide( TRUE ); checkAlternateMouseID = TheNameKeyGenerator->nameToKey( AsciiString( "OptionsMenu.wnd:CheckAlternateMouse" ) ); checkAlternateMouse = TheWindowManager->winGetWindowFromId( NULL, checkAlternateMouseID); checkRetaliationID = TheNameKeyGenerator->nameToKey( AsciiString( "OptionsMenu.wnd:Retaliation" ) ); @@ -1520,8 +1507,6 @@ void OptionsMenuInit( WindowLayout *layout, void *userData ) } } - // And now the GameSpy one - if (comboBoxOnlineIP) { UnsignedInt selectedIP = pref->getOnlineIPAddress(); UnicodeString str; @@ -1530,13 +1515,10 @@ void OptionsMenuInit( WindowLayout *layout, void *userData ) Int index; Int selectedIndex = -1; Int count = 0; - GadgetComboBoxReset(comboBoxOnlineIP); while (IPlist) { count++; str.translate(IPlist->getIPstring()); - index = GadgetComboBoxAddEntry(comboBoxOnlineIP, str, color); - GadgetComboBoxSetItemData(comboBoxOnlineIP, index, (void *)(IPlist->getIP())); if (selectedIP == IPlist->getIP()) { selectedIndex = index; @@ -1545,14 +1527,11 @@ void OptionsMenuInit( WindowLayout *layout, void *userData ) } if (selectedIndex >= 0) { - GadgetComboBoxSetSelectedPos(comboBoxOnlineIP, selectedIndex); } else { - GadgetComboBoxSetSelectedPos(comboBoxOnlineIP, 0); if (IPs.getAddresses()) { - pref->setOnlineIPAddress(IPs.getAddresses()->getIPstring()); } } } @@ -1796,12 +1775,10 @@ void OptionsMenuInit( WindowLayout *layout, void *userData ) GameWindow *parent = TheWindowManager->winGetWindowFromId( NULL, parentID ); TheWindowManager->winSetFocus( parent ); - if( (TheGameLogic->isInGame() && TheGameLogic->getGameMode() != GAME_SHELL) || TheGameSpyInfo ) + if( (TheGameLogic->isInGame() && TheGameLogic->getGameMode() != GAME_SHELL) ) { // disable controls that you can't change the options for in game comboBoxLANIP->winEnable(FALSE); - if (comboBoxOnlineIP) - comboBoxOnlineIP->winEnable(FALSE); checkSendDelay->winEnable(FALSE); buttonFirewallRefresh->winEnable(FALSE); @@ -1996,15 +1973,8 @@ WindowMsgHandledType OptionsMenuSystem( GameWindow *window, UnsignedInt msg, pref = NULL; } - comboBoxLANIP = NULL; - comboBoxOnlineIP = NULL; - - if(GameSpyIsOverlayOpen(GSOVERLAY_OPTIONS)) - GameSpyCloseOverlay(GSOVERLAY_OPTIONS); - else - { - DestroyOptionsLayout(); - } +comboBoxLANIP = NULL; +DestroyOptionsLayout(); } // end if else if (controlID == buttonAccept ) @@ -2018,23 +1988,16 @@ WindowMsgHandledType OptionsMenuSystem( GameWindow *window, UnsignedInt msg, pref = NULL; } - comboBoxLANIP = NULL; - comboBoxOnlineIP = NULL; - - if(!TheGameLogic->isInGame() || TheGameLogic->isInShellGame()) - destroyQuitMenu(); // if we're in a game, the change res then enter the same kind of game, we nee the quit menu to be gone. +comboBoxLANIP = NULL; +if(!TheGameLogic->isInGame() || TheGameLogic->isInShellGame()) +destroyQuitMenu(); // if we're in a game, the change res then enter the same kind of game, we nee the quit menu to be gone. - if(GameSpyIsOverlayOpen(GSOVERLAY_OPTIONS)) - GameSpyCloseOverlay(GSOVERLAY_OPTIONS); - else - { - DestroyOptionsLayout(); - if (dispChanged) - { - DoResolutionDialog(); - } - } +DestroyOptionsLayout(); +if (dispChanged) +{ +DoResolutionDialog(); +} } else if (controlID == buttonDefaults ) diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/PopupLadderSelect.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/PopupLadderSelect.cpp deleted file mode 100644 index 1c57a852b3e..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/PopupLadderSelect.cpp +++ /dev/null @@ -1,682 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PopupLadderSelect.cpp //////////////////////////////////////////////// -//----------------------------------------------------------------------------- -// -// Electronic Arts Pacific. -// -// Confidential Information -// Copyright (C) 2002 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// created: August 2002 -// -// Filename: PopupLadderSelect.cpp -// -// author: Matthew D. Campbell -// -// purpose: Contains the Callbacks for the Ladder Select Popup -// -//----------------------------------------------------------------------------- -/////////////////////////////////////////////////////////////////////////////// - -//----------------------------------------------------------------------------- -// SYSTEM INCLUDES //////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// USER INCLUDES ////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GlobalData.h" -#include "Common/Encrypt.h" -#include "Common/NameKeyGenerator.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/GameText.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/MapUtil.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameNetwork/GameSpy/LadderDefs.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -//#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpyOverlay.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -//----------------------------------------------------------------------------- -// DEFINES //////////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -static NameKeyType parentID = NAMEKEY_INVALID; -static NameKeyType listboxLadderSelectID = NAMEKEY_INVALID; -static NameKeyType listboxLadderDetailsID = NAMEKEY_INVALID; -static NameKeyType staticTextLadderNameID = NAMEKEY_INVALID; -static NameKeyType buttonOkID = NAMEKEY_INVALID; -static NameKeyType buttonCancelID = NAMEKEY_INVALID; - -static GameWindow *parent = NULL; -static GameWindow *listboxLadderSelect = NULL; -static GameWindow *listboxLadderDetails = NULL; -static GameWindow *staticTextLadderName = NULL; -static GameWindow *buttonOk = NULL; -static GameWindow *buttonCancel = NULL; - -// password entry popup -static NameKeyType passwordParentID = NAMEKEY_INVALID; -static NameKeyType buttonPasswordOkID = NAMEKEY_INVALID; -static NameKeyType buttonPasswordCancelID = NAMEKEY_INVALID; -static NameKeyType textEntryPasswordID = NAMEKEY_INVALID; -static GameWindow *passwordParent = NULL; -static GameWindow *textEntryPassword = NULL; - -// incorrect password popup -static NameKeyType badPasswordParentID = NAMEKEY_INVALID; -static NameKeyType buttonBadPasswordOkID = NAMEKEY_INVALID; -static GameWindow *badPasswordParent = NULL; - -static void updateLadderDetails( Int ladderID, GameWindow *staticTextLadderName, GameWindow *listboxLadderDetails ); - -void PopulateQMLadderComboBox( void ); -void PopulateCustomLadderComboBox( void ); - -void PopulateQMLadderListBox( GameWindow *win ); -void PopulateCustomLadderListBox( GameWindow *win ); - -void HandleQMLadderSelection(Int ladderID); -void HandleCustomLadderSelection(Int ladderID); - -void CustomMatchHideHostPopup(Bool hide); - -static void populateLadderComboBox( void ) -{ - // only one of these will do any work... - PopulateQMLadderComboBox(); - PopulateCustomLadderComboBox(); -} - -static void populateLadderListBox( void ) -{ - // only one of these will do any work... - PopulateQMLadderListBox(listboxLadderSelect); - PopulateCustomLadderListBox(listboxLadderSelect); - - Int selIndex, selID; - GadgetListBoxGetSelected(listboxLadderSelect, &selIndex); - if (selIndex < 0) - return; - selID = (Int)GadgetListBoxGetItemData(listboxLadderSelect, selIndex); - if (!selID) - return; - updateLadderDetails(selID, staticTextLadderName, listboxLadderDetails); -} - -static void handleLadderSelection( Int ladderID ) -{ - // only one of these will do any work... - HandleQMLadderSelection(ladderID); - HandleCustomLadderSelection(ladderID); -} - - -enum PasswordMode -{ - PASS_NONE, - PASS_ENTRY, - PASS_ERROR -}; - -static PasswordMode s_currentMode = PASS_NONE; -static void setPasswordMode(PasswordMode mode) -{ - s_currentMode = mode; - switch(mode) - { - case PASS_NONE: - if (passwordParent) - passwordParent->winHide(TRUE); - if (badPasswordParent) - badPasswordParent->winHide(TRUE); - if (buttonOk) - buttonOk->winEnable(TRUE); - if (buttonCancel) - buttonCancel->winEnable(TRUE); - if (textEntryPassword) - textEntryPassword->winEnable(FALSE); - if (listboxLadderSelect) - listboxLadderSelect->winEnable(TRUE); - TheWindowManager->winSetFocus(listboxLadderSelect); - break; - case PASS_ENTRY: - if (passwordParent) - passwordParent->winHide(FALSE); - if (badPasswordParent) - badPasswordParent->winHide(TRUE); - if (buttonOk) - buttonOk->winEnable(FALSE); - if (buttonCancel) - buttonCancel->winEnable(FALSE); - if (textEntryPassword) - { - textEntryPassword->winEnable(TRUE); - GadgetTextEntrySetText(textEntryPassword, UnicodeString::TheEmptyString); - } - if (listboxLadderSelect) - listboxLadderSelect->winEnable(FALSE); - TheWindowManager->winSetFocus(textEntryPassword); - break; - case PASS_ERROR: - if (passwordParent) - passwordParent->winHide(TRUE); - if (badPasswordParent) - badPasswordParent->winHide(FALSE); - if (buttonOk) - buttonOk->winEnable(FALSE); - if (buttonCancel) - buttonCancel->winEnable(FALSE); - if (textEntryPassword) - textEntryPassword->winEnable(FALSE); - if (listboxLadderSelect) - listboxLadderSelect->winEnable(FALSE); - TheWindowManager->winSetFocus(parent); - break; - } -} - -//----------------------------------------------------------------------------- -// PUBLIC FUNCTIONS /////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//------------------------------------------------------------------------------------------------- -/** Initialize the menu */ -//------------------------------------------------------------------------------------------------- -void PopupLadderSelectInit( WindowLayout *layout, void *userData ) -{ - parentID = NAMEKEY("PopupLadderSelect.wnd:Parent"); - parent = TheWindowManager->winGetWindowFromId(NULL, parentID); - - listboxLadderSelectID = NAMEKEY("PopupLadderSelect.wnd:ListBoxLadderSelect"); - listboxLadderSelect = TheWindowManager->winGetWindowFromId(parent, listboxLadderSelectID); - - listboxLadderDetailsID = NAMEKEY("PopupLadderSelect.wnd:ListBoxLadderDetails"); - listboxLadderDetails = TheWindowManager->winGetWindowFromId(parent, listboxLadderDetailsID); - - staticTextLadderNameID = NAMEKEY("PopupLadderSelect.wnd:StaticTextLadderName"); - staticTextLadderName = TheWindowManager->winGetWindowFromId(parent, staticTextLadderNameID); - - buttonOkID = NAMEKEY("PopupLadderSelect.wnd:ButtonOk"); - buttonCancelID = NAMEKEY("PopupLadderSelect.wnd:ButtonCancel"); - - buttonOk = TheWindowManager->winGetWindowFromId(parent, buttonOkID); - buttonCancel = TheWindowManager->winGetWindowFromId(parent, buttonCancelID); - - TheWindowManager->winSetFocus( parent ); - TheWindowManager->winSetModal( parent ); - - // password entry popup - passwordParentID = NAMEKEY("PopupLadderSelect.wnd:PasswordParent"); - passwordParent = TheWindowManager->winGetWindowFromId(parent, passwordParentID); - buttonPasswordOkID = NAMEKEY("PopupLadderSelect.wnd:ButtonPasswordOk"); - buttonPasswordCancelID = NAMEKEY("PopupLadderSelect.wnd:ButtonPasswordCancel"); - textEntryPasswordID = NAMEKEY("PopupLadderSelect.wnd:PasswordEntry"); - textEntryPassword = TheWindowManager->winGetWindowFromId(parent, textEntryPasswordID); - - // bad password popup - badPasswordParentID = NAMEKEY("PopupLadderSelect.wnd:BadPasswordParent"); - badPasswordParent = TheWindowManager->winGetWindowFromId(parent, badPasswordParentID); - buttonBadPasswordOkID = NAMEKEY("PopupLadderSelect.wnd:ButtonBadPasswordOk"); - - setPasswordMode(PASS_NONE); - - CustomMatchHideHostPopup(TRUE); - - // populate list box (based on whether we're in custom or quickmatch) - populateLadderListBox(); -} - -//------------------------------------------------------------------------------------------------- -/** Input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType PopupLadderSelectInput( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; -// if (buttonPushed) -// break; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - switch (s_currentMode) - { - case PASS_NONE: - // re-select whatever was chosen before - populateLadderComboBox(); - GameSpyCloseOverlay(GSOVERLAY_LADDERSELECT); - break; - case PASS_ENTRY: - case PASS_ERROR: - setPasswordMode(PASS_NONE); - break; - } - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; - -} - -static Int ladderIndex = 0; -void ladderSelectedCallback(void) -{ - handleLadderSelection( ladderIndex ); - - // update combo box - populateLadderComboBox(); - - // tear down overlay - GameSpyCloseOverlay( GSOVERLAY_LADDERSELECT ); -} - -//------------------------------------------------------------------------------------------------- -/** System callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType PopupLadderSelectSystem( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - // -------------------------------------------------------------------------------------------- - case GWM_CREATE: - { - break; - } // end create - //--------------------------------------------------------------------------------------------- - case GWM_DESTROY: - { - parent = NULL; - listboxLadderSelect = NULL; - listboxLadderDetails = NULL; - CustomMatchHideHostPopup(FALSE); - break; - } // end case - - //---------------------------------------------------------------------------------------------- - case GWM_INPUT_FOCUS: - { - // if we're given the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - break; - } // end input - //---------------------------------------------------------------------------------------------- - case GBM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if (controlID == buttonOkID) - { - // save selection - Int selectPos = -1; - GadgetListBoxGetSelected( listboxLadderSelect, &selectPos ); - if (selectPos < 0) - break; - - ladderIndex = (Int)GadgetListBoxGetItemData( listboxLadderSelect, selectPos, 0 ); - const LadderInfo *li = TheLadderList->findLadderByIndex( ladderIndex ); - if (li && li->cryptedPassword.isNotEmpty()) - { - // need password asking - setPasswordMode(PASS_ENTRY); - } - else - { - ladderSelectedCallback(); - } - } - else if (controlID == buttonCancelID) - { - // reset what had been - populateLadderComboBox(); - - // tear down overlay - GameSpyCloseOverlay( GSOVERLAY_LADDERSELECT ); - } - else if (controlID == buttonPasswordOkID) - { - const LadderInfo *li = TheLadderList->findLadderByIndex( ladderIndex ); - if (!li || li->cryptedPassword.isEmpty()) - { - // eh? something's not right. just pretend they typed something wrong... - setPasswordMode(PASS_ERROR); - break; - } - - AsciiString pass; - pass.translate(GadgetTextEntryGetText(textEntryPassword)); - if ( pass.isNotEmpty() ) // password ok - { - AsciiString cryptPass = EncryptString(pass.str()); - DEBUG_LOG(("pass is %s, crypted pass is %s, comparing to %s\n", - pass.str(), cryptPass.str(), li->cryptedPassword.str())); - if (cryptPass == li->cryptedPassword) - ladderSelectedCallback(); - else - setPasswordMode(PASS_ERROR); - } - else - { - setPasswordMode(PASS_ERROR); - } - } - else if (controlID == buttonPasswordCancelID) - { - setPasswordMode(PASS_NONE); - } - else if (controlID == buttonBadPasswordOkID) - { - setPasswordMode(PASS_NONE); - } - break; - } // end input - - //--------------------------------------------------------------------------------------------- - case GLM_SELECTED: - { - Int selIndex, selID; - GadgetListBoxGetSelected(listboxLadderSelect, &selIndex); - if (selIndex < 0) - break; - - selID = (Int)GadgetListBoxGetItemData(listboxLadderSelect, selIndex); - if (!selID) - break; - - updateLadderDetails(selID, staticTextLadderName, listboxLadderDetails); - break; - } // end GLM_DOUBLE_CLICKED - - //--------------------------------------------------------------------------------------------- - case GLM_DOUBLE_CLICKED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - Int selectPos = (Int)mData2; - GadgetListBoxSetSelected(control, &selectPos); - - if( controlID == listboxLadderSelectID ) - { - TheWindowManager->winSendSystemMsg( parent, GBM_SELECTED, - (WindowMsgData)buttonOk, buttonOk->winGetWindowId() ); - } - break; - } - - //--------------------------------------------------------------------------------------------- - case GEM_EDIT_DONE: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if (controlID == textEntryPasswordID) - { - TheWindowManager->winSendSystemMsg( parent, GBM_SELECTED, - (WindowMsgData)(TheWindowManager->winGetWindowFromId(passwordParent, buttonPasswordOkID)), buttonPasswordOkID ); - } - break; - } - - default: - return MSG_IGNORED; - - } // end switch - - return MSG_HANDLED; - -} - - -//----------------------------------------------------------------------------- -// PRIVATE FUNCTIONS ////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -static void updateLadderDetails( Int selID, GameWindow *staticTextLadderName, GameWindow *listboxLadderDetails ) -{ - if (!staticTextLadderName || !listboxLadderDetails) - return; - - GadgetStaticTextSetText(staticTextLadderName, UnicodeString::TheEmptyString); - GadgetListBoxReset(listboxLadderDetails); - - const LadderInfo *info = TheLadderList->findLadderByIndex(selID); - if (!info) - return; - - UnicodeString line; - Color color = GameMakeColor( 255, 255, 255, 255 ); - Color captionColor = GameMakeColor( 0, 255, 255, 255 ); - - // name - line.format(TheGameText->fetch("GUI:LadderNameAndSize"), info->name.str(), info->playersPerTeam, info->playersPerTeam); - GadgetStaticTextSetText(staticTextLadderName, line); - - // location - if (!info->location.isEmpty()) - GadgetListBoxAddEntryText(listboxLadderDetails, info->location, captionColor, -1); - - // homepage - line.format(TheGameText->fetch("GUI:LadderURL"), info->homepageURL.str()); - GadgetListBoxAddEntryText(listboxLadderDetails, line, captionColor, -1); - - // description - if (!info->description.isEmpty()) - GadgetListBoxAddEntryText(listboxLadderDetails, info->description, color, -1); - - // requires password? - if (info->cryptedPassword.isNotEmpty()) - { - GadgetListBoxAddEntryText(listboxLadderDetails, TheGameText->fetch("GUI:LadderHasPassword"), captionColor, -1); - } - - // wins limits - if (info->minWins) - { - line.format(TheGameText->fetch("GUI:LadderMinWins"), info->minWins); - GadgetListBoxAddEntryText(listboxLadderDetails, line, captionColor, -1); - } - if (info->maxWins) - { - line.format(TheGameText->fetch("GUI:LadderMaxWins"), info->maxWins); - GadgetListBoxAddEntryText(listboxLadderDetails, line, captionColor, -1); - } - - // random factions? - if (info->randomFactions) - { - GadgetListBoxAddEntryText(listboxLadderDetails, TheGameText->fetch("GUI:LadderRandomFactions"), captionColor, -1); - } - else - { - GadgetListBoxAddEntryText(listboxLadderDetails, TheGameText->fetch("GUI:LadderFactions"), captionColor, -1); - } - - // factions - AsciiStringList validFactions = info->validFactions; - for (AsciiStringListIterator it = validFactions.begin(); it != validFactions.end(); ++it) - { - AsciiString marker; - marker.format("INI:Faction%s", it->str()); - GadgetListBoxAddEntryText(listboxLadderDetails, TheGameText->fetch(marker), color, -1); - } - - // random maps? - if (info->randomMaps) - { - GadgetListBoxAddEntryText(listboxLadderDetails, TheGameText->fetch("GUI:LadderRandomMaps"), captionColor, -1); - } - else - { - GadgetListBoxAddEntryText(listboxLadderDetails, TheGameText->fetch("GUI:LadderMaps"), captionColor, -1); - } - - // maps - AsciiStringList validMaps = info->validMaps; - for (it = validMaps.begin(); it != validMaps.end(); ++it) - { - const MapMetaData *md = TheMapCache->findMap(*it); - if (md) - { - GadgetListBoxAddEntryText(listboxLadderDetails, md->m_displayName, color, -1); - } - } -} - -static void closeRightClickMenu(GameWindow *win) -{ - - if(win) - { - WindowLayout *winLay = win->winGetLayout(); - if(!winLay) - return; - winLay->destroyWindows(); - winLay->deleteInstance(); - winLay = NULL; - - } -} -void RCGameDetailsMenuInit( WindowLayout *layout, void *userData ) -{ -} - -WindowMsgHandledType RCGameDetailsMenuSystem( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 ) -{ - - static NameKeyType ladderInfoID = NAMEKEY_INVALID; - static NameKeyType buttonOkID = NAMEKEY_INVALID; - switch( msg ) - { - - case GWM_CREATE: - { - ladderInfoID = NAMEKEY("RCGameDetailsMenu.wnd:ButtonLadderDetails"); - buttonOkID = NAMEKEY("PopupLadderDetails.wnd:ButtonOk"); - break; - } // case GWM_DESTROY: - - case GGM_CLOSE: - { - closeRightClickMenu(window); - //rcMenu = NULL; - break; - } - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GBM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - Int selectedID = (Int)window->winGetUserData(); - if(!selectedID) - break; - closeRightClickMenu(window); - - if (controlID == ladderInfoID) - { - StagingRoomMap *srm = TheGameSpyInfo->getStagingRoomList(); - StagingRoomMap::iterator srmIt = srm->find(selectedID); - if (srmIt != srm->end()) - { - GameSpyStagingRoom *theRoom = srmIt->second; - if (!theRoom) - break; - const LadderInfo *linfo = TheLadderList->findLadder(theRoom->getLadderIP(), theRoom->getLadderPort()); - if (linfo) - { - WindowLayout *rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/PopupLadderDetails.wnd")); - if (!rcLayout) - break; - - GameWindow *rcMenu = rcLayout->getFirstWindow(); - rcMenu->winGetLayout()->runInit(); - rcMenu->winBringToTop(); - rcMenu->winHide(FALSE); - - rcMenu->winSetUserData((void *)selectedID); - TheWindowManager->winSetLoneWindow(rcMenu); - - GameWindow *st = TheWindowManager->winGetWindowFromId(NULL, - NAMEKEY("PopupLadderDetails.wnd:StaticTextLadderName")); - GameWindow *lb = TheWindowManager->winGetWindowFromId(NULL, - NAMEKEY("PopupLadderDetails.wnd:ListBoxLadderDetails")); - updateLadderDetails(selectedID, st, lb); - } - } - } - break; - } - default: - return MSG_IGNORED; - - }//Switch - return MSG_HANDLED; -} diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ScoreScreen.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ScoreScreen.cpp index 46eb2eefce7..f6e95713109 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ScoreScreen.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ScoreScreen.cpp @@ -60,7 +60,6 @@ #include "Common/GameEngine.h" #include "Common/GameLOD.h" #include "Common/GameState.h" -#include "Common/GameSpyMiscPreferences.h" #include "Common/GlobalData.h" #include "Common/NameKeyGenerator.h" #include "Common/Player.h" @@ -90,13 +89,8 @@ #include "GameClient/CampaignManager.h" #include "GameClient/GameWindowTransitions.h" #include "GameClient/VideoPlayer.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/GameResultsThread.h" #include "GameNetwork/NetworkDefs.h" #include "GameNetwork/LANAPICallbacks.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" #include "GameClient/InGameUI.h" #include "GameClient/ChallengeGenerals.h" diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp deleted file mode 100644 index be7280dec14..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp +++ /dev/null @@ -1,1450 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLBuddyOverlay.cpp -// Author: Chris Huybregts, November 2001 -// Description: Lan Lobby Menu -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/AudioEventRTS.h" -#include "Common/PlayerList.h" -#include "Common/Player.h" -#include "GameClient/GameText.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetPushButton.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/GadgetRadioButton.h" -#include "GameClient/Display.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/BuddyDefs.h" -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/LobbyUtils.h" -#include "GameNetwork/GameSpy/PersistentStorageDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpy/ThreadUtils.h" - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentID = NAMEKEY_INVALID; -static NameKeyType buttonHideID = NAMEKEY_INVALID; -static NameKeyType buttonAddBuddyID = NAMEKEY_INVALID; -static NameKeyType buttonDeleteBuddyID = NAMEKEY_INVALID; -static NameKeyType textEntryID = NAMEKEY_INVALID; -static NameKeyType listboxBuddyID = NAMEKEY_INVALID; -static NameKeyType listboxChatID = NAMEKEY_INVALID; -static NameKeyType buttonAcceptBuddyID = NAMEKEY_INVALID; -static NameKeyType buttonDenyBuddyID = NAMEKEY_INVALID; -static NameKeyType radioButtonBuddiesID = NAMEKEY_INVALID; -static NameKeyType radioButtonIgnoreID = NAMEKEY_INVALID; -static NameKeyType parentBuddiesID = NAMEKEY_INVALID; -static NameKeyType parentIgnoreID = NAMEKEY_INVALID; -static NameKeyType listboxIgnoreID = NAMEKEY_INVALID; -static NameKeyType buttonNotificationID = NAMEKEY_INVALID; - - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parent = NULL; -static GameWindow *buttonHide = NULL; -static GameWindow *buttonAddBuddy = NULL; -static GameWindow *buttonDeleteBuddy = NULL; -static GameWindow *textEntry = NULL; -static GameWindow *listboxBuddy = NULL; -static GameWindow *listboxChat = NULL; -static GameWindow *buttonAcceptBuddy = NULL; -static GameWindow *buttonDenyBuddy = NULL; -static GameWindow *radioButtonBuddies = NULL; -static GameWindow *radioButtonIgnore = NULL; -static GameWindow *parentBuddies = NULL; -static GameWindow *parentIgnore = NULL; -static GameWindow *listboxIgnore = NULL; - -static Bool isOverlayActive = false; -void insertChat( BuddyMessage msg ); -// RightClick pointers --------------------------------------------------------------------- -static GameWindow *rcMenu = NULL; -static WindowLayout *noticeLayout = NULL; -static UnsignedInt noticeExpires = 0; -enum { NOTIFICATION_EXPIRES = 3000 }; - -void setUnignoreText( WindowLayout *layout, AsciiString nick, GPProfile id); -void refreshIgnoreList( void ); -void showNotificationBox( AsciiString nick, UnicodeString message); -void deleteNotificationBox( void ); -static Bool lastNotificationWasStatus = FALSE; -static Int numOnlineInNotification = 0; - -class BuddyControls -{ -public: - BuddyControls(void ); - GameWindow *listboxChat; - NameKeyType listboxChatID; - - GameWindow *listboxBuddies; - NameKeyType listboxBuddiesID; - - GameWindow *textEntryEdit; - NameKeyType textEntryEditID; - Bool isInit; -}; - -static BuddyControls buddyControls; -BuddyControls::BuddyControls( void ) -{ - listboxChat = NULL; - listboxChatID = NAMEKEY_INVALID; - listboxBuddies = NULL; - listboxBuddiesID = NAMEKEY_INVALID; - textEntryEdit = NULL; - textEntryEditID = NAMEKEY_INVALID; - isInit = FALSE; -} -// At this point I don't give a damn about how good this way is. I'm doing it anyway. -enum -{ - BUDDY_RESETALL_CRAP = -1, - BUDDY_WINDOW_BUDDIES = 0, - BUDDY_WINDOW_DIPLOMACY, - BUDDY_WINDOW_WELCOME_SCREEN, -}; - -void InitBuddyControls(Int type) -{ - if(!TheGameSpyInfo) - { - buddyControls.textEntryEditID = NAMEKEY_INVALID; - buddyControls.textEntryEdit = NULL; - buddyControls.listboxBuddiesID = NAMEKEY_INVALID; - buddyControls.listboxChatID = NAMEKEY_INVALID; - buddyControls.listboxBuddies = NULL; - buddyControls.listboxChat = NULL; - buddyControls.isInit = FALSE; - return; - } - switch (type) { - case BUDDY_RESETALL_CRAP: - buddyControls.textEntryEditID = NAMEKEY_INVALID; - buddyControls.textEntryEdit = NULL; - buddyControls.listboxBuddiesID = NAMEKEY_INVALID; - buddyControls.listboxChatID = NAMEKEY_INVALID; - buddyControls.listboxBuddies = NULL; - buddyControls.listboxChat = NULL; - buddyControls.isInit = FALSE; - break; - case BUDDY_WINDOW_BUDDIES: - buddyControls.textEntryEditID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:TextEntryChat" ) ); - buddyControls.textEntryEdit = TheWindowManager->winGetWindowFromId(NULL, buddyControls.textEntryEditID); - buddyControls.listboxBuddiesID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ListboxBuddies" ) ); - buddyControls.listboxChatID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ListboxBuddyChat" ) ); - buddyControls.listboxBuddies = TheWindowManager->winGetWindowFromId( NULL, buddyControls.listboxBuddiesID ); - buddyControls.listboxChat = TheWindowManager->winGetWindowFromId( NULL, buddyControls.listboxChatID); - GadgetTextEntrySetText(buddyControls.textEntryEdit, UnicodeString.TheEmptyString); - buddyControls.isInit = TRUE; - break; - case BUDDY_WINDOW_DIPLOMACY: - buddyControls.textEntryEditID = TheNameKeyGenerator->nameToKey( AsciiString( "Diplomacy.wnd:TextEntryChat" ) ); - buddyControls.textEntryEdit = TheWindowManager->winGetWindowFromId(NULL, buddyControls.textEntryEditID); - buddyControls.listboxBuddiesID = TheNameKeyGenerator->nameToKey( AsciiString( "Diplomacy.wnd:ListboxBuddies" ) ); - buddyControls.listboxChatID = TheNameKeyGenerator->nameToKey( AsciiString( "Diplomacy.wnd:ListboxBuddyChat" ) ); - buddyControls.listboxBuddies = TheWindowManager->winGetWindowFromId( NULL, buddyControls.listboxBuddiesID ); - buddyControls.listboxChat = TheWindowManager->winGetWindowFromId( NULL, buddyControls.listboxChatID); - GadgetTextEntrySetText(buddyControls.textEntryEdit, UnicodeString.TheEmptyString); - buddyControls.isInit = TRUE; - break; - case BUDDY_WINDOW_WELCOME_SCREEN: - break; - default: - DEBUG_ASSERTCRASH(FALSE, ("Well, you really shouldn't have gotten here, if you really care about GUI Bugs, search for this string, you you don't care, call chris (who probably doesn't care either")); - } - -} - -WindowMsgHandledType BuddyControlSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2) -{ - if(!TheGameSpyInfo || TheGameSpyInfo->getLocalProfileID() == 0 || !buddyControls.isInit) - { - return MSG_IGNORED; - } - - switch( msg ) - { - case GLM_RIGHT_CLICKED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if( controlID == buddyControls.listboxBuddiesID ) - { - RightClickStruct *rc = (RightClickStruct *)mData2; - WindowLayout *rcLayout; - if(rc->pos < 0) - break; - - GPProfile profileID = (GPProfile)GadgetListBoxGetItemData(control, rc->pos, 0); - RCItemType itemType = (RCItemType)(Int)GadgetListBoxGetItemData(control, rc->pos, 1); - UnicodeString nick = GadgetListBoxGetText(control, rc->pos); - - GadgetListBoxSetSelected(control, rc->pos); - if (itemType == ITEM_BUDDY) - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCBuddiesMenu.wnd")); - else if (itemType == ITEM_REQUEST) - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCBuddyRequestMenu.wnd")); - else - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCNonBuddiesMenu.wnd")); - rcMenu = rcLayout->getFirstWindow(); - rcMenu->winGetLayout()->runInit(); - rcMenu->winBringToTop(); - rcMenu->winHide(FALSE); - - - ICoord2D rcSize, rcPos; - rcMenu->winGetSize(&rcSize.x, &rcSize.y); - rcPos.x = rc->mouseX; - rcPos.y = rc->mouseY; - if(rc->mouseX + rcSize.x > TheDisplay->getWidth()) - rcPos.x = TheDisplay->getWidth() - rcSize.x; - if(rc->mouseY + rcSize.y > TheDisplay->getHeight()) - rcPos.y = TheDisplay->getHeight() - rcSize.y; - rcMenu->winSetPosition(rcPos.x, rcPos.y); - - - GameSpyRCMenuData *rcData = NEW GameSpyRCMenuData; - rcData->m_id = profileID; - rcData->m_nick.translate(nick); - rcData->m_itemType = itemType; - setUnignoreText(rcLayout, rcData->m_nick, rcData->m_id); - rcMenu->winSetUserData((void *)rcData); - TheWindowManager->winSetLoneWindow(rcMenu); - } - else - return MSG_IGNORED; - break; - } - case GEM_EDIT_DONE: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if(controlID != buddyControls.textEntryEditID) - return MSG_IGNORED; - - // see if someone's selected - Int selected = -1; - GadgetListBoxGetSelected(buddyControls.listboxBuddies, &selected); - if (selected >= 0) - { - GPProfile selectedProfile = (GPProfile)GadgetListBoxGetItemData(buddyControls.listboxBuddies, selected); - BuddyInfoMap *m = TheGameSpyInfo->getBuddyMap(); - BuddyInfoMap::iterator recipIt = m->find(selectedProfile); - if (recipIt == m->end()) - break; - - DEBUG_LOG(("Trying to send a buddy message to %d.\n", selectedProfile)); - if (TheGameSpyGame && TheGameSpyGame->isInGame() && TheGameSpyGame->isGameInProgress() && - !ThePlayerList->getLocalPlayer()->isPlayerActive()) - { - DEBUG_LOG(("I'm dead - gotta look for cheats.\n")); - for (Int i=0; igetGameSpySlot(i)->getProfileID())); - if (TheGameSpyGame->getGameSpySlot(i)->getProfileID() == selectedProfile) - { - // can't send to someone in our game if we're dead/observing. security breach and all that. no seances for you. - if (buddyControls.listboxChat) - { - GadgetListBoxAddEntryText( buddyControls.listboxChat, TheGameText->fetch("Buddy:CantTalkToIngameBuddy"), - GameSpyColor[GSCOLOR_DEFAULT], -1, -1 ); - } - return MSG_HANDLED; - } - } - } - - // read the user's input and clear the entry box - UnicodeString txtInput; - txtInput.set(GadgetTextEntryGetText( buddyControls.textEntryEdit )); - GadgetTextEntrySetText(buddyControls.textEntryEdit, UnicodeString::TheEmptyString); - txtInput.trim(); - if (!txtInput.isEmpty()) - { - // Send the message - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_MESSAGE; - wcsncpy(req.arg.message.text, txtInput.str(), MAX_BUDDY_CHAT_LEN); - req.arg.message.text[MAX_BUDDY_CHAT_LEN-1] = 0; - req.arg.message.recipient = selectedProfile; - TheGameSpyBuddyMessageQueue->addRequest(req); - - // save message for future incarnations of the buddy window - BuddyMessageList *messages = TheGameSpyInfo->getBuddyMessages(); - BuddyMessage message; - message.m_timestamp = time(NULL); - message.m_senderID = TheGameSpyInfo->getLocalProfileID(); - message.m_senderNick = TheGameSpyInfo->getLocalBaseName(); - message.m_recipientID = selectedProfile; - message.m_recipientNick = recipIt->second.m_name; - message.m_message = UnicodeString(req.arg.message.text); - messages->push_back(message); - - // put message on screen - insertChat(message); - } - } - else - { - // nobody selected. Prompt the user. - if (buddyControls.listboxChat) - { - GadgetListBoxAddEntryText( buddyControls.listboxChat, TheGameText->fetch("Buddy:SelectBuddyToChat"), - GameSpyColor[GSCOLOR_DEFAULT], -1, -1 ); - } - } - break; - } - default: - return MSG_IGNORED; - } - return MSG_HANDLED; -} - - -static void insertChat( BuddyMessage msg ) -{ - if (buddyControls.listboxChat) - { - BuddyInfoMap *m = TheGameSpyInfo->getBuddyMap(); - BuddyInfoMap::iterator senderIt = m->find(msg.m_senderID); - BuddyInfoMap::iterator recipientIt = m->find(msg.m_recipientID); - Bool localSender = (msg.m_senderID == TheGameSpyInfo->getLocalProfileID()); - UnicodeString s; - //UnicodeString timeStr = UnicodeString(_wctime( (const time_t *)&msg.m_timestamp )); - UnicodeString timeStr; - if (localSender /*&& recipientIt != m->end()*/) - { - s.format(L"[%hs -> %hs] %s", TheGameSpyInfo->getLocalBaseName().str(), msg.m_recipientNick.str(), msg.m_message.str()); - Int index = GadgetListBoxAddEntryText( buddyControls.listboxChat, s, GameSpyColor[GSCOLOR_PLAYER_SELF], -1, -1 ); - GadgetListBoxAddEntryText( buddyControls.listboxChat, timeStr, GameSpyColor[GSCOLOR_PLAYER_SELF], index, 1); - } - else if (!localSender /*&& senderIt != m->end()*/) - { - if (!msg.m_senderID) - { - s = msg.m_message; - Int index = GadgetListBoxAddEntryText( buddyControls.listboxChat, s, GameSpyColor[GSCOLOR_DEFAULT], -1, -1 ); - GadgetListBoxAddEntryText( buddyControls.listboxChat, timeStr, GameSpyColor[GSCOLOR_DEFAULT], index, 1); - } - else - { - s.format(L"[%hs] %s", msg.m_senderNick.str(), msg.m_message.str()); - Int index = GadgetListBoxAddEntryText( buddyControls.listboxChat, s, GameSpyColor[GSCOLOR_PLAYER_BUDDY], -1, -1 ); - GadgetListBoxAddEntryText( buddyControls.listboxChat, timeStr, GameSpyColor[GSCOLOR_PLAYER_BUDDY], index, 1); - } - } - } -} - -void updateBuddyInfo( void ) -{ - if (!TheGameSpyBuddyMessageQueue->isConnected()) - { - GadgetListBoxReset(buddyControls.listboxBuddies); - return; - } - - if (!buddyControls.isInit) - return; - - int selected; - GPProfile selectedProfile = 0; - int visiblePos = GadgetListBoxGetTopVisibleEntry(buddyControls.listboxBuddies); - - GadgetListBoxGetSelected(buddyControls.listboxBuddies, &selected); - if (selected >= 0) - selectedProfile = (GPProfile)GadgetListBoxGetItemData(buddyControls.listboxBuddies, selected); - - selected = -1; - GadgetListBoxReset(buddyControls.listboxBuddies); - - // Add buddies - BuddyInfoMap *buddies = TheGameSpyInfo->getBuddyMap(); - BuddyInfoMap::iterator bIt; - for (bIt = buddies->begin(); bIt != buddies->end(); ++bIt) - { - BuddyInfo info = bIt->second; - GPProfile profileID = bIt->first; - - // insert name into box - UnicodeString formatStr; - formatStr.translate(info.m_name.str());//, info.m_status, info.m_statusString.str(), info.m_locationString.str()); - Color nameColor = (TheGameSpyInfo->isSavedIgnored(profileID)) ? - GameSpyColor[GSCOLOR_PLAYER_IGNORED] : GameSpyColor[GSCOLOR_PLAYER_BUDDY]; - int index = GadgetListBoxAddEntryText(buddyControls.listboxBuddies, formatStr, nameColor, -1, -1); - - // insert status into box - AsciiString marker; - marker.format("Buddy:%ls", info.m_statusString.str()); - if (!info.m_statusString.compareNoCase(L"Offline") || - !info.m_statusString.compareNoCase(L"Online") || - !info.m_statusString.compareNoCase(L"Matching")) - { - formatStr = TheGameText->fetch(marker); - } - else if (!info.m_statusString.compareNoCase(L"Staging") || - !info.m_statusString.compareNoCase(L"Loading") || - !info.m_statusString.compareNoCase(L"Playing")) - { - formatStr.format(TheGameText->fetch(marker), info.m_locationString.str()); - } - else if (!info.m_statusString.compareNoCase(L"Chatting")) - { - UnicodeString roomName; - GroupRoomMap::iterator gIt = TheGameSpyInfo->getGroupRoomList()->find( _wtoi(info.m_locationString.str()) ); - if (gIt != TheGameSpyInfo->getGroupRoomList()->end()) - { - AsciiString s; - s.format("GUI:%s", gIt->second.m_name.str()); - roomName = TheGameText->fetch(s); - } - formatStr.format(TheGameText->fetch(marker), roomName.str()); - } - else - { - formatStr = info.m_statusString; - } - GadgetListBoxAddEntryText(buddyControls.listboxBuddies, formatStr, GameSpyColor[GSCOLOR_DEFAULT], index, 1); - GadgetListBoxSetItemData(buddyControls.listboxBuddies, (void *)(profileID), index, 0 ); - GadgetListBoxSetItemData(buddyControls.listboxBuddies, (void *)(ITEM_BUDDY), index, 1 ); - - if (profileID == selectedProfile) - selected = index; - } - - // add requests - buddies = TheGameSpyInfo->getBuddyRequestMap(); - for (bIt = buddies->begin(); bIt != buddies->end(); ++bIt) - { - BuddyInfo info = bIt->second; - GPProfile profileID = bIt->first; - - // insert name into box - UnicodeString formatStr; - formatStr.translate(info.m_name.str()); - int index = GadgetListBoxAddEntryText(buddyControls.listboxBuddies, formatStr, GameSpyColor[GSCOLOR_DEFAULT], -1, -1); - GadgetListBoxSetItemData(buddyControls.listboxBuddies, (void *)(profileID), index, 0 ); - - // insert status into box - formatStr = TheGameText->fetch("GUI:BuddyAddReq"); - GadgetListBoxAddEntryText(buddyControls.listboxBuddies, formatStr, GameSpyColor[GSCOLOR_DEFAULT], index, 1); - GadgetListBoxSetItemData(buddyControls.listboxBuddies, (void *)(ITEM_REQUEST), index, 1 ); - - if (profileID == selectedProfile) - selected = index; - } - - - // select the same guy - if (selected >= 0) - { - GadgetListBoxSetSelected(buddyControls.listboxBuddies, selected); - } - - // view the same spot - GadgetListBoxSetTopVisibleEntry(buddyControls.listboxBuddies, visiblePos); -} - -void HandleBuddyResponses( void ) -{ - if (TheGameSpyBuddyMessageQueue) - { - BuddyResponse resp; - if (TheGameSpyBuddyMessageQueue->getResponse( resp )) - { - switch (resp.buddyResponseType) - { - case BuddyResponse::BUDDYRESPONSE_LOGIN: - { - deleteNotificationBox(); - } - break; - case BuddyResponse::BUDDYRESPONSE_DISCONNECT: - { - lastNotificationWasStatus = FALSE; - numOnlineInNotification = 0; - showNotificationBox(AsciiString::TheEmptyString, TheGameText->fetch("Buddy:MessageDisconnected")); - } - break; - case BuddyResponse::BUDDYRESPONSE_MESSAGE: - { - if ( !wcscmp(resp.arg.message.text, L"I have authorized your request to add me to your list") ) - break; - - if (TheGameSpyInfo->isSavedIgnored(resp.profile)) - { - //DEBUG_CRASH(("Player is ignored!\n")); - break; // no buddy messages from ignored people - } - - // save message for future incarnations of the buddy window - BuddyMessageList *messages = TheGameSpyInfo->getBuddyMessages(); - BuddyMessage message; - message.m_timestamp = resp.arg.message.date; - message.m_senderID = resp.profile; - message.m_recipientID = TheGameSpyInfo->getLocalProfileID(); - message.m_recipientNick = TheGameSpyInfo->getLocalBaseName(); - message.m_message = resp.arg.message.text; - // insert status into box - BuddyInfoMap *m = TheGameSpyInfo->getBuddyMap(); - BuddyInfoMap::iterator senderIt = m->find(message.m_senderID); - AsciiString nick; - if (senderIt != m->end()) - nick = senderIt->second.m_name.str(); - else - nick = resp.arg.message.nick; - message.m_senderNick = nick; - messages->push_back(message); - - DEBUG_LOG(("Inserting buddy chat from '%s'/'%s'\n", nick.str(), resp.arg.message.nick)); - - // put message on screen - insertChat(message); - - // play audio notification - AudioEventRTS buddyMsgAudio("GUIMessageReceived"); - if( TheAudio ) - { - TheAudio->addAudioEvent( &buddyMsgAudio ); - } // end if - - UnicodeString snippet = message.m_message; - while (snippet.getLength() > 11) - { - snippet.removeLastChar(); - } - UnicodeString s; - s.format(TheGameText->fetch("Buddy:MessageNotification"), nick.str(), snippet.str()); - lastNotificationWasStatus = FALSE; - numOnlineInNotification = 0; - showNotificationBox(AsciiString::TheEmptyString, s); - } - break; - case BuddyResponse::BUDDYRESPONSE_REQUEST: - { - // save request for future incarnations of the buddy window - BuddyInfoMap *m = TheGameSpyInfo->getBuddyRequestMap(); - BuddyInfo info; - info.m_countryCode = resp.arg.request.countrycode; - info.m_email = resp.arg.request.email; - info.m_name = resp.arg.request.nick; - info.m_id = resp.profile; - info.m_status = (GPEnum)0; - info.m_statusString = resp.arg.request.text; - (*m)[resp.profile] = info; - - // TODO: put request on screen - updateBuddyInfo(); - // insert status into box - lastNotificationWasStatus = FALSE; - numOnlineInNotification = 0; - showNotificationBox(info.m_name, TheGameText->fetch("Buddy:AddNotification")); - } - break; - case BuddyResponse::BUDDYRESPONSE_STATUS: - { - BuddyInfoMap *m = TheGameSpyInfo->getBuddyMap(); - BuddyInfoMap::const_iterator bit = m->find(resp.profile); - Bool seenPreviously = FALSE; - GPEnum oldStatus = GP_OFFLINE; - GPEnum newStatus = resp.arg.status.status; - if (bit != m->end()) - { - seenPreviously = TRUE; - oldStatus = (*m)[resp.profile].m_status; - } - BuddyInfo info; - info.m_countryCode = resp.arg.status.countrycode; - info.m_email = resp.arg.status.email; - info.m_name = resp.arg.status.nick; - info.m_id = resp.profile; - info.m_status = newStatus; - info.m_statusString = UnicodeString(MultiByteToWideCharSingleLine(resp.arg.status.statusString).c_str()); - info.m_locationString = UnicodeString(MultiByteToWideCharSingleLine(resp.arg.status.location).c_str()); - (*m)[resp.profile] = info; - - updateBuddyInfo(); - PopulateLobbyPlayerListbox(); - RefreshGameListBoxes(); - if ( (newStatus == GP_OFFLINE && seenPreviously) || - (newStatus == GP_ONLINE && (oldStatus == GP_OFFLINE || !seenPreviously)) ) - //if (!info.m_statusString.compareNoCase(L"Offline") || - //!info.m_statusString.compareNoCase(L"Online")) - { - // insert status into box - AsciiString marker; - marker.format("Buddy:%lsNotification", info.m_statusString.str()); - - lastNotificationWasStatus = TRUE; - if (newStatus != GP_OFFLINE) - ++numOnlineInNotification; - - showNotificationBox(info.m_name, TheGameText->fetch(marker)); - } - else if( newStatus == GP_RECV_GAME_INVITE && !seenPreviously) - { - lastNotificationWasStatus = TRUE; - if (newStatus != GP_OFFLINE) - ++numOnlineInNotification; - - showNotificationBox(info.m_name, TheGameText->fetch("Buddy:OnlineNotification")); - } - } - break; - } - } - } - else - { - DEBUG_CRASH(("No buddy message queue!\n")); - } - if(noticeLayout && timeGetTime() > noticeExpires) - { - deleteNotificationBox(); - } -} - -void showNotificationBox( AsciiString nick, UnicodeString message) -{ -// if(!GameSpyIsOverlayOpen(GSOVERLAY_BUDDY)) -// return; - if( !noticeLayout ) - noticeLayout = TheWindowManager->winCreateLayout( "Menus/PopupBuddyListNotification.wnd" ); - noticeLayout->hide( FALSE ); - if (buttonNotificationID == NAMEKEY_INVALID) - { - buttonNotificationID = TheNameKeyGenerator->nameToKey("PopupBuddyListNotification.wnd:ButtonNotification"); - } - GameWindow *win = TheWindowManager->winGetWindowFromId(NULL,buttonNotificationID); - if(!win) - { - deleteNotificationBox(); - return; - } - - if (lastNotificationWasStatus && numOnlineInNotification > 1) - { - message = TheGameText->fetch("Buddy:MultipleOnlineNotification"); - } - - if (nick.isNotEmpty()) - message.format(message, nick.str()); - GadgetButtonSetText(win, message); - //GadgetStaticTextSetText(win, message); - noticeExpires = timeGetTime() + NOTIFICATION_EXPIRES; - noticeLayout->bringForward(); - - AudioEventRTS buttonClick("GUICommunicatorIncoming"); - - if( TheAudio ) - { - TheAudio->addAudioEvent( &buttonClick ); - } // end if - -} - -void deleteNotificationBox( void ) -{ - lastNotificationWasStatus = FALSE; - numOnlineInNotification = 0; - if(noticeLayout) - { - noticeLayout->destroyWindows(); - noticeLayout->deleteInstance(); - noticeLayout = NULL; - } -} - -void PopulateOldBuddyMessages(void) -{ - // show previous messages - BuddyMessageList *messages = TheGameSpyInfo->getBuddyMessages(); - for (BuddyMessageList::iterator mIt = messages->begin(); mIt != messages->end(); ++mIt) - { - BuddyMessage message = *mIt; - insertChat(message); - } -} - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Buddy Overlay */ -//------------------------------------------------------------------------------------------------- -void WOLBuddyOverlayInit( WindowLayout *layout, void *userData ) -{ - parentID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:BuddyMenuParent" ) ); - buttonHideID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ButtonHide" ) ); - buttonAddBuddyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ButtonAdd" ) ); - buttonDeleteBuddyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ButtonDelete" ) ); - //textEntryID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:TextEntryChat" ) ); - //listboxBuddyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ListboxBuddies" ) ); - //listboxChatID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ListboxBuddyChat" ) ); - buttonAcceptBuddyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ButtonYes" ) ); - buttonDenyBuddyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ButtonNo" ) ); - radioButtonBuddiesID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:RadioButtonBuddies" ) ); - radioButtonIgnoreID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:RadioButtonIgnore" ) ); - parentBuddiesID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:BuddiesParent" ) ); - parentIgnoreID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:IgnoreParent" ) ); - listboxIgnoreID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ListboxIgnore" ) ); - - - parent = TheWindowManager->winGetWindowFromId( NULL, parentID ); - buttonHide = TheWindowManager->winGetWindowFromId( parent, buttonHideID); - buttonAddBuddy = TheWindowManager->winGetWindowFromId( parent, buttonAddBuddyID); - buttonDeleteBuddy = TheWindowManager->winGetWindowFromId( parent, buttonDeleteBuddyID); - // textEntry = TheWindowManager->winGetWindowFromId( parent, textEntryID); - //listboxBuddy = TheWindowManager->winGetWindowFromId( parent, listboxBuddyID); - //listboxChat = TheWindowManager->winGetWindowFromId( parent, listboxChatID); - buttonAcceptBuddy = TheWindowManager->winGetWindowFromId( parent, buttonAcceptBuddyID); - buttonDenyBuddy = TheWindowManager->winGetWindowFromId( parent, buttonDenyBuddyID); - radioButtonBuddies = TheWindowManager->winGetWindowFromId( parent, radioButtonBuddiesID); - radioButtonIgnore = TheWindowManager->winGetWindowFromId( parent, radioButtonIgnoreID); - parentBuddies = TheWindowManager->winGetWindowFromId( parent, parentBuddiesID); - parentIgnore = TheWindowManager->winGetWindowFromId( parent, parentIgnoreID); - listboxIgnore = TheWindowManager->winGetWindowFromId( parent, listboxIgnoreID); - - InitBuddyControls(BUDDY_WINDOW_BUDDIES); - - GadgetRadioSetSelection(radioButtonBuddies,FALSE); - parentBuddies->winHide(FALSE); - parentIgnore->winHide(TRUE); - - //GadgetTextEntrySetText(textEntry, UnicodeString.TheEmptyString); - - PopulateOldBuddyMessages(); - - // Show Menu - layout->hide( FALSE ); - - // Set Keyboard to Main Parent - TheWindowManager->winSetFocus( parent ); - - isOverlayActive = true; - updateBuddyInfo(); - -} // WOLBuddyOverlayInit - -//------------------------------------------------------------------------------------------------- -/** WOL Buddy Overlay shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLBuddyOverlayShutdown( WindowLayout *layout, void *userData ) -{ - listboxIgnore = NULL; - - // hide menu - layout->hide( TRUE ); - - // our shutdown is complete - //TheShell->shutdownComplete( layout ); - - isOverlayActive = false; - - InitBuddyControls(BUDDY_RESETALL_CRAP); - -} // WOLBuddyOverlayShutdown - - -//------------------------------------------------------------------------------------------------- -/** WOL Buddy Overlay update method */ -//------------------------------------------------------------------------------------------------- -void WOLBuddyOverlayUpdate( WindowLayout * layout, void *userData) -{ - if (!TheGameSpyBuddyMessageQueue || !TheGameSpyBuddyMessageQueue->isConnected()) - GameSpyCloseOverlay(GSOVERLAY_BUDDY); -}// WOLBuddyOverlayUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Buddy Overlay input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLBuddyOverlayInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonHide, buttonHideID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// WOLBuddyOverlayInput - -//------------------------------------------------------------------------------------------------- -/** WOL Buddy Overlay window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLBuddyOverlaySystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - if(BuddyControlSystem(window, msg, mData1, mData2) == MSG_HANDLED) - { - return MSG_HANDLED; - } - switch( msg ) - { - - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - case GLM_RIGHT_CLICKED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if( controlID == listboxIgnoreID ) - { - RightClickStruct *rc = (RightClickStruct *)mData2; - WindowLayout *rcLayout; - if(rc->pos < 0) - break; - - Bool isBuddy = false, isRequest = false; - GPProfile profileID = (GPProfile)GadgetListBoxGetItemData(control, rc->pos); - UnicodeString nick = GadgetListBoxGetText(control, rc->pos); - BuddyInfoMap *buddies = TheGameSpyInfo->getBuddyMap(); - BuddyInfoMap::iterator bIt; - bIt = buddies->find(profileID); - if (bIt != buddies->end()) - { - isBuddy = true; - } - else - { - buddies = TheGameSpyInfo->getBuddyRequestMap(); - bIt = buddies->find(profileID); - if (bIt != buddies->end()) - { - isRequest = true; - } - else - { - // neither buddy nor request - //break; - } - } - - GadgetListBoxSetSelected(control, rc->pos); - if (isBuddy) - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCBuddiesMenu.wnd")); - else if (isRequest) - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCBuddyRequestMenu.wnd")); - else - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCNonBuddiesMenu.wnd")); - rcMenu = rcLayout->getFirstWindow(); - rcMenu->winGetLayout()->runInit(); - rcMenu->winBringToTop(); - rcMenu->winHide(FALSE); - - - - rcMenu->winSetPosition(rc->mouseX, rc->mouseY); - GameSpyRCMenuData *rcData = NEW GameSpyRCMenuData; - rcData->m_id = profileID; - rcData->m_nick.translate(nick); - rcData->m_itemType = (isBuddy)?ITEM_BUDDY:((isRequest)?ITEM_REQUEST:ITEM_NONBUDDY); - setUnignoreText(rcLayout, rcData->m_nick, rcData->m_id); - rcMenu->winSetUserData((void *)rcData); - TheWindowManager->winSetLoneWindow(rcMenu); - } - break; - } - case GBM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if (controlID == buttonHideID) - { - GameSpyCloseOverlay( GSOVERLAY_BUDDY ); - } - else if (controlID == radioButtonBuddiesID) - { - parentBuddies->winHide(FALSE); - parentIgnore->winHide(TRUE); - } - else if (controlID == radioButtonIgnoreID) - { - parentBuddies->winHide(TRUE); - parentIgnore->winHide(FALSE); - refreshIgnoreList(); - } - else if (controlID == buttonAddBuddyID) - { - /* - UnicodeString uName = GadgetTextEntryGetText(textEntry); - AsciiString aName; - aName.translate(uName); - if (!aName.isEmpty()) - { - TheWOLBuddyList->requestBuddyAdd(aName); - } - GadgetTextEntrySetText(textEntry, UnicodeString::TheEmptyString); - */ - } - else if (controlID == buttonDeleteBuddyID) - { - /* - int selected; - AsciiString selectedName = AsciiString::TheEmptyString; - - GadgetListBoxGetSelected(listbox, &selected); - if (selected >= 0) - selectedName = TheNameKeyGenerator->keyToName((NameKeyType)(int)GadgetListBoxGetItemData(listbox, selected)); - - if (!selectedName.isEmpty()) - { - TheWOLBuddyList->requestBuddyDelete(selectedName); - } - */ - } - break; - }// case GBM_SELECTED: - case GLM_DOUBLE_CLICKED: - { - /* - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if( controlID == listboxBuddyID ) - { - int rowSelected = mData2; - - if (rowSelected >= 0) - { - UnicodeString buddyName; - GameWindow *listboxWindow = TheWindowManager->winGetWindowFromId( parent, listboxBuddyID ); - - // get text of buddy name - buddyName = GadgetListBoxGetText( listboxWindow, rowSelected,0 ); - GPProfile buddyID = (GPProfile)GadgetListBoxGetItemData( listboxWindow, rowSelected, 0 ); - - Int index = -1; - gpGetBuddyIndex(TheGPConnection, buddyID, &index); - if (index >= 0) - { - GPBuddyStatus status; - gpGetBuddyStatus(TheGPConnection, rowSelected, &status); - - UnicodeString string; - string.format(L"To join %s in %hs:", buddyName.str(), status.locationString); - GameSpyAddText(string, GSCOLOR_DEFAULT); - - if (status.status == GP_CHATTING) - { - AsciiString location = status.locationString; - AsciiString val; - location.nextToken(&val, "/"); - location.nextToken(&val, "/"); - location.nextToken(&val, "/"); - - string.format(L" ???"); - if (!val.isEmpty()) - { - Int groupRoom = atoi(val.str()); - if (TheGameSpyChat->getCurrentGroupRoomID() == groupRoom) - { - // already there - string.format(L" nothing"); - GameSpyAddText(string, GSCOLOR_DEFAULT); - } - else - { - GroupRoomMap *rooms = TheGameSpyChat->getGroupRooms(); - if (rooms) - { - Bool needToJoin = true; - GroupRoomMap::iterator it = rooms->find(groupRoom); - if (it != rooms->end()) - { - // he's in a different room - if (TheGameSpyChat->getCurrentGroupRoomID()) - { - string.format(L" leave group room"); - GameSpyAddText(string, GSCOLOR_DEFAULT); - - TheGameSpyChat->leaveRoom(GroupRoom); - } - else if (TheGameSpyGame->isInGame()) - { - if (TheGameSpyGame->isGameInProgress()) - { - string.format(L" can't leave game in progress"); - GameSpyAddText(string, GSCOLOR_DEFAULT); - needToJoin = false; - } - else - { - string.format(L" leave game setup"); - GameSpyAddText(string, GSCOLOR_DEFAULT); - - TheGameSpyChat->leaveRoom(StagingRoom); - TheGameSpyGame->leaveGame(); - } - } - if (needToJoin) - { - string.format(L" join lobby %d", groupRoom); - TheGameSpyChat->joinGroupRoom(groupRoom); - GameSpyAddText(string, GSCOLOR_DEFAULT); - } - } - } - } - } - } - } - else - { - DEBUG_CRASH(("No buddy associated with that ProfileID")); - GameSpyUpdateBuddyOverlay(); - } - } - } - */ - break; - } - - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLBuddyOverlaySystem - -WindowMsgHandledType PopupBuddyNotificationSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - case GWM_CREATE: - { - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GBM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if (controlID == buttonNotificationID) - { - GameSpyOpenOverlay( GSOVERLAY_BUDDY ); - } - break; - } - - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// PopupBuddyNotificationSystem - -/* -static NameKeyType buttonAcceptBuddyID = NAMEKEY_INVALID; -static NameKeyType buttonDenyBuddyID = NAMEKEY_INVALID; -*/ -static NameKeyType buttonAddID = NAMEKEY_INVALID; -static NameKeyType buttonDeleteID = NAMEKEY_INVALID; -static NameKeyType buttonPlayID = NAMEKEY_INVALID; -static NameKeyType buttonIgnoreID = NAMEKEY_INVALID; -static NameKeyType buttonStatsID = NAMEKEY_INVALID; -// Window Pointers ------------------------------------------------------------------------ -//static GameWindow *rCparent = NULL; - - -//------------------------------------------------------------------------------------------------- -/** WOL Buddy Overlay Right Click menu callbacks */ -//------------------------------------------------------------------------------------------------- -void WOLBuddyOverlayRCMenuInit( WindowLayout *layout, void *userData ) -{ - AsciiString controlName; - controlName.format("%s:ButtonAdd",layout->getFilename().str()+6); - buttonAddID = TheNameKeyGenerator->nameToKey( controlName ); - controlName.format("%s:ButtonDelete",layout->getFilename().str()+6); - buttonDeleteID = TheNameKeyGenerator->nameToKey( controlName ); - controlName.format("%s:ButtonPlay",layout->getFilename().str()+6); - buttonPlayID = TheNameKeyGenerator->nameToKey( controlName ); - controlName.format("%s:ButtonIgnore",layout->getFilename().str()+6); - buttonIgnoreID = TheNameKeyGenerator->nameToKey( controlName ); - controlName.format("%s:ButtonStats",layout->getFilename().str()+6); - buttonStatsID = TheNameKeyGenerator->nameToKey( controlName ); -} -static void closeRightClickMenu(GameWindow *win) -{ - - if(win) - { - WindowLayout *winLay = win->winGetLayout(); - if(!winLay) - return; - winLay->destroyWindows(); - winLay->deleteInstance(); - winLay = NULL; - - } -} - -void RequestBuddyAdd(Int profileID, AsciiString nick) -{ - // request to add a buddy - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_ADDBUDDY; - req.arg.addbuddy.id = profileID; - UnicodeString buddyAddstr; - buddyAddstr = TheGameText->fetch("GUI:BuddyAddReq"); - wcsncpy(req.arg.addbuddy.text, buddyAddstr.str(), MAX_BUDDY_CHAT_LEN); - req.arg.addbuddy.text[MAX_BUDDY_CHAT_LEN-1] = 0; - TheGameSpyBuddyMessageQueue->addRequest(req); - - UnicodeString s; - Bool exists = TRUE; - s.format(TheGameText->fetch("Buddy:InviteSent", &exists)); - if (!exists) - { - // no string yet. don't display. - return; - } - - // save message for future incarnations of the buddy window - BuddyMessageList *messages = TheGameSpyInfo->getBuddyMessages(); - BuddyMessage message; - message.m_timestamp = time(NULL); - message.m_senderID = 0; - message.m_senderNick = ""; - message.m_recipientID = TheGameSpyInfo->getLocalProfileID(); - message.m_recipientNick = TheGameSpyInfo->getLocalBaseName(); - message.m_message.format(TheGameText->fetch("Buddy:InviteSentToPlayer"), nick.str()); - - // insert status into box - messages->push_back(message); - - DEBUG_LOG(("Inserting buddy add request\n")); - - // put message on screen - insertChat(message); - - // play audio notification - AudioEventRTS buddyMsgAudio("GUIMessageReceived"); - if( TheAudio ) - { - TheAudio->addAudioEvent( &buddyMsgAudio ); - } // end if - - lastNotificationWasStatus = FALSE; - numOnlineInNotification = 0; - showNotificationBox(AsciiString::TheEmptyString, s); -} - -WindowMsgHandledType WOLBuddyOverlayRCMenuSystem( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 ) -{ - - switch( msg ) - { - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - rcMenu = NULL; - break; - } // case GWM_DESTROY: - - case GGM_CLOSE: - { - closeRightClickMenu(window); - //rcMenu = NULL; - break; - } - - - case GBM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - GameSpyRCMenuData *rcData = (GameSpyRCMenuData*)window->winGetUserData(); - if(!rcData) - break; - DEBUG_ASSERTCRASH(rcData, ("WOLBuddyOverlayRCMenuSystem GBM_SELECTED:: we're attempting to read the GameSpyRCMenuData from the window, but the data's not there")); - GPProfile profileID = rcData->m_id; - AsciiString nick = rcData->m_nick; - - Bool isBuddy = false, isRequest = false; - Bool isGameSpyUser = profileID > 0; - if (rcData->m_itemType == ITEM_BUDDY) - isBuddy = TRUE; - else if (rcData->m_itemType == ITEM_REQUEST) - isRequest = TRUE; - - if(rcData) - { - delete rcData; - rcData = NULL; - } - window->winSetUserData(NULL); - //DEBUG_ASSERTCRASH(profileID > 0, ("Bad profile ID in user data!")); - - if( controlID == buttonAddID ) - { - if(!isGameSpyUser) - break; - DEBUG_LOG(("ButtonAdd was pushed\n")); - if (isRequest) - { - // ok the request - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_OKADD; - req.arg.profile.id = profileID; - TheGameSpyBuddyMessageQueue->addRequest(req); - - BuddyInfoMap *m = TheGameSpyInfo->getBuddyRequestMap(); - m->erase( profileID ); - // if the profile ID is not from a buddy and we're okaying his request, then - // request to add him to our list automatically CLH 2-18-03 - if(!TheGameSpyInfo->isBuddy(profileID)) - { - RequestBuddyAdd(profileID, nick); - } - updateBuddyInfo(); - } - else if (!isBuddy) - { - RequestBuddyAdd(profileID, nick); - } - } - else if( controlID == buttonDeleteID ) - { - if(!isGameSpyUser) - break; - if (isBuddy) - { - // delete the buddy - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_DELBUDDY; - req.arg.profile.id = profileID; - TheGameSpyBuddyMessageQueue->addRequest(req); - } - else - { - // delete the request - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_DENYADD; - req.arg.profile.id = profileID; - TheGameSpyBuddyMessageQueue->addRequest(req); - BuddyInfoMap *m = TheGameSpyInfo->getBuddyRequestMap(); - m->erase( profileID ); - } - BuddyInfoMap *buddies = (isBuddy)?TheGameSpyInfo->getBuddyMap():TheGameSpyInfo->getBuddyRequestMap(); - buddies->erase(profileID); - updateBuddyInfo(); - DEBUG_LOG(("ButtonDelete was pushed\n")); - PopulateLobbyPlayerListbox(); - } - else if( controlID == buttonPlayID ) - { - DEBUG_LOG(("buttonPlayID was pushed\n")); - } - else if( controlID == buttonIgnoreID ) - { - DEBUG_LOG(("%s is isGameSpyUser %d", nick.str(), isGameSpyUser)); - if( isGameSpyUser ) - { - if(TheGameSpyInfo->isSavedIgnored(profileID)) - { - TheGameSpyInfo->removeFromSavedIgnoreList(profileID); - } - else - { - TheGameSpyInfo->addToSavedIgnoreList(profileID, nick); - } - } - else - { - if(TheGameSpyInfo->isIgnored(nick)) - { - TheGameSpyInfo->removeFromIgnoreList(nick); - } - else - { - TheGameSpyInfo->addToIgnoreList(nick); - } - } - updateBuddyInfo(); - refreshIgnoreList(); - // repopulate our player listboxes now - PopulateLobbyPlayerListbox(); - } - else if( controlID == buttonStatsID ) - { - DEBUG_LOG(("buttonStatsID was pushed\n")); - GameSpyCloseOverlay(GSOVERLAY_PLAYERINFO); - SetLookAtPlayer(profileID,nick ); - GameSpyOpenOverlay(GSOVERLAY_PLAYERINFO); - PSRequest req; - req.requestType = PSRequest::PSREQUEST_READPLAYERSTATS; - req.player.id = profileID; - TheGameSpyPSMessageQueue->addRequest(req); - } - closeRightClickMenu(window); - break; - } - default: - return MSG_IGNORED; - - }//Switch - return MSG_HANDLED; -} - - -void setUnignoreText( WindowLayout *layout, AsciiString nick, GPProfile id) -{ - AsciiString controlName; - controlName.format("%s:ButtonIgnore",layout->getFilename().str()+6); - NameKeyType ID = TheNameKeyGenerator->nameToKey( controlName ); - GameWindow *win = TheWindowManager->winGetWindowFromId(layout->getFirstWindow(), ID); - if(win) - { - if(TheGameSpyInfo->isSavedIgnored(id) || TheGameSpyInfo->isIgnored(nick)) - GadgetButtonSetText(win, TheGameText->fetch("GUI:Unignore")); - } -} - -void refreshIgnoreList( void ) -{ - - - SavedIgnoreMap tempMap; - tempMap = TheGameSpyInfo->returnSavedIgnoreList(); - SavedIgnoreMap::iterator it = tempMap.begin(); - GadgetListBoxReset(listboxIgnore); - while(it != tempMap.end()) - { - UnicodeString name; - name.translate(it->second); - Int pos = GadgetListBoxAddEntryText(listboxIgnore, name, GameMakeColor(255,100,100,255),-1); - GadgetListBoxSetItemData(listboxIgnore, (void *)it->first,pos ); - ++it; - } - IgnoreList tempList; - tempList = TheGameSpyInfo->returnIgnoreList(); - IgnoreList::iterator iListIt = tempList.begin(); - while( iListIt != tempList.end()) - { - AsciiString aName = *iListIt; - UnicodeString name; - name.translate(aName); - Int pos = GadgetListBoxAddEntryText(listboxIgnore, name, GameMakeColor(255,100,100,255),-1); - GadgetListBoxSetItemData(listboxIgnore, 0,pos ); - ++iListIt; - } - -// -// GPProfile profileID = 0; -// PlayerInfoMap::iterator it = TheGameSpyInfo->getPlayerInfoMap()->find(aName); -// if (it != TheGameSpyInfo->getPlayerInfoMap()->end()) -// profileID = it->second.m_profileID; - -} diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLCustomScoreScreen.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLCustomScoreScreen.cpp deleted file mode 100644 index a045c27f255..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLCustomScoreScreen.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLCustomScoreScreen.cpp -// Author: Matt Campbell, December 2001 -// Description: Custom match score screen -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Lib/BaseType.h" -#include "Common/GameEngine.h" -#include "Common/NameKeyGenerator.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetTextEntry.h" -#include "Common/GlobalData.h" -//#include "GameNetwork/WOL.h" -//#include "GameNetwork/WOLmenus.h" - - - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentWOLCustomScoreID = NAMEKEY_INVALID; -static NameKeyType buttonDisconnectID = NAMEKEY_INVALID; -static NameKeyType buttonLobbyID = NAMEKEY_INVALID; - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentWOLCustomScore = NULL; -static GameWindow *buttonDisconnect = NULL; -static GameWindow *buttonLobby = NULL; - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Status Menu */ -//------------------------------------------------------------------------------------------------- -void WOLCustomScoreScreenInit( WindowLayout *layout, void *userData ) -{ - parentWOLCustomScoreID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLCustomScoreScreen.wnd:WOLCustomScoreScreenParent" ) ); - buttonDisconnectID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLCustomScoreScreen.wnd:ButtonDisconnect" ) ); - buttonLobbyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLCustomScoreScreen.wnd:ButtonLobby" ) ); - parentWOLCustomScore = TheWindowManager->winGetWindowFromId( NULL, parentWOLCustomScoreID ); - buttonDisconnect = TheWindowManager->winGetWindowFromId( NULL, buttonDisconnectID); - buttonLobby = TheWindowManager->winGetWindowFromId( NULL, buttonLobbyID); - - /* - if (WOL::TheWOL->getState() == WOL::WOLAPI_FATAL_ERROR) - { - // We can get to the score screen even though we've been disconnected. Just hide - // any buttons that lead back into WOL. - buttonLobby->winHide( TRUE ); - } - */ - - // Show Menu - layout->hide( FALSE ); - - // Set Keyboard to Main Parent - TheWindowManager->winSetFocus( parentWOLCustomScore ); -} // WOLCustomScoreScreenInit - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLCustomScoreScreenShutdown( WindowLayout *layout, void *userData ) -{ - // hide menu - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout ); -} // WOLCustomScoreScreenShutdown - - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLCustomScoreScreenUpdate( WindowLayout * layout, void *userData) -{ - /* - if (WOL::TheWOL) - WOL::TheWOL->update(); - */ -}// WOLCustomScoreScreenUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLCustomScoreScreenInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonDisconnect, buttonDisconnectID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// WOLCustomScoreScreenInput - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLCustomScoreScreenSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - - switch( msg ) - { - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're given the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - case GBM_SELECTED: - { - /* - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if ( controlID == buttonDisconnectID ) - { - if (WOL::TheWOL->setState( WOL::WOLAPI_FATAL_ERROR )) - { - WOL::TheWOL->addCommand( WOL::WOLCOMMAND_RESET ); // don't display an error, log out, or anything - } - - } //if ( controlID == buttonDisconnect ) - else if ( controlID == buttonLobbyID ) - { - if (WOL::TheWOL->getState() != WOL::WOLAPI_FATAL_ERROR) - { - WOL::TheWOL->setScreen(WOL::WOLAPI_MENU_CUSTOMLOBBY); - WOL::TheWOL->setGameMode(WOL::WOLTYPE_CUSTOM); - WOL::TheWOL->setState( WOL::WOLAPI_LOBBY ); - WOL::TheWOL->addCommand( WOL::WOLCOMMAND_REFRESH_CHANNELS ); - } - else - { - } - } //if ( controlID == buttonDisconnect ) - */ - break; - }// case GBM_SELECTED: - - case GEM_EDIT_DONE: - { - break; - } - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLCustomScoreScreenSystem diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp deleted file mode 100644 index 43d42d7e109..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp +++ /dev/null @@ -1,2887 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLGameSetupMenu.cpp -// Author: Matt Campbell, December 2001 -// Description: WOL Game Options Menu -/////////////////////////////////////////////////////////////////////////////////////// - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "Common/GameState.h" -#include "GameClient/GameText.h" -#include "Common/MultiplayerSettings.h" -#include "Common/PlayerTemplate.h" -#include "Common/CustomMatchPreferences.h" -#include "GameClient/AnimateWindowManager.h" -#include "GameClient/InGameUI.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Mouse.h" -#include "GameClient/Gadget.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetComboBox.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/GadgetPushButton.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/GadgetCheckBox.h" -#include "GameClient/MapUtil.h" -#include "GameClient/EstablishConnectionsMenu.h" -#include "GameClient/GameWindowTransitions.h" -#include "GameNetwork/GameSpy/LobbyUtils.h" - -#include "GameNetwork/GameSpy/BuddyDefs.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PersistentStorageDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameNetwork/NAT.h" -#include "GameNetwork/GUIUtil.h" -#include "GameNetwork/GameSpy/GSConfig.h" - -void WOLDisplaySlotList( void ); - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -extern std::list TheLobbyQueuedUTMs; -extern void MapSelectorTooltip(GameWindow *window, WinInstanceData *instData, UnsignedInt mouse); - - -#if defined(_DEBUG) || defined(_INTERNAL) -extern Bool g_debugSlots; -void slotListDebugLog(const char *fmt, ...) -{ - static char buf[1024]; - va_list va; - va_start( va, fmt ); - _vsnprintf(buf, 1024, fmt, va ); - va_end( va ); - buf[1023] = 0; - - DEBUG_LOG(("%s", buf)); - if (g_debugSlots) - { - UnicodeString msg; - msg.translate(buf); - TheGameSpyInfo->addText(msg, GameSpyColor[GSCOLOR_DEFAULT], NULL); - } -} -#define SLOTLIST_DEBUG_LOG(x) slotListDebugLog x -#else -#define SLOTLIST_DEBUG_LOG(x) DEBUG_LOG(x) -#endif - -void SendStatsToOtherPlayers(const GameInfo *game) -{ - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "STATS/"; - AsciiString fullStr; - PSPlayerStats fullStats = TheGameSpyPSMessageQueue->findPlayerStatsByID(TheGameSpyInfo->getLocalProfileID()); - PSPlayerStats subStats; - subStats.id = fullStats.id; - subStats.wins = fullStats.wins; - subStats.losses = fullStats.losses; - subStats.discons = fullStats.discons; - subStats.desyncs = fullStats.desyncs; - subStats.games = fullStats.games; - subStats.locale = fullStats.locale; - subStats.gamesAsRandom = fullStats.gamesAsRandom; - GetAdditionalDisconnectsFromUserFile(&subStats); - fullStr.format("%d %s", TheGameSpyInfo->getLocalProfileID(), TheGameSpyPSMessageQueue->formatPlayerKVPairs( subStats )); - req.options = fullStr.str(); - - Int localIndex = game->getLocalSlotNum(); - for (Int i=0; igetConstSlot(i); - if (slot->isHuman() && i != localIndex) - { - AsciiString hostName; - hostName.translate(slot->getName()); - req.nick = hostName.str(); - DEBUG_LOG(("SendStatsToOtherPlayers() - sending to '%s', data of\n\t'%s'\n", hostName.str(), req.options.c_str())); - TheGameSpyPeerMessageQueue->addRequest(req); - } - } -} - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -static Bool isShuttingDown = false; -static Bool buttonPushed = false; -static char *nextScreen = NULL; -static Bool raiseMessageBoxes = false; -static Bool launchGameNext = FALSE; - -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentWOLGameSetupID = NAMEKEY_INVALID; - -static NameKeyType comboBoxPlayerID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; - -static NameKeyType staticTextPlayerID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; - -static NameKeyType buttonAcceptID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; - -static NameKeyType comboBoxColorID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; - -static NameKeyType comboBoxPlayerTemplateID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; - -static NameKeyType comboBoxTeamID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; -//static NameKeyType buttonStartPositionID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, -// NAMEKEY_INVALID,NAMEKEY_INVALID, -// NAMEKEY_INVALID,NAMEKEY_INVALID, -// NAMEKEY_INVALID,NAMEKEY_INVALID }; - -static NameKeyType buttonMapStartPositionID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; -static NameKeyType genericPingWindowID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; - -static NameKeyType textEntryChatID = NAMEKEY_INVALID; -static NameKeyType textEntryMapDisplayID = NAMEKEY_INVALID; -static NameKeyType buttonBackID = NAMEKEY_INVALID; -static NameKeyType buttonStartID = NAMEKEY_INVALID; -static NameKeyType buttonEmoteID = NAMEKEY_INVALID; -static NameKeyType buttonSelectMapID = NAMEKEY_INVALID; -static NameKeyType windowMapID = NAMEKEY_INVALID; - -static NameKeyType windowMapSelectMapID = NAMEKEY_INVALID; -static NameKeyType checkBoxUseStatsID = NAMEKEY_INVALID; -static NameKeyType checkBoxLimitSuperweaponsID = NAMEKEY_INVALID; -static NameKeyType comboBoxStartingCashID = NAMEKEY_INVALID; -static NameKeyType checkBoxLimitArmiesID = NAMEKEY_INVALID; - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentWOLGameSetup = NULL; -static GameWindow *buttonBack = NULL; -static GameWindow *buttonStart = NULL; -static GameWindow *buttonSelectMap = NULL; -static GameWindow *buttonEmote = NULL; -static GameWindow *textEntryChat = NULL; -static GameWindow *textEntryMapDisplay = NULL; -static GameWindow *windowMap = NULL; -static GameWindow *checkBoxUseStats = NULL; -static GameWindow *checkBoxLimitSuperweapons = NULL; -static GameWindow *comboBoxStartingCash = NULL; -static GameWindow *checkBoxLimitArmies = NULL; - -static GameWindow *comboBoxPlayer[MAX_SLOTS] = {NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL }; -static GameWindow *staticTextPlayer[MAX_SLOTS] = {NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL }; -static GameWindow *buttonAccept[MAX_SLOTS] = {NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL }; - -static GameWindow *comboBoxColor[MAX_SLOTS] = {NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL }; - -static GameWindow *comboBoxPlayerTemplate[MAX_SLOTS] = {NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL }; - -static GameWindow *comboBoxTeam[MAX_SLOTS] = {NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL }; - -//static GameWindow *buttonStartPosition[MAX_SLOTS] = {NULL,NULL,NULL,NULL, -// NULL,NULL,NULL,NULL }; -// -static GameWindow *buttonMapStartPosition[MAX_SLOTS] = {NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL }; - -static GameWindow *genericPingWindow[MAX_SLOTS] = {NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL }; - -static const Image *pingImages[3] = { NULL, NULL, NULL }; - -WindowLayout *WOLMapSelectLayout = NULL; - -void PopBackToLobby( void ) -{ - // delete TheNAT, its no good for us anymore. - delete TheNAT; - TheNAT = NULL; - - if (TheGameSpyInfo) // this can be blown away by a disconnect on the map transfer screen - { - TheGameSpyInfo->getCurrentStagingRoom()->reset(); - TheGameSpyInfo->leaveStagingRoom(); - //TheGameSpyInfo->joinBestGroupRoom(); - } - - DEBUG_LOG(("PopBackToLobby() - parentWOLGameSetup is %X\n", parentWOLGameSetup)); - if (parentWOLGameSetup) - { - nextScreen = "Menus/WOLCustomLobby.wnd"; - TheShell->pop(); - } -} - -void updateMapStartSpots( GameInfo *myGame, GameWindow *buttonMapStartPositions[], Bool onLoadScreen = FALSE ); -void positionStartSpots( GameInfo *myGame, GameWindow *buttonMapStartPositions[], GameWindow *mapWindow); -void positionStartSpots(AsciiString mapName, GameWindow *buttonMapStartPositions[], GameWindow *mapWindow); -void WOLPositionStartSpots( void ) -{ - GameWindow *win = windowMap; - if (WOLMapSelectLayout != NULL) { - win = TheWindowManager->winGetWindowFromId(NULL, windowMapSelectMapID); - - // get the controls. - NameKeyType listboxMapID = TheNameKeyGenerator->nameToKey( AsciiString("WOLMapSelectMenu.wnd:ListboxMap") ); - GameWindow *listboxMap = TheWindowManager->winGetWindowFromId( NULL, listboxMapID ); - - if (listboxMap != NULL) { - Int selected; - UnicodeString map; - - // get the selected index - GadgetListBoxGetSelected( listboxMap, &selected ); - - if( selected != -1 ) - { - - // get text of the map to load - map = GadgetListBoxGetText( listboxMap, selected, 0 ); - - - // set the map name in the global data map name - AsciiString asciiMap; - const char *mapFname = (const char *)GadgetListBoxGetItemData( listboxMap, selected ); - DEBUG_ASSERTCRASH(mapFname, ("No map item data")); - if (mapFname) { - asciiMap = mapFname; - } else { - asciiMap.translate( map ); - } - - positionStartSpots(asciiMap, buttonMapStartPosition, win); - } - } - - } else { - DEBUG_ASSERTCRASH(win != NULL, ("no map preview window")); - positionStartSpots( TheGameSpyInfo->getCurrentStagingRoom(), buttonMapStartPosition, win); - } -} -static void savePlayerInfo( void ) -{ - if (TheGameSpyGame) - { - Int slotNum = TheGameSpyGame->getLocalSlotNum(); - if (slotNum >= 0) - { - GameSpyGameSlot *slot = TheGameSpyGame->getGameSpySlot(slotNum); - if (slot) - { - // save off some prefs - CustomMatchPreferences pref; - pref.setPreferredColor(slot->getColor()); - pref.setPreferredFaction(slot->getPlayerTemplate()); - if (TheGameSpyGame->amIHost()) - { - pref.setPreferredMap(TheGameSpyGame->getMap()); - pref.setSuperweaponRestricted( TheGameSpyGame->getSuperweaponRestriction() != 0 ); - pref.setStartingCash( TheGameSpyGame->getStartingCash() ); - } - pref.write(); - } - } - } -} - -// Tooltips ------------------------------------------------------------------------------- - -static void playerTooltip(GameWindow *window, - WinInstanceData *instData, - UnsignedInt mouse) -{ - Int slotIdx = -1; - for (Int i=0; isetCursorTooltip( UnicodeString::TheEmptyString, -1, NULL, 1.5f ); - return; - } - - GameSpyStagingRoom *game = TheGameSpyInfo->getCurrentStagingRoom(); - if (!game) - { - TheMouse->setCursorTooltip( UnicodeString::TheEmptyString, -1, NULL, 1.5f ); - return; - } - - GameSpyGameSlot *slot = game->getGameSpySlot(slotIdx); - if (!slot || !slot->isHuman()) - { - TheMouse->setCursorTooltip( UnicodeString::TheEmptyString, -1, NULL, 1.5f ); - return; - } - - // for tooltip, we want: - // * player name - // * ping - // * locale - // * win/loss history - // * discons/desyncs as one var - // * favorite army - // in that order. got it? good. - - UnicodeString uName = slot->getName(); - - AsciiString aName; - aName.translate(uName); - PlayerInfoMap::iterator pmIt = TheGameSpyInfo->getPlayerInfoMap()->find(aName); - if (pmIt == TheGameSpyInfo->getPlayerInfoMap()->end()) - { - TheMouse->setCursorTooltip( uName, -1, NULL, 1.5f ); - return; - } - Int profileID = pmIt->second.m_profileID; - - PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(profileID); - if (stats.id == 0) - { - TheMouse->setCursorTooltip( uName, -1, NULL, 1.5f ); - return; - } - - Bool isLocalPlayer = slot == game->getGameSpySlot(game->getLocalSlotNum()); - - AsciiString localeIdentifier; - localeIdentifier.format("WOL:Locale%2.2d", stats.locale); - UnicodeString playerInfo; - Int totalWins = 0, totalLosses = 0, totalDiscons = 0; - PerGeneralMap::iterator it; - - for (it = stats.wins.begin(); it != stats.wins.end(); ++it) - { - totalWins += it->second; - } - for (it = stats.losses.begin(); it != stats.losses.end(); ++it) - { - totalLosses += it->second; - } - for (it = stats.discons.begin(); it != stats.discons.end(); ++it) - { - totalDiscons += it->second; - } - for (it = stats.desyncs.begin(); it != stats.desyncs.end(); ++it) - { - totalDiscons += it->second; - } - UnicodeString favoriteSide; - Int numGames = 0; - Int favorite = 0; - for(it = stats.games.begin(); it != stats.games.end(); ++it) - { - if(it->second >= numGames) - { - numGames = it->second; - favorite = it->first; - } - } - if(numGames == 0) - favoriteSide = TheGameText->fetch("GUI:None"); - else if( stats.gamesAsRandom >= numGames ) - favoriteSide = TheGameText->fetch("GUI:Random"); - else - { - const PlayerTemplate *fac = ThePlayerTemplateStore->getNthPlayerTemplate(favorite); - if (fac) - { - AsciiString side; - side.format("SIDE:%s", fac->getSide().str()); - - favoriteSide = TheGameText->fetch(side); - } - } - - playerInfo.format(TheGameText->fetch("TOOLTIP:StagingPlayerInfo"), - TheGameText->fetch(localeIdentifier).str(), - slot->getPingAsInt(), - totalWins, totalLosses, totalDiscons, - favoriteSide.str()); - - UnicodeString tooltip = UnicodeString::TheEmptyString; - if (isLocalPlayer) - { - tooltip.format(TheGameText->fetch("TOOLTIP:LocalPlayer"), uName.str()); - } - else - { - // not us - if (TheGameSpyInfo->getBuddyMap()->find(profileID) != TheGameSpyInfo->getBuddyMap()->end()) - { - // buddy - tooltip.format(TheGameText->fetch("TOOLTIP:BuddyPlayer"), uName.str()); - } - else - { - if (profileID) - { - // non-buddy profiled player - tooltip.format(TheGameText->fetch("TOOLTIP:ProfiledPlayer"), uName.str()); - } - else - { - // non-profiled player - tooltip.format(TheGameText->fetch("TOOLTIP:GenericPlayer"), uName.str()); - } - } - } - - tooltip.concat(playerInfo); - - TheMouse->setCursorTooltip( tooltip, -1, NULL, 1.5f ); // the text and width are the only params used. the others are the default values. -} - -void gameAcceptTooltip(GameWindow *window, WinInstanceData *instData, UnsignedInt mouse) -{ - Int x, y; - x = LOLONGTOSHORT(mouse); - y = HILONGTOSHORT(mouse); - - Int winPosX, winPosY, winWidth, winHeight; - - window->winGetScreenPosition(&winPosX, &winPosY); - - window->winGetSize(&winWidth, &winHeight); - - if ((x > winPosX && x < (winPosX + winWidth)) && (y > winPosY && y < (winPosY + winHeight))) - { - TheMouse->setCursorTooltip(TheGameText->fetch("TOOLTIP:GameAcceptance"), -1, NULL); - } -} - -void pingTooltip(GameWindow *window, WinInstanceData *instData, UnsignedInt mouse) -{ - Int x, y; - x = LOLONGTOSHORT(mouse); - y = HILONGTOSHORT(mouse); - - - Int winPosX, winPosY, winWidth, winHeight; - - window->winGetScreenPosition(&winPosX, &winPosY); - - window->winGetSize(&winWidth, &winHeight); - - if ((x > winPosX && x < (winPosX + winWidth)) && (y > winPosY && y < (winPosY + winHeight))) - { - TheMouse->setCursorTooltip(TheGameText->fetch("TOOLTIP:ConnectionSpeed"), -1, NULL); - } -} - -//external declarations of the Gadgets the callbacks can use -GameWindow *listboxGameSetupChat = NULL; -NameKeyType listboxGameSetupChatID = NAMEKEY_INVALID; - -static void handleColorSelection(int index) -{ - GameWindow *combo = comboBoxColor[index]; - Int color, selIndex; - GadgetComboBoxGetSelectedPos(combo, &selIndex); - color = (Int)GadgetComboBoxGetItemData(combo, selIndex); - - GameInfo *myGame = TheGameSpyInfo->getCurrentStagingRoom(); - - if (myGame) - { - GameSlot * slot = myGame->getSlot(index); - if (color == slot->getColor()) - return; - - if (color >= -1 && color < TheMultiplayerSettings->getNumColors()) - { - Bool colorAvailable = TRUE; - if(color != -1 ) - { - for(Int i=0; i getSlot(i); - if(color == checkSlot->getColor() && slot != checkSlot) - { - colorAvailable = FALSE; - break; - } - } - } - if(!colorAvailable) - return; - } - - slot->setColor(color); - - if (TheGameSpyInfo->amIHost()) - { - // send around a new slotlist - TheGameSpyInfo->setGameOptions(); - WOLDisplaySlotList(); - } - else - { - // request the color from the host - if (!slot->isPlayer(TheGameSpyInfo->getLocalName())) - return; - - AsciiString options; - options.format("Color=%d", color); - AsciiString hostName; - hostName.translate(myGame->getSlot(0)->getName()); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "REQ/"; - req.nick = hostName.str(); - req.options = options.str(); - TheGameSpyPeerMessageQueue->addRequest(req); - } - } -} - -static void handlePlayerTemplateSelection(int index) -{ - GameWindow *combo = comboBoxPlayerTemplate[index]; - Int playerTemplate, selIndex; - GadgetComboBoxGetSelectedPos(combo, &selIndex); - playerTemplate = (Int)GadgetComboBoxGetItemData(combo, selIndex); - GameInfo *myGame = TheGameSpyInfo->getCurrentStagingRoom(); - - if (myGame) - { - GameSlot * slot = myGame->getSlot(index); - if (playerTemplate == slot->getPlayerTemplate()) - return; - - Int oldTemplate = slot->getPlayerTemplate(); - slot->setPlayerTemplate(playerTemplate); - - if (oldTemplate == PLAYERTEMPLATE_OBSERVER) - { - // was observer, so populate color & team with all, and enable - GadgetComboBoxSetSelectedPos(comboBoxColor[index], 0); - GadgetComboBoxSetSelectedPos(comboBoxTeam[index], 0); - slot->setStartPos(-1); - } - else if (playerTemplate == PLAYERTEMPLATE_OBSERVER) - { - // is becoming observer, so populate color & team with random only, and disable - GadgetComboBoxSetSelectedPos(comboBoxColor[index], 0); - GadgetComboBoxSetSelectedPos(comboBoxTeam[index], 0); - slot->setStartPos(-1); - } - - - if (TheGameSpyInfo->amIHost()) - { - // send around a new slotlist - myGame->resetAccepted(); - TheGameSpyInfo->setGameOptions(); - WOLDisplaySlotList(); - } - else - { - // request the playerTemplate from the host - AsciiString options; - options.format("PlayerTemplate=%d", playerTemplate); - AsciiString hostName; - hostName.translate(myGame->getSlot(0)->getName()); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "REQ/"; - req.nick = hostName.str(); - req.options = options.str(); - TheGameSpyPeerMessageQueue->addRequest(req); - } - } -} - - -static void handleStartPositionSelection(Int player, int startPos) -{ - GameSpyStagingRoom *myGame = TheGameSpyInfo->getCurrentStagingRoom(); - - if (myGame) - { - GameSpyGameSlot * slot = myGame->getGameSpySlot(player); - if (!slot) - return; - - if (startPos == slot->getStartPos()) - return; - Bool skip = FALSE; - if (startPos < 0) - { - skip = TRUE; - } - - if(!skip) - { - Bool isAvailable = TRUE; - for(Int i = 0; i < MAX_SLOTS; ++i) - { - if(i != player && myGame->getSlot(i)->getStartPos() == startPos) - { - isAvailable = FALSE; - break; - } - } - if( !isAvailable ) - return; - } - slot->setStartPos(startPos); - - if (myGame->amIHost()) - { - // send around a new slotlist - myGame->resetAccepted(); - TheGameSpyInfo->setGameOptions(); - WOLDisplaySlotList(); - } - else - { - // request the color from the host - if (AreSlotListUpdatesEnabled()) - { - // request the playerTemplate from the host - AsciiString options; - options.format("StartPos=%d", slot->getStartPos()); - AsciiString hostName; - hostName.translate(myGame->getSlot(0)->getName()); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "REQ/"; - req.nick = hostName.str(); - req.options = options.str(); - TheGameSpyPeerMessageQueue->addRequest(req); - - } - } - } -} - - - -static void handleTeamSelection(int index) -{ - GameWindow *combo = comboBoxTeam[index]; - Int team, selIndex; - GadgetComboBoxGetSelectedPos(combo, &selIndex); - team = (Int)GadgetComboBoxGetItemData(combo, selIndex); - GameInfo *myGame = TheGameSpyInfo->getCurrentStagingRoom(); - - if (myGame) - { - GameSlot * slot = myGame->getSlot(index); - if (team == slot->getTeamNumber()) - return; - - slot->setTeamNumber(team); - - if (TheGameSpyInfo->amIHost()) - { - // send around a new slotlist - myGame->resetAccepted(); - TheGameSpyInfo->setGameOptions(); - WOLDisplaySlotList(); - } - else - { - // request the team from the host - AsciiString options; - options.format("Team=%d", team); - AsciiString hostName; - hostName.translate(myGame->getSlot(0)->getName()); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "REQ/"; - req.nick = hostName.str(); - req.options = options.str(); - TheGameSpyPeerMessageQueue->addRequest(req); - } - } -} - -static void handleStartingCashSelection() -{ - GameInfo *myGame = TheGameSpyInfo->getCurrentStagingRoom(); - - if (myGame) - { - Int selIndex; - GadgetComboBoxGetSelectedPos(comboBoxStartingCash, &selIndex); - - Money startingCash; - startingCash.deposit( (UnsignedInt)GadgetComboBoxGetItemData( comboBoxStartingCash, selIndex ), FALSE ); - myGame->setStartingCash( startingCash ); - myGame->resetAccepted(); - - if (myGame->amIHost()) - { - // send around the new data - TheGameSpyInfo->setGameOptions(); - WOLDisplaySlotList();// Update the accepted button UI - } - } -} - -static void handleLimitSuperweaponsClick() -{ - GameInfo *myGame = TheGameSpyInfo->getCurrentStagingRoom(); - - if (myGame) - { - // At the moment, 1 and 0 are the only choices supported in the GUI, though the system could - // support more. - if ( GadgetCheckBoxIsChecked( checkBoxLimitSuperweapons ) ) - { - myGame->setSuperweaponRestriction( 1 ); - } - else - { - myGame->setSuperweaponRestriction( 0 ); - } - myGame->resetAccepted(); - - if (myGame->amIHost()) - { - // send around a new slotlist - TheGameSpyInfo->setGameOptions(); - WOLDisplaySlotList();// Update the accepted button UI - } - } -} - - -static void StartPressed(void) -{ - Bool isReady = TRUE; - Bool allHaveMap = TRUE; - Int playerCount = 0; - Int humanCount = 0; - GameSpyStagingRoom *myGame = TheGameSpyInfo->getCurrentStagingRoom(); - if (!myGame) - return; - - // see if everyone's accepted and count the number of players in the game - UnicodeString mapDisplayName; - const MapMetaData *mapData = TheMapCache->findMap( myGame->getMap() ); - Bool willTransfer = TRUE; - if (mapData) - { - mapDisplayName.format(L"%ls", mapData->m_displayName.str()); - willTransfer = !mapData->m_isOfficial; - } - else - { - mapDisplayName.format(L"%hs", myGame->getMap().str()); - willTransfer = WouldMapTransfer(myGame->getMap()); - } - for( int i = 0; i < MAX_SLOTS; i++ ) - { - if ((myGame->getSlot(i)->isAccepted() == FALSE) && (myGame->getSlot(i)->isHuman() == TRUE)) - { - isReady = FALSE; - if (!myGame->getSlot(i)->hasMap() && !willTransfer) - { - UnicodeString msg; - msg.format(TheGameText->fetch("GUI:PlayerNoMap"), myGame->getSlot(i)->getName().str(), mapDisplayName.str()); - TheGameSpyInfo->addText(msg, GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - allHaveMap = FALSE; - } - } - if(myGame->getSlot(i)->isOccupied() && myGame->getSlot(i)->getPlayerTemplate() != PLAYERTEMPLATE_OBSERVER) - { - if (myGame->getSlot(i)->isHuman()) - humanCount++; - playerCount++; - } - } - - // Check for too many players - const MapMetaData *md = TheMapCache->findMap( myGame->getMap() ); - if (!md || md->m_numPlayers < playerCount) - { - if (myGame->amIHost()) - { - UnicodeString text; - text.format(TheGameText->fetch("LAN:TooManyPlayers"), (md)?md->m_numPlayers:0); - TheGameSpyInfo->addText(text, GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - } - return; - } - - // Check for observer + AI players - if (TheGlobalData->m_netMinPlayers && !humanCount) - { - if (myGame->amIHost()) - { - UnicodeString text = TheGameText->fetch("GUI:NeedHumanPlayers"); - TheGameSpyInfo->addText(text, GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - } - return; - } - - // Check for too few players - if (playerCount < TheGlobalData->m_netMinPlayers) - { - if (myGame->amIHost()) - { - UnicodeString text; - text.format(TheGameText->fetch("LAN:NeedMorePlayers"),playerCount); - TheGameSpyInfo->addText(text, GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - } - return; - } - - // Check for too few teams - int numRandom = 0; - std::set teams; - for (i=0; igetSlot(i); - if (slot && slot->isOccupied() && slot->getPlayerTemplate() != PLAYERTEMPLATE_OBSERVER) - { - if (slot->getTeamNumber() >= 0) - { - teams.insert(slot->getTeamNumber()); - } - else - { - ++numRandom; - } - } - } - if (numRandom + teams.size() < TheGlobalData->m_netMinPlayers) - { - if (myGame->amIHost()) - { - UnicodeString text; - text.format(TheGameText->fetch("LAN:NeedMoreTeams")); - TheGameSpyInfo->addText(text, GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - } - return; - } - - if (numRandom + teams.size() < 2) - { - UnicodeString text; - text.format(TheGameText->fetch("GUI:SandboxMode")); - TheGameSpyInfo->addText(text, GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - } - - if(isReady) - { - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_STARTGAME; - TheGameSpyPeerMessageQueue->addRequest(req); - - SendStatsToOtherPlayers(myGame); - - // we've started, there's no going back - // i.e. disable the back button. - buttonBack->winEnable(FALSE); - GameWindow *buttonBuddy = TheWindowManager->winGetWindowFromId(NULL, NAMEKEY("GameSpyGameOptionsMenu.wnd:ButtonCommunicator")); - if (buttonBuddy) - buttonBuddy->winEnable(FALSE); - GameSpyCloseOverlay(GSOVERLAY_BUDDY); - - *TheGameSpyGame = *myGame; - TheGameSpyGame->startGame(0); - } - else if (allHaveMap) - { - TheGameSpyInfo->addText(TheGameText->fetch("GUI:NotifiedStartIntent"), GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMROOM; - req.UTM.isStagingRoom = TRUE; - req.id = "HWS/"; - req.options = "true"; - TheGameSpyPeerMessageQueue->addRequest(req); - } - -}//void StartPressed(void) - -//------------------------------------------------------------------------------------------------- -/** Update options on screen */ -//------------------------------------------------------------------------------------------------- -void WOLDisplayGameOptions( void ) -{ - GameSpyStagingRoom *theGame = TheGameSpyInfo->getCurrentStagingRoom(); - if (!parentWOLGameSetup || !theGame) - return; - - const GameSlot *localSlot = NULL; - if (theGame->getLocalSlotNum() >= 0) - localSlot = theGame->getConstSlot(theGame->getLocalSlotNum()); - - const MapMetaData *md = TheMapCache->findMap(TheGameSpyInfo->getCurrentStagingRoom()->getMap()); - if (md && localSlot && localSlot->hasMap()) - { - GadgetStaticTextSetText(textEntryMapDisplay, md->m_displayName); - } - else - { - AsciiString s = TheGameSpyInfo->getCurrentStagingRoom()->getMap(); - if (s.reverseFind('\\')) - { - s = s.reverseFind('\\') + 1; - } - UnicodeString mapDisplay; - mapDisplay.translate(s); - GadgetStaticTextSetText(textEntryMapDisplay, mapDisplay); - } - WOLPositionStartSpots(); - updateMapStartSpots(TheGameSpyInfo->getCurrentStagingRoom(), buttonMapStartPosition); - - //If our display does not match the current state of game settings, update the checkbox. - Bool isUsingStats = TheGameSpyInfo->getCurrentStagingRoom()->getUseStats() ? TRUE : FALSE; - if (GadgetCheckBoxIsChecked(checkBoxUseStats) != isUsingStats) - { - GadgetCheckBoxSetChecked(checkBoxUseStats, isUsingStats); - checkBoxUseStats->winSetTooltip( TheGameText->fetch( isUsingStats ? "TOOLTIP:UseStatsOn" : "TOOLTIP:UseStatsOff" ) ); - } - - Bool oldFactionsOnly = theGame->oldFactionsOnly(); - if (GadgetCheckBoxIsChecked(checkBoxLimitArmies) != oldFactionsOnly) - { - GadgetCheckBoxSetChecked(checkBoxLimitArmies, oldFactionsOnly); - // Repopulate the lists of available armies, since the old list is now wrong - for (Int i = 0; i < MAX_SLOTS; i++) - { - PopulatePlayerTemplateComboBox(i, comboBoxPlayerTemplate, theGame, theGame->getAllowObservers() ); - - // Make sure selections are up to date on all machines - handlePlayerTemplateSelection(i) ; - } - } - - // Note: must check if checkbox is already correct to avoid infinite recursion - Bool limitSuperweapons = (theGame->getSuperweaponRestriction() != 0); - if ( limitSuperweapons != GadgetCheckBoxIsChecked(checkBoxLimitSuperweapons)) - GadgetCheckBoxSetChecked( checkBoxLimitSuperweapons, limitSuperweapons ); - - Int itemCount = GadgetComboBoxGetLength(comboBoxStartingCash); - for ( Int index = 0; index < itemCount; index++ ) - { - Int value = (Int)GadgetComboBoxGetItemData(comboBoxStartingCash, index); - if ( value == theGame->getStartingCash().countMoney() ) - { - // Note: must check if combobox is already correct to avoid infinite recursion - Int selectedIndex; - GadgetComboBoxGetSelectedPos( comboBoxStartingCash, &selectedIndex ); - if ( index != selectedIndex ) - GadgetComboBoxSetSelectedPos(comboBoxStartingCash, index, TRUE); - - break; - } - } - - DEBUG_ASSERTCRASH( index < itemCount, ("Could not find new starting cash amount %d in list", theGame->getStartingCash().countMoney() ) ); -} - - -// ----------------------------------------------------------------------------------------- -// The Bad munkee slot list displaying function -//------------------------------------------------------------------------------------------------- -void WOLDisplaySlotList( void ) -{ - if (!parentWOLGameSetup || !TheGameSpyInfo->getCurrentStagingRoom()) - return; - - GameSpyStagingRoom *game = TheGameSpyInfo->getCurrentStagingRoom(); - if (!game->isInGame()) - return; - - DEBUG_ASSERTCRASH(!game->getConstSlot(0)->isOpen(), ("Open host!")); - - UpdateSlotList( game, comboBoxPlayer, comboBoxColor, - comboBoxPlayerTemplate, comboBoxTeam, buttonAccept, buttonStart, buttonMapStartPosition ); - - WOLDisplayGameOptions(); - - for (Int i=0; igetGameSpySlot(i); - if (slot && slot->isHuman()) - { - if (i == game->getLocalSlotNum()) - { - // set up my own ping... - slot->setPingString(TheGameSpyInfo->getPingString()); - } - - if (genericPingWindow[i]) - { - genericPingWindow[i]->winHide(FALSE); - Int ping = slot->getPingAsInt(); - if (ping < TheGameSpyConfig->getPingCutoffGood()) - { - genericPingWindow[i]->winSetEnabledImage(0, pingImages[0]); - } - else if (ping < TheGameSpyConfig->getPingCutoffBad()) - { - genericPingWindow[i]->winSetEnabledImage(0, pingImages[1]); - } - else - { - genericPingWindow[i]->winSetEnabledImage(0, pingImages[2]); - } - } - } - else - { - if (genericPingWindow[i]) - genericPingWindow[i]->winHide(TRUE); - } - } -} - -//------------------------------------------------------------------------------------------------- -/** Initialize the Gadgets Options Menu */ -//------------------------------------------------------------------------------------------------- -void InitWOLGameGadgets( void ) -{ - GameSpyStagingRoom *theGameInfo = TheGameSpyInfo->getCurrentStagingRoom(); - pingImages[0] = TheMappedImageCollection->findImageByName("Ping03"); - pingImages[1] = TheMappedImageCollection->findImageByName("Ping02"); - pingImages[2] = TheMappedImageCollection->findImageByName("Ping01"); - DEBUG_ASSERTCRASH(pingImages[0], ("Can't find ping image!")); - DEBUG_ASSERTCRASH(pingImages[1], ("Can't find ping image!")); - DEBUG_ASSERTCRASH(pingImages[2], ("Can't find ping image!")); - - //Initialize the gadget IDs - parentWOLGameSetupID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:GameSpyGameOptionsMenuParent" ) ); - buttonBackID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:ButtonBack" ) ); - buttonStartID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:ButtonStart" ) ); - textEntryChatID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:TextEntryChat" ) ); - textEntryMapDisplayID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:TextEntryMapDisplay" ) ); - listboxGameSetupChatID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:ListboxChatWindowGameSpyGameSetup" ) ); - buttonEmoteID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:ButtonEmote" ) ); - buttonSelectMapID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:ButtonSelectMap" ) ); - checkBoxUseStatsID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:CheckBoxUseStats" ) ); - windowMapID = TheNameKeyGenerator->nameToKey( AsciiString( "GameSpyGameOptionsMenu.wnd:MapWindow" ) ); - checkBoxLimitSuperweaponsID = TheNameKeyGenerator->nameToKey(AsciiString("GameSpyGameOptionsMenu.wnd:CheckboxLimitSuperweapons")); - comboBoxStartingCashID = TheNameKeyGenerator->nameToKey(AsciiString("GameSpyGameOptionsMenu.wnd:ComboBoxStartingCash")); - checkBoxLimitArmiesID = TheNameKeyGenerator->nameToKey(AsciiString("GameSpyGameOptionsMenu.wnd:CheckBoxLimitArmies")); - windowMapSelectMapID = TheNameKeyGenerator->nameToKey(AsciiString("WOLMapSelectMenu.wnd:WinMapPreview")); - - NameKeyType staticTextTitleID = NAMEKEY("GameSpyGameOptionsMenu.wnd:StaticTextGameName"); - - // Initialize the pointers to our gadgets - parentWOLGameSetup = TheWindowManager->winGetWindowFromId( NULL, parentWOLGameSetupID ); - buttonEmote = TheWindowManager->winGetWindowFromId( parentWOLGameSetup,buttonEmoteID ); - buttonSelectMap = TheWindowManager->winGetWindowFromId( parentWOLGameSetup,buttonSelectMapID ); - checkBoxUseStats = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, checkBoxUseStatsID ); - buttonStart = TheWindowManager->winGetWindowFromId( parentWOLGameSetup,buttonStartID ); - buttonBack = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, buttonBackID); - listboxGameSetupChat = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, listboxGameSetupChatID ); - textEntryChat = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, textEntryChatID ); - textEntryMapDisplay = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, textEntryMapDisplayID ); - windowMap = TheWindowManager->winGetWindowFromId( parentWOLGameSetup,windowMapID ); - DEBUG_ASSERTCRASH(windowMap, ("Could not find the parentWOLGameSetup.wnd:MapWindow" )); - - checkBoxLimitSuperweapons = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, checkBoxLimitSuperweaponsID ); - DEBUG_ASSERTCRASH(windowMap, ("Could not find the GameSpyGameOptionsMenu.wnd:CheckboxLimitSuperweapons" )); - comboBoxStartingCash = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, comboBoxStartingCashID ); - DEBUG_ASSERTCRASH(windowMap, ("Could not find the GameSpyGameOptionsMenu.wnd:ComboBoxStartingCash" )); - PopulateStartingCashComboBox( comboBoxStartingCash, TheGameSpyGame ); - checkBoxLimitArmies = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, checkBoxLimitArmiesID ); - DEBUG_ASSERTCRASH(windowMap, ("Could not find the GameSpyGameOptionsMenu.wnd:CheckBoxLimitArmies" )); - - // Limit Armies can ONLY be set in the Host Game window (PopupHostGame.wnd) - checkBoxLimitArmies->winEnable( false ); - // Ditto use stats - checkBoxUseStats->winEnable( false ); - Int isUsingStats = TheGameSpyGame->getUseStats(); - GadgetCheckBoxSetChecked(checkBoxUseStats, isUsingStats ); - checkBoxUseStats->winSetTooltip( TheGameText->fetch( isUsingStats ? "TOOLTIP:UseStatsOn" : "TOOLTIP:UseStatsOff" ) ); - - if ( !TheGameSpyGame->amIHost() ) - { - checkBoxLimitSuperweapons->winEnable( false ); - comboBoxStartingCash->winEnable( false ); - NameKeyType labelID = TheNameKeyGenerator->nameToKey(AsciiString("GameSpyGameOptionsMenu.wnd:StartingCashLabel")); - TheWindowManager->winGetWindowFromId(parentWOLGameSetup, labelID)->winEnable( FALSE ); - } - - if (isUsingStats) - { - // Recorded stats games can never limit superweapons, limit armies, or have inflated starting cash. - // This should probably be enforced at the gamespy level as well, to prevent expoits. - checkBoxLimitSuperweapons->winEnable( FALSE ); - comboBoxStartingCash->winEnable( FALSE ); - checkBoxLimitArmies->winEnable( FALSE ); - NameKeyType labelID = TheNameKeyGenerator->nameToKey(AsciiString("GameSpyGameOptionsMenu.wnd:StartingCashLabel")); - TheWindowManager->winGetWindowFromId(parentWOLGameSetup, labelID)->winEnable( FALSE ); - } - - //Added By Sadullah Nader - //Tooltip Function set - windowMap->winSetTooltipFunc(MapSelectorTooltip); - // - - GameWindow *staticTextTitle = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, staticTextTitleID ); - if (staticTextTitle) - { - GadgetStaticTextSetText(staticTextTitle, TheGameSpyGame->getGameName()); - } - - if (!theGameInfo) - { - DEBUG_CRASH(("No staging room!")); - return; - } - - for (Int i = 0; i < MAX_SLOTS; i++) - { - AsciiString tmpString; - tmpString.format("GameSpyGameOptionsMenu.wnd:ComboBoxPlayer%d", i); - comboBoxPlayerID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - comboBoxPlayer[i] = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, comboBoxPlayerID[i] ); - GadgetComboBoxReset(comboBoxPlayer[i]); - comboBoxPlayer[i]->winSetTooltipFunc(playerTooltip); - - tmpString.format("GameSpyGameOptionsMenu.wnd:StaticTextPlayer%d", i); - staticTextPlayerID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - staticTextPlayer[i] = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, staticTextPlayerID[i] ); - staticTextPlayer[i]->winSetTooltipFunc(playerTooltip); - if (TheGameSpyInfo->amIHost()) - staticTextPlayer[i]->winHide(TRUE); - - if(i==0 && TheGameSpyInfo->amIHost()) - { - UnicodeString uName; - uName.translate(TheGameSpyInfo->getLocalName()); - GadgetComboBoxAddEntry(comboBoxPlayer[i],uName,GameSpyColor[GSCOLOR_PLAYER_OWNER]); - GadgetComboBoxSetSelectedPos(comboBoxPlayer[0],0); - } - else - { - GadgetComboBoxAddEntry(comboBoxPlayer[i],TheGameText->fetch("GUI:Open"),GameSpyColor[GSCOLOR_PLAYER_NORMAL]); - GadgetComboBoxAddEntry(comboBoxPlayer[i],TheGameText->fetch("GUI:Closed"),GameSpyColor[GSCOLOR_PLAYER_NORMAL]); - GadgetComboBoxAddEntry(comboBoxPlayer[i],TheGameText->fetch("GUI:EasyAI"),GameSpyColor[GSCOLOR_PLAYER_NORMAL]); - GadgetComboBoxAddEntry(comboBoxPlayer[i],TheGameText->fetch("GUI:MediumAI"),GameSpyColor[GSCOLOR_PLAYER_NORMAL]); - GadgetComboBoxAddEntry(comboBoxPlayer[i],TheGameText->fetch("GUI:HardAI"),GameSpyColor[GSCOLOR_PLAYER_NORMAL]); - GadgetComboBoxSetSelectedPos(comboBoxPlayer[i],0); - } - - tmpString.format("GameSpyGameOptionsMenu.wnd:ComboBoxColor%d", i); - comboBoxColorID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - comboBoxColor[i] = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, comboBoxColorID[i] ); - DEBUG_ASSERTCRASH(comboBoxColor[i], ("Could not find the comboBoxColor[%d]",i )); - PopulateColorComboBox(i, comboBoxColor, theGameInfo); - GadgetComboBoxSetSelectedPos(comboBoxColor[i], 0); - - tmpString.format("GameSpyGameOptionsMenu.wnd:ComboBoxPlayerTemplate%d", i); - comboBoxPlayerTemplateID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - comboBoxPlayerTemplate[i] = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, comboBoxPlayerTemplateID[i] ); - DEBUG_ASSERTCRASH(comboBoxPlayerTemplate[i], ("Could not find the comboBoxPlayerTemplate[%d]",i )); - PopulatePlayerTemplateComboBox(i, comboBoxPlayerTemplate, theGameInfo, theGameInfo->getAllowObservers() ); - - // add tooltips to the player template combobox and listbox - comboBoxPlayerTemplate[i]->winSetTooltipFunc(playerTemplateComboBoxTooltip); - GadgetComboBoxGetListBox(comboBoxPlayerTemplate[i])->winSetTooltipFunc(playerTemplateListBoxTooltip); - - tmpString.format("GameSpyGameOptionsMenu.wnd:ComboBoxTeam%d", i); - comboBoxTeamID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - comboBoxTeam[i] = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, comboBoxTeamID[i] ); - DEBUG_ASSERTCRASH(comboBoxTeam[i], ("Could not find the comboBoxTeam[%d]",i )); - PopulateTeamComboBox(i, comboBoxTeam, theGameInfo); - - tmpString.format("GameSpyGameOptionsMenu.wnd:ButtonAccept%d", i); - buttonAcceptID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - buttonAccept[i] = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, buttonAcceptID[i] ); - DEBUG_ASSERTCRASH(buttonAccept[i], ("Could not find the buttonAccept[%d]",i )); - buttonAccept[i]->winSetTooltipFunc(gameAcceptTooltip); - - tmpString.format("GameSpyGameOptionsMenu.wnd:GenericPing%d", i); - genericPingWindowID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - genericPingWindow[i] = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, genericPingWindowID[i] ); - DEBUG_ASSERTCRASH(genericPingWindow[i], ("Could not find the genericPingWindow[%d]",i )); - genericPingWindow[i]->winSetTooltipFunc(pingTooltip); - -// tmpString.format("GameSpyGameOptionsMenu.wnd:ButtonStartPosition%d", i); -// buttonStartPositionID[i] = TheNameKeyGenerator->nameToKey( tmpString ); -// buttonStartPosition[i] = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, buttonStartPositionID[i] ); -// DEBUG_ASSERTCRASH(buttonStartPosition[i], ("Could not find the ButtonStartPosition[%d]",i )); - - tmpString.format("GameSpyGameOptionsMenu.wnd:ButtonMapStartPosition%d", i); - buttonMapStartPositionID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - buttonMapStartPosition[i] = TheWindowManager->winGetWindowFromId( parentWOLGameSetup, buttonMapStartPositionID[i] ); - DEBUG_ASSERTCRASH(buttonMapStartPosition[i], ("Could not find the ButtonMapStartPosition[%d]",i )); - -// if (buttonStartPosition[i]) -// buttonStartPosition[i]->winHide(TRUE); - - if(i !=0 && buttonAccept[i]) - buttonAccept[i]->winHide(TRUE); - } - - if( buttonAccept[0] ) - buttonAccept[0]->winEnable(TRUE); - - if (buttonBack != NULL) - { - buttonBack->winEnable(TRUE); - } - //GadgetButtonSetEnabledColor(buttonAccept[0], GameSpyColor[GSCOLOR_ACCEPT_TRUE]); -} - -void DeinitWOLGameGadgets( void ) -{ - parentWOLGameSetup = NULL; - buttonEmote = NULL; - buttonSelectMap = NULL; - buttonStart = NULL; - buttonBack = NULL; - listboxGameSetupChat = NULL; - textEntryChat = NULL; - textEntryMapDisplay = NULL; - windowMap = NULL; - checkBoxUseStats = NULL; - checkBoxLimitSuperweapons = NULL; - comboBoxStartingCash = NULL; - -// GameWindow *staticTextTitle = NULL; - for (Int i = 0; i < MAX_SLOTS; i++) - { - comboBoxPlayer[i] = NULL; - staticTextPlayer[i] = NULL; - comboBoxColor[i] = NULL; - comboBoxPlayerTemplate[i] = NULL; - comboBoxTeam[i] = NULL; - buttonAccept[i] = NULL; -// buttonStartPosition[i] = NULL; - buttonMapStartPosition[i] = NULL; - genericPingWindow[i] = NULL; - } -} - -static Bool initDone = false; -UnsignedInt lastSlotlistTime = 0; -UnsignedInt enterTime = 0; -Bool initialAcceptEnable = FALSE; -//------------------------------------------------------------------------------------------------- -/** Initialize the Lan Game Options Menu */ -//------------------------------------------------------------------------------------------------- -void WOLGameSetupMenuInit( WindowLayout *layout, void *userData ) -{ - if (TheGameSpyGame && TheGameSpyGame->isGameInProgress()) - { - TheGameSpyGame->setGameInProgress(FALSE); - - // check if we were disconnected - Int disconReason; - if (TheGameSpyInfo->isDisconnectedAfterGameStart(&disconReason)) - { - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", disconReason); - UnicodeString title, body; - title = TheGameText->fetch( "GUI:GSErrorTitle" ); - body = TheGameText->fetch( disconMunkee ); - GameSpyCloseAllOverlays(); - GSMessageBoxOk( title, body ); - TheGameSpyInfo->reset(); - DEBUG_LOG(("WOLGameSetupMenuInit() - game was in progress, and we were disconnected, so pop immediate back to main menu\n")); - TheShell->popImmediate(); - return; - } - - // If we init while the game is in progress, we are really returning to the menu - // after the game. So, we pop the menu and go back to the lobby. Whee! - DEBUG_LOG(("WOLGameSetupMenuInit() - game was in progress, so pop immediate back to lobby\n")); - TheShell->popImmediate(); - if (TheGameSpyPeerMessageQueue && TheGameSpyPeerMessageQueue->isConnected()) - { - DEBUG_LOG(("We're still connected, so pushing back on the lobby\n")); - TheShell->push("Menus/WOLCustomLobby.wnd", TRUE); - } - return; - } - TheGameSpyInfo->setCurrentGroupRoom(0); - - if (TheNAT != NULL) { - delete TheNAT; - TheNAT = NULL; - } - - nextScreen = NULL; - buttonPushed = false; - isShuttingDown = false; - launchGameNext = FALSE; - - //initialize the gadgets - EnableSlotListUpdates(FALSE); - InitWOLGameGadgets(); - EnableSlotListUpdates(TRUE); - TheGameSpyInfo->registerTextWindow(listboxGameSetupChat); - - //The dialog needs to react differently depending on whether it's the host or not. - TheMapCache->updateCache(); - GameSpyStagingRoom *game = TheGameSpyInfo->getCurrentStagingRoom(); - GameSpyGameSlot *hostSlot = game->getGameSpySlot(0); - hostSlot->setAccept(); - if (TheGameSpyInfo->amIHost()) - { - OptionPreferences natPref; - CustomMatchPreferences customPref; - hostSlot->setColor( customPref.getPreferredColor() ); - hostSlot->setPlayerTemplate( customPref.getPreferredFaction() ); - hostSlot->setNATBehavior((FirewallHelperClass::FirewallBehaviorType)natPref.getFirewallBehavior()); - hostSlot->setPingString(TheGameSpyInfo->getPingString()); - game->setMap(customPref.getPreferredMap()); - - // Recorded stats games can never limit superweapons, limit armies, or have inflated starting cash. - // This should probably be enforced at the gamespy level as well, to prevent expoits. - Int isUsingStats = TheGameSpyGame->getUseStats(); - game->setStartingCash( isUsingStats? TheMultiplayerSettings->getDefaultStartingMoney() : customPref.getStartingCash() ); - game->setSuperweaponRestriction( isUsingStats? 0 : customPref.getSuperweaponRestricted() ? 1 : 0 ); - if (isUsingStats) - game->setOldFactionsOnly( 0 ); - - //game->setOldFactionsOnly( customPref.getFactionsLimited() ); - if ( game->oldFactionsOnly() ) - { - // Make sure host follows the old factions only restrictions! - const PlayerTemplate *fac = ThePlayerTemplateStore->getNthPlayerTemplate(hostSlot->getPlayerTemplate()); - - if ( fac != NULL && !fac->isOldFaction() ) - { - hostSlot->setPlayerTemplate( PLAYERTEMPLATE_RANDOM ); - } - } - - for (Int i=1; igetGameSpySlot(i); - slot->setState( SLOT_OPEN ); - } - - AsciiString lowerMap = customPref.getPreferredMap(); - lowerMap.toLower(); - std::map::iterator it = TheMapCache->find(lowerMap); - if (it != TheMapCache->end()) - { - hostSlot->setMapAvailability(TRUE); - game->setMapCRC( it->second.m_CRC ); - game->setMapSize( it->second.m_filesize ); - - game->adjustSlotsForMap(); // BGC- adjust the slots for the new map. - } - - - WOLDisplaySlotList(); - WOLDisplayGameOptions(); - } - else - { - OptionPreferences natPref; - CustomMatchPreferences customPref; - AsciiString options; - PeerRequest req; - UnicodeString uName = hostSlot->getName(); - AsciiString aName; - aName.translate(uName); - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "REQ/"; - req.nick = aName.str(); - options.format("PlayerTemplate=%d", customPref.getPreferredFaction()); - req.options = options.str(); - TheGameSpyPeerMessageQueue->addRequest(req); - options.format("Color=%d", customPref.getPreferredColor()); - req.options = options.str(); - TheGameSpyPeerMessageQueue->addRequest(req); - options.format("NAT=%d", natPref.getFirewallBehavior()); - req.options = options.str(); - TheGameSpyPeerMessageQueue->addRequest(req); - options.format("Ping=%s", TheGameSpyInfo->getPingString().str()); - req.options = options.str(); - TheGameSpyPeerMessageQueue->addRequest(req); - - game->setMapCRC( game->getMapCRC() ); // force a recheck - game->setMapSize( game->getMapSize() ); // of if we have the map - - for (Int i = 0; i < MAX_SLOTS; ++i) - { - //I'm a client, disable the controls I can't touch. - comboBoxPlayer[i]->winEnable(FALSE); - - comboBoxColor[i]->winEnable(FALSE); - comboBoxPlayerTemplate[i]->winEnable(FALSE); - comboBoxTeam[i]->winEnable(FALSE); -// buttonStartPosition[i]->winEnable(FALSE); - buttonMapStartPosition[i]->winEnable(FALSE); - - } - buttonStart->winSetText(TheGameText->fetch("GUI:Accept")); - buttonStart->winEnable( FALSE ); - buttonSelectMap->winEnable( FALSE ); - checkBoxLimitSuperweapons->winEnable( FALSE ); // Can look but only host can touch - comboBoxStartingCash->winEnable( FALSE ); // Ditto - initialAcceptEnable = FALSE; - } - - // Show the Menu - layout->hide( FALSE ); - - // Make sure the text fields are clear - GadgetListBoxReset( listboxGameSetupChat ); - GadgetTextEntrySetText(textEntryChat, UnicodeString::TheEmptyString); - - initDone = true; - TheGameSpyInfo->setGameOptions(); - //TheShell->registerWithAnimateManager(parentWOLGameSetup, WIN_ANIMATION_SLIDE_TOP, TRUE); - WOLPositionStartSpots(); - - lastSlotlistTime = 0; - enterTime = timeGetTime(); - - // Set Keyboard to chat entry - TheWindowManager->winSetFocus( textEntryChat ); - raiseMessageBoxes = true; - TheTransitionHandler->setGroup("GameSpyGameOptionsMenuFade"); -}// void WOLGameSetupMenuInit( WindowLayout *layout, void *userData ) - -//------------------------------------------------------------------------------------------------- -/** This is called when a shutdown is complete for this menu */ -//------------------------------------------------------------------------------------------------- -static void shutdownComplete( WindowLayout *layout ) -{ - - isShuttingDown = false; - - // hide the layout - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout, (nextScreen != NULL) ); - - if (nextScreen != NULL) - { - if (!TheGameSpyPeerMessageQueue || !TheGameSpyPeerMessageQueue->isConnected()) - { - DEBUG_LOG(("GameSetup shutdownComplete() - skipping push because we're disconnected\n")); - } - else - { - TheShell->push(nextScreen); - } - } - - /* - if (launchGameNext) - { - TheGameSpyGame->launchGame(); - TheGameSpyInfo->leaveStagingRoom(); - } - */ - - nextScreen = NULL; - -} // end if - -//------------------------------------------------------------------------------------------------- -/** GameSpy Game Options menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLGameSetupMenuShutdown( WindowLayout *layout, void *userData ) -{ - TheGameSpyInfo->unregisterTextWindow(listboxGameSetupChat); - - if( WOLMapSelectLayout ) - { - WOLMapSelectLayout->destroyWindows(); - WOLMapSelectLayout->deleteInstance(); - WOLMapSelectLayout = NULL; - } - parentWOLGameSetup = NULL; - EnableSlotListUpdates(FALSE); - DeinitWOLGameGadgets(); - if (TheEstablishConnectionsMenu != NULL) - { - TheEstablishConnectionsMenu->endMenu(); - } - initDone = false; - - isShuttingDown = true; - - // if we are shutting down for an immediate pop, skip the animations - Bool popImmediate = *(Bool *)userData; - if( popImmediate ) - { - - shutdownComplete( layout ); - return; - - } //end if - - TheShell->reverseAnimatewindow(); - - RaiseGSMessageBox(); - TheTransitionHandler->reverse("GameSpyGameOptionsMenuFade"); -} // void WOLGameSetupMenuShutdown( WindowLayout *layout, void *userData ) - -static void fillPlayerInfo(const PeerResponse *resp, PlayerInfo *info) -{ - info->m_name = resp->nick.c_str(); - info->m_profileID = resp->player.profileID; - info->m_flags = resp->player.flags; - info->m_wins = resp->player.wins; - info->m_losses = resp->player.losses; - info->m_locale = resp->locale.c_str(); - info->m_rankPoints= resp->player.rankPoints; - info->m_side = resp->player.side; - info->m_preorder = resp->player.preorder; -} - -//------------------------------------------------------------------------------------------------- -/** Lan Game Options menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLGameSetupMenuUpdate( WindowLayout * layout, void *userData) -{ - // We'll only be successful if we've requested to - if(isShuttingDown && TheShell->isAnimFinished() && TheTransitionHandler->isFinished()) - { - shutdownComplete(layout); - return; - } - - if (raiseMessageBoxes) - { - RaiseGSMessageBox(); - raiseMessageBoxes = false; - } - - if (TheShell->isAnimFinished() && !buttonPushed && TheGameSpyPeerMessageQueue) - { - HandleBuddyResponses(); - HandlePersistentStorageResponses(); - - if (TheGameSpyGame && TheGameSpyGame->isGameInProgress()) - { - if (TheGameSpyInfo->isDisconnectedAfterGameStart(NULL)) - { - return; // already been disconnected, so don't worry. - } - - Int allowedMessages = TheGameSpyInfo->getMaxMessagesPerUpdate(); - Bool sawImportantMessage = FALSE; - PeerResponse resp; - while (allowedMessages-- && !sawImportantMessage && TheGameSpyPeerMessageQueue->getResponse( resp )) - { - switch (resp.peerResponseType) - { - case PeerResponse::PEERRESPONSE_DISCONNECT: - { - sawImportantMessage = TRUE; - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", resp.discon.reason); - - // check for scorescreen - NameKeyType listboxChatWindowScoreScreenID = NAMEKEY("ScoreScreen.wnd:ListboxChatWindowScoreScreen"); - GameWindow *listboxChatWindowScoreScreen = TheWindowManager->winGetWindowFromId( NULL, listboxChatWindowScoreScreenID ); - if (listboxChatWindowScoreScreen) - { - GadgetListBoxAddEntryText(listboxChatWindowScoreScreen, TheGameText->fetch(disconMunkee), - GameSpyColor[GSCOLOR_DEFAULT], -1); - } - else - { - // still ingame - TheInGameUI->message(disconMunkee); - } - TheGameSpyInfo->markAsDisconnectedAfterGameStart(resp.discon.reason); - } - } - } - - return; // if we're in game, all we care about is if we've been disconnected from the chat server - } - - Bool isHosting = TheGameSpyInfo->amIHost(); // only while in game setup screen - isHosting = isHosting || (TheGameSpyGame && TheGameSpyGame->isInGame() && TheGameSpyGame->amIHost()); // while in game - if (!isHosting && !lastSlotlistTime && timeGetTime() > enterTime + 10000) - { - // don't do this if we're disconnected - if (TheGameSpyPeerMessageQueue->isConnected()) - { - // haven't seen ourselves - buttonPushed = true; - DEBUG_LOG(("Haven't seen ourselves in slotlist\n")); - if (TheGameSpyGame) - TheGameSpyGame->reset(); - TheGameSpyInfo->leaveStagingRoom(); - //TheGameSpyInfo->joinBestGroupRoom(); - GSMessageBoxOk(TheGameText->fetch("GUI:HostLeftTitle"), TheGameText->fetch("GUI:HostLeft")); - nextScreen = "Menus/WOLCustomLobby.wnd"; - TheShell->pop(); - } - return; - } - - if (TheNAT != NULL) { - NATStateType NATState = TheNAT->update(); - if (NATState == NATSTATE_DONE) - { - //launchGameNext = TRUE; - //TheShell->pop(); - TheGameSpyGame->launchGame(); - if (TheGameSpyInfo) // this can be blown away by a disconnect on the map transfer screen - TheGameSpyInfo->leaveStagingRoom(); - return; - } - else if (NATState == NATSTATE_FAILED) - { - // Just back out. This cleans up some slot list problems - buttonPushed = true; - - // delete TheNAT, its no good for us anymore. - delete TheNAT; - TheNAT = NULL; - - TheGameSpyInfo->getCurrentStagingRoom()->reset(); - TheGameSpyInfo->leaveStagingRoom(); - //TheGameSpyInfo->joinBestGroupRoom(); - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:NATNegotiationFailed")); - nextScreen = "Menus/WOLCustomLobby.wnd"; - TheShell->pop(); - return; - } - } - - PeerResponse resp; - - Int allowedMessages = TheGameSpyInfo->getMaxMessagesPerUpdate(); - Bool sawImportantMessage = FALSE; - while (allowedMessages-- && !sawImportantMessage) - { - - if (!TheLobbyQueuedUTMs.empty()) - { - DEBUG_LOG(("Got response from queued lobby UTM list\n")); - resp = TheLobbyQueuedUTMs.front(); - TheLobbyQueuedUTMs.pop_front(); - } - else if (TheGameSpyPeerMessageQueue->getResponse( resp )) - { - DEBUG_LOG(("Got response from message queue\n")); - } - else - { - break; - } - switch (resp.peerResponseType) - { - case PeerResponse::PEERRESPONSE_FAILEDTOHOST: - { - // oops - we've not heard from the qr server. bail. - TheGameSpyInfo->addText(TheGameText->fetch("GUI:GSFailedToHost"), GameSpyColor[GSCOLOR_DEFAULT], NULL); - } - break; - case PeerResponse::PEERRESPONSE_GAMESTART: - { - sawImportantMessage = TRUE; - GameSpyStagingRoom *myGame = TheGameSpyInfo->getCurrentStagingRoom(); - if (!myGame || !myGame->isInGame()) - break; - - if (!TheGameSpyGame) - break; - - SendStatsToOtherPlayers(TheGameSpyGame); - - // we've started, there's no going back - // i.e. disable the back button. - buttonBack->winEnable(FALSE); - GameWindow *buttonBuddy = TheWindowManager->winGetWindowFromId(NULL, NAMEKEY("GameSpyGameOptionsMenu.wnd:ButtonCommunicator")); - if (buttonBuddy) - buttonBuddy->winEnable(FALSE); - GameSpyCloseOverlay(GSOVERLAY_BUDDY); - - *TheGameSpyGame = *myGame; - TheGameSpyGame->startGame(0); - } - break; - case PeerResponse::PEERRESPONSE_PLAYERCHANGEDFLAGS: - { - PlayerInfo p; - fillPlayerInfo(&resp, &p); - TheGameSpyInfo->updatePlayerInfo(p); - WOLDisplaySlotList(); - } - break; - case PeerResponse::PEERRESPONSE_PLAYERINFO: - { - PlayerInfo p; - fillPlayerInfo(&resp, &p); - TheGameSpyInfo->updatePlayerInfo(p); - WOLDisplaySlotList(); - // send out new slotlist if I'm host - TheGameSpyInfo->setGameOptions(); - } - break; - case PeerResponse::PEERRESPONSE_PLAYERJOIN: - { - if (resp.player.roomType != StagingRoom) - { - break; - } - sawImportantMessage = TRUE; - PlayerInfo p; - fillPlayerInfo(&resp, &p); - TheGameSpyInfo->updatePlayerInfo(p); - - if (p.m_profileID) - { - if (TheGameSpyPSMessageQueue->findPlayerStatsByID(p.m_profileID).id == 0) - { - PSRequest req; - req.requestType = PSRequest::PSREQUEST_READPLAYERSTATS; - req.player.id = p.m_profileID; - TheGameSpyPSMessageQueue->addRequest(req); - } - } - - // check if we have room for the dude - GameInfo *game = TheGameSpyInfo->getCurrentStagingRoom(); - if (TheGameSpyInfo->amIHost() && game) - { - if (TheNAT) - { - // ditch him - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "KICK/"; - req.nick = p.m_name.str(); - req.options = "GameStarted"; - TheGameSpyPeerMessageQueue->addRequest(req); - } - else - { - // look for room for him - // See if there's room - // First get the number of players currently in the room. - Int numPlayers = 0; - for (Int player = 0; player < MAX_SLOTS; ++player) - { - if (game->getSlot(player)->isOccupied() && - game->getSlot(player)->getPlayerTemplate() != PLAYERTEMPLATE_OBSERVER) - { - ++numPlayers; - } - } - - // now get the number of starting spots on the map. - Int numStartingSpots = MAX_SLOTS; - const MapMetaData *md = TheMapCache->findMap(game->getMap()); - if (md != NULL) - { - numStartingSpots = md->m_numPlayers; - } - - Int openSlotIndex = -1; - for (Int i=0; igetConstSlot(i); - if (slot && slot->isOpen()) - { - openSlotIndex = i; - break; - } - } - - if (openSlotIndex >= 0) - { - // add him - GameSlot newSlot; - UnicodeString uName; - uName.translate(p.m_name); - newSlot.setState(SLOT_PLAYER, uName); - newSlot.setIP(ntohl(resp.player.IP)); - game->setSlot( openSlotIndex, newSlot ); - game->resetAccepted(); // BGC - need to unaccept everyone if someone joins the game. - } - else - { - // ditch him - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "KICK/"; - req.nick = p.m_name.str(); - req.options = "GameFull"; - TheGameSpyPeerMessageQueue->addRequest(req); - } - - // send out new slotlist if I'm host - TheGameSpyInfo->setGameOptions(); - } - } - WOLDisplaySlotList(); - } - break; - - case PeerResponse::PEERRESPONSE_PLAYERLEFT: - { - sawImportantMessage = TRUE; - PlayerInfo p; - fillPlayerInfo(&resp, &p); - TheGameSpyInfo->playerLeftGroupRoom(resp.nick.c_str()); - - if (TheGameSpyGame && TheGameSpyGame->isGameInProgress()) - { - break; - } - - if (TheNAT == NULL) // don't update slot list if we're trying to start a game - { - - GameInfo *game = TheGameSpyInfo->getCurrentStagingRoom(); - if (game && TheGameSpyInfo->amIHost()) - { - Int idx = game->getSlotNum(resp.nick.c_str()); - if (idx >= 0) - { - game->getSlot(idx)->setState(SLOT_OPEN); - game->resetAccepted(); // BGC - need to unaccept everyone if someone leaves the game. - } - } - - // send out new slotlist if I'm host - TheGameSpyInfo->setGameOptions(); - WOLDisplaySlotList(); - - if (game && !TheGameSpyInfo->amIHost()) - { - Int idx = game->getSlotNum(resp.nick.c_str()); - if (idx == 0) - { - // host left - buttonPushed = true; - TheGameSpyInfo->getCurrentStagingRoom()->reset(); - TheGameSpyInfo->leaveStagingRoom(); - //TheGameSpyInfo->joinBestGroupRoom(); - GSMessageBoxOk(TheGameText->fetch("GUI:HostLeftTitle"), TheGameText->fetch("GUI:HostLeft")); - nextScreen = "Menus/WOLCustomLobby.wnd"; - TheShell->pop(); - } - } - - } - } - break; - - case PeerResponse::PEERRESPONSE_MESSAGE: - { - TheGameSpyInfo->addChat(resp.nick.c_str(), resp.message.profileID, - UnicodeString(resp.text.c_str()), !resp.message.isPrivate, resp.message.isAction, listboxGameSetupChat); - } - break; - - case PeerResponse::PEERRESPONSE_DISCONNECT: - { - sawImportantMessage = TRUE; - UnicodeString title, body; - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", resp.discon.reason); - title = TheGameText->fetch( "GUI:GSErrorTitle" ); - body = TheGameText->fetch( disconMunkee ); - GameSpyCloseAllOverlays(); - GSMessageBoxOk( title, body ); - TheGameSpyInfo->reset(); - TheShell->pop(); - } - - case PeerResponse::PEERRESPONSE_ROOMUTM: - { - sawImportantMessage = TRUE; -#if defined(_DEBUG) || defined(_INTERNAL) - if (g_debugSlots) - { - DEBUG_LOG(("About to process a room UTM. Command is '%s', command options is '%s'\n", - resp.command.c_str(), resp.commandOptions.c_str())); - } -#endif - if (!strcmp(resp.command.c_str(), "SL")) - { - // slotlist - GameSpyStagingRoom *game = TheGameSpyInfo->getCurrentStagingRoom(); - Bool isValidSlotList = game && game->getSlot(0) && game->getSlot(0)->isPlayer( resp.nick.c_str() ) && !TheGameSpyInfo->amIHost(); - if (!isValidSlotList) - { - SLOTLIST_DEBUG_LOG(("Not a valid slotlist\n")); - if (!game) - { - SLOTLIST_DEBUG_LOG(("No game!\n")); - } - else - { - if (!game->getSlot(0)) - { - SLOTLIST_DEBUG_LOG(("No slot 0!\n")); - } - else - { - if (TheGameSpyInfo->amIHost()) - { - SLOTLIST_DEBUG_LOG(("I'm the host!\n")); - } - else - { - SLOTLIST_DEBUG_LOG(("Not from the host! isHuman:%d, name:'%ls', sender:'%s'\n", - game->getSlot(0)->isHuman(), game->getSlot(0)->getName().str(), - resp.nick.c_str())); - } - } - } - } - else // isValidSlotList - { - Int oldLocalSlotNum = (game->isInGame()) ? game->getLocalSlotNum() : -1; - Bool wasInGame = oldLocalSlotNum >= 0; - AsciiString oldMap = game->getMap(); - UnsignedInt oldMapCRC, newMapCRC; - oldMapCRC = game->getMapCRC(); - - AsciiString options = resp.commandOptions.c_str(); - options.trim(); - UnsignedShort ports[MAX_SLOTS]; - UnsignedInt ips[MAX_SLOTS]; - Int i; - for (i=0; igetConstSlot(i)) - { - ips[i] = game->getConstSlot(i)->getIP(); - ports[i] = game->getConstSlot(i)->getPort(); - } - else - { - ips[i] = 0; - ports[i] = 0; - } - } - Bool optionsOK = ParseAsciiStringToGameInfo(game, options.str()); - if (TheNAT) - { - for (i=0; igetSlot(i)) - { -#ifdef DEBUG_LOGGING - UnsignedShort newPort = game->getConstSlot(i)->getPort(); - UnsignedInt newIP = game->getConstSlot(i)->getIP(); - DEBUG_ASSERTLOG(newIP == ips[i], ("IP was different for player %d (%X --> %X)\n", - i, ips[i], newIP)); - DEBUG_ASSERTLOG(newPort == ports[i], ("Port was different for player %d (%d --> %d)\n", - i, ports[i], newPort)); -#endif - game->getSlot(i)->setPort(ports[i]); - game->getSlot(i)->setIP(ips[i]); - } - } - } - Int newLocalSlotNum = (game->isInGame()) ? game->getLocalSlotNum() : -1; - Bool isInGame = newLocalSlotNum >= 0; - if (!optionsOK) - { - SLOTLIST_DEBUG_LOG(("Options are bad! bailing!\n")); - break; - } - else - { - SLOTLIST_DEBUG_LOG(("Options are good, local slot is %d\n", newLocalSlotNum)); - if (!isInGame) - { - SLOTLIST_DEBUG_LOG(("Not in game; players are:\n")); - for (Int i=0; igetGameSpySlot(i); - if (slot && slot->isHuman()) - { - UnicodeString munkee; - munkee.format(L"\t%d: %ls", i, slot->getName().str()); - SLOTLIST_DEBUG_LOG(("%ls\n", munkee.str())); - } - } - } - } - WOLDisplaySlotList(); - - // if I changed map availability, send it across - newMapCRC = game->getMapCRC(); - if (isInGame) - { - lastSlotlistTime = timeGetTime(); - if ( (oldMapCRC ^ newMapCRC) || (!wasInGame && isInGame) ) - { - // it changed. send it - UnicodeString hostName = TheGameSpyInfo->getCurrentStagingRoom()->getSlot(0)->getName(); - AsciiString asciiName; - asciiName.translate(hostName); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "MAP"; - req.nick = asciiName.str(); - req.options = (game->getSlot(newLocalSlotNum)->hasMap())?"1":"0"; - TheGameSpyPeerMessageQueue->addRequest(req); - if (!game->getSlot(newLocalSlotNum)->hasMap()) - { - UnicodeString text; - UnicodeString mapDisplayName; - const MapMetaData *mapData = TheMapCache->findMap( game->getMap() ); - Bool willTransfer = TRUE; - if (mapData) - { - mapDisplayName.format(L"%ls", mapData->m_displayName.str()); - willTransfer = !mapData->m_isOfficial; - } - else - { - mapDisplayName.format(L"%hs", TheGameState->getMapLeafName(game->getMap()).str()); - willTransfer = WouldMapTransfer(game->getMap()); - } - if (willTransfer) - text.format(TheGameText->fetch("GUI:LocalPlayerNoMapWillTransfer"), mapDisplayName.str()); - else - text.format(TheGameText->fetch("GUI:LocalPlayerNoMap"), mapDisplayName.str()); - TheGameSpyInfo->addText(text, GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - } - } - if (!initialAcceptEnable) - { - buttonStart->winEnable( TRUE ); - initialAcceptEnable = TRUE; - } - } - else - { - if (lastSlotlistTime) - { - // can't see ourselves - buttonPushed = true; - DEBUG_LOG(("Can't see ourselves in slotlist %s\n", options.str())); - TheGameSpyInfo->getCurrentStagingRoom()->reset(); - TheGameSpyInfo->leaveStagingRoom(); - //TheGameSpyInfo->joinBestGroupRoom(); - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSKicked")); - nextScreen = "Menus/WOLCustomLobby.wnd"; - TheShell->pop(); - } - } - } - } - else if (!strcmp(resp.command.c_str(), "HWS")) - { - // host wants to start - GameInfo *game = TheGameSpyInfo->getCurrentStagingRoom(); - if (game && game->isInGame() && game->getSlot(0) && game->getSlot(0)->isPlayer( resp.nick.c_str() )) - { - Int slotNum = game->getLocalSlotNum(); - GameSlot *slot = game->getSlot(slotNum); - if (slot && (slot->isAccepted() == false)) - { - TheGameSpyInfo->addText(TheGameText->fetch("GUI:HostWantsToStart"), GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - } - } - } - else if (!stricmp(resp.command.c_str(), "NAT")) - { - if (TheNAT != NULL) { - TheNAT->processGlobalMessage(-1, resp.commandOptions.c_str()); - } - } - else if (!stricmp(resp.command.c_str(), "Pings")) - { - if (!TheGameSpyInfo->amIHost()) - { - AsciiString pings = resp.commandOptions.c_str(); - AsciiString token; - for (Int i=0; igetCurrentStagingRoom()->getGameSpySlot(i); - if (pings.nextToken(&token, ",")) - { - token.trim(); - slot->setPingString(token); - } - else - { - slot->setPingString(""); - } - } - } - } - } - break; - - case PeerResponse::PEERRESPONSE_PLAYERUTM: - { - sawImportantMessage = TRUE; - if (!strcmp(resp.command.c_str(), "STATS")) - { - PSPlayerStats stats = TheGameSpyPSMessageQueue->parsePlayerKVPairs(resp.commandOptions.c_str()); - if (stats.id && (TheGameSpyPSMessageQueue->findPlayerStatsByID(stats.id).id == 0)) - TheGameSpyPSMessageQueue->trackPlayerStats(stats); - break; - } - GameSpyStagingRoom *game = TheGameSpyInfo->getCurrentStagingRoom(); - if (game) - { - Int slotNum = game->getSlotNum(resp.nick.c_str()); - if ((slotNum >= 0) && (slotNum < MAX_SLOTS) && (!stricmp(resp.command.c_str(), "NAT"))) { - // this is a command for NAT negotiations, pass if off to TheNAT - if (TheNAT != NULL) { - TheNAT->processGlobalMessage(slotNum, resp.commandOptions.c_str()); - } - } - if (slotNum == 0 && !TheGameSpyInfo->amIHost()) - { - if (!strcmp(resp.command.c_str(), "KICK")) - { - // oops - we've been kicked. bail. - buttonPushed = true; - TheGameSpyInfo->getCurrentStagingRoom()->reset(); - TheGameSpyInfo->leaveStagingRoom(); - //TheGameSpyInfo->joinBestGroupRoom(); - UnicodeString message = TheGameText->fetch("GUI:GSKicked"); - AsciiString commandMessage = resp.commandOptions.c_str(); - commandMessage.trim(); - DEBUG_LOG(("We were kicked: reason was '%s'\n", resp.commandOptions.c_str())); - if (commandMessage == "GameStarted") - { - message = TheGameText->fetch("GUI:GSKickedGameStarted"); - } - else if (commandMessage == "GameFull") - { - message = TheGameText->fetch("GUI:GSKickedGameFull"); - } - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), message); - nextScreen = "Menus/WOLCustomLobby.wnd"; - TheShell->pop(); - } - } - else if (slotNum > 0 && TheGameSpyInfo->amIHost()) - { - if (!strcmp(resp.command.c_str(), "accept")) - { - game->getSlot(slotNum)->setAccept(); - TheGameSpyInfo->setGameOptions(); - WOLDisplaySlotList(); - } - else if (!strcmp(resp.command.c_str(), "MAP")) - { - Bool hasMap = atoi(resp.commandOptions.c_str()); - game->getSlot(slotNum)->setMapAvailability(hasMap); - if (!hasMap) - { - // tell the host the user doesn't have the map - UnicodeString mapDisplayName; - const MapMetaData *mapData = TheMapCache->findMap( game->getMap() ); - Bool willTransfer = TRUE; - if (mapData) - { - mapDisplayName.format(L"%ls", mapData->m_displayName.str()); - willTransfer = !mapData->m_isOfficial; - } - else - { - mapDisplayName.format(L"%hs", game->getMap().str()); - willTransfer = WouldMapTransfer(game->getMap()); - } - UnicodeString text; - if (willTransfer) - text.format(TheGameText->fetch("GUI:PlayerNoMapWillTransfer"), game->getSlot(slotNum)->getName().str(), mapDisplayName.str()); - else - text.format(TheGameText->fetch("GUI:PlayerNoMap"), game->getSlot(slotNum)->getName().str(), mapDisplayName.str()); - TheGameSpyInfo->addText(text, GameSpyColor[GSCOLOR_DEFAULT], listboxGameSetupChat); - } - WOLDisplaySlotList(); - } - else if (!strcmp(resp.command.c_str(), "REQ")) - { - AsciiString options = resp.commandOptions.c_str(); - options.trim(); - - Bool change = false; - Bool shouldUnaccept = false; - AsciiString key; - options.nextToken(&key, "="); - Int val = atoi(options.str()+1); - UnsignedInt uVal = atoi(options.str()+1); - DEBUG_LOG(("GameOpt request: key=%s, val=%s from player %d\n", key.str(), options.str()+1, slotNum)); - - GameSpyGameSlot *slot = game->getGameSpySlot(slotNum); - if (!slot) - break; - - if (key == "Color") - { - if (val >= -1 && val < TheMultiplayerSettings->getNumColors() && val != slot->getColor() && slot->getPlayerTemplate() != PLAYERTEMPLATE_OBSERVER) - { - Bool colorAvailable = TRUE; - if(val != -1 ) - { - for(Int i=0; i getSlot(i); - if(val == checkSlot->getColor() && slot != checkSlot) - { - colorAvailable = FALSE; - break; - } - } - } - if(colorAvailable) - slot->setColor(val); - change = true; - } - else - { - DEBUG_LOG(("Rejecting invalid color %d\n", val)); - } - } - else if (key == "PlayerTemplate") - { - if (val >= PLAYERTEMPLATE_MIN && val < ThePlayerTemplateStore->getPlayerTemplateCount() && val != slot->getPlayerTemplate()) - { - // Validate for LimitArmies checkbox - if ( game->oldFactionsOnly() ) - { - const PlayerTemplate *fac = ThePlayerTemplateStore->getNthPlayerTemplate(val); - if ( fac != NULL && !fac->isOldFaction()) - { - val = PLAYERTEMPLATE_RANDOM; - } - } - - slot->setPlayerTemplate(val); - if (val == PLAYERTEMPLATE_OBSERVER) - { - slot->setColor(-1); - slot->setStartPos(-1); - slot->setTeamNumber(-1); - } - change = true; - shouldUnaccept = true; - } - else - { - DEBUG_LOG(("Rejecting invalid PlayerTemplate %d\n", val)); - } - } - else if (key == "StartPos") - { - if (val >= -1 && val < MAX_SLOTS && val != slot->getStartPos() && slot->getPlayerTemplate() != PLAYERTEMPLATE_OBSERVER) - { - Bool startPosAvailable = TRUE; - if(val != -1) - { - for(Int i=0; i getSlot(i); - if(val == checkSlot->getStartPos() && slot != checkSlot) - { - startPosAvailable = FALSE; - break; - } - } - } - if(startPosAvailable) - slot->setStartPos(val); - change = true; - shouldUnaccept = true; - } - else - { - DEBUG_LOG(("Rejecting invalid startPos %d\n", val)); - } - } - else if (key == "Team") - { - if (val >= -1 && val < MAX_SLOTS/2 && val != slot->getTeamNumber() && slot->getPlayerTemplate() != PLAYERTEMPLATE_OBSERVER) - { - slot->setTeamNumber(val); - change = true; - shouldUnaccept = true; - } - else - { - DEBUG_LOG(("Rejecting invalid team %d\n", val)); - } - } - else if (key == "IP") - { - if (uVal != slot->getIP()) - { - DEBUG_LOG(("setting IP of player %ls from 0x%08x to be 0x%08x", slot->getName().str(), slot->getIP(), uVal)); - slot->setIP(uVal); - change = true; - shouldUnaccept = true; - } - else - { - DEBUG_LOG(("Rejecting invalid IP %d\n", uVal)); - } - } - else if (key == "NAT") - { - if ((val >= FirewallHelperClass::FIREWALL_MIN) && - (val <= FirewallHelperClass::FIREWALL_MAX)) - { - slot->setNATBehavior((FirewallHelperClass::FirewallBehaviorType)val); - DEBUG_LOG(("Setting NAT behavior to %d for player %d\n", val, slotNum)); - change = true; - } - else - { - DEBUG_LOG(("Rejecting invalid NAT behavior %d from player %d\n", val, slotNum)); - } - } - else if (key == "Ping") - { - slot->setPingString(options.str()+1); - TheGameSpyInfo->setGameOptions(); - DEBUG_LOG(("Setting ping string to %s for player %d\n", options.str()+1, slotNum)); - } - - if (change) - { - if (shouldUnaccept) - game->resetAccepted(); - - TheGameSpyInfo->setGameOptions(); - - WOLDisplaySlotList(); - DEBUG_LOG(("Slot value is color=%d, PlayerTemplate=%d, startPos=%d, team=%d, IP=0x%8.8X\n", - slot->getColor(), slot->getPlayerTemplate(), slot->getStartPos(), slot->getTeamNumber(), slot->getIP())); - DEBUG_LOG(("Slot list updated to %s\n", GameInfoToAsciiString(game).str())); - } - } - } - } - } - break; - - } - } - - - } -}// void WOLGameSetupMenuUpdate( WindowLayout * layout, void *userData) - -//------------------------------------------------------------------------------------------------- -/** Lan Game Options menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLGameSetupMenuInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - /* - switch( msg ) - { - - //------------------------------------------------------------------------------------------------- - case GWM_RIGHT_UP: - { - if (buttonPushed) - break; - - GameWindow *control = (GameWindow *)mData1; - NameKeyType controlID = (NameKeyType)control->winGetWindowId(); - DEBUG_LOG(("GWM_RIGHT_UP for control %d(%s)\n", controlID, TheNameKeyGenerator->keyToName(controlID).str())); - break; - } - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - if (buttonPushed) - break; - - switch( key ) - { - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonBack, buttonBackID ); - } // end if - // don't let key fall through anywhere else - return MSG_HANDLED; - } // end escape - } // end switch( key ) - } // end char - } // end switch( msg ) - */ - return MSG_IGNORED; -}//WindowMsgHandledType WOLGameSetupMenuInput( GameWindow *window, UnsignedInt msg, - - -// Slash commands ------------------------------------------------------------------------- -//extern "C" { -//int getQR2HostingStatus(void); -//} -extern int isThreadHosting; - -Bool handleGameSetupSlashCommands(UnicodeString uText) -{ - AsciiString message; - message.translate(uText); - - if (message.getCharAt(0) != '/') - { - return FALSE; // not a slash command - } - - AsciiString remainder = message.str() + 1; - AsciiString token; - remainder.nextToken(&token); - token.toLower(); - - if (token == "host") - { - UnicodeString s; - s.format(L"Hosting qr2:%d thread:%d", 0, isThreadHosting); - TheGameSpyInfo->addText(s, GameSpyColor[GSCOLOR_DEFAULT], NULL); - return TRUE; // was a slash command - } - else if (token == "me" && uText.getLength()>4) - { - TheGameSpyInfo->sendChat(UnicodeString(uText.str()+4), TRUE, NULL); - return TRUE; // was a slash command - } -#if defined(_DEBUG) || defined(_INTERNAL) - else if (token == "slots") - { - g_debugSlots = !g_debugSlots; - TheGameSpyInfo->addText(UnicodeString(L"Toggled SlotList debug"), GameSpyColor[GSCOLOR_DEFAULT], NULL); - return TRUE; // was a slash command - } - else if (token == "discon") - { - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_LOGOUT; - TheGameSpyPeerMessageQueue->addRequest( req ); - return TRUE; - } -#endif // defined(_DEBUG) || defined(_INTERNAL) - - return FALSE; // not a slash command -} - -static Int getNextSelectablePlayer(Int start) -{ - GameSpyStagingRoom *game = TheGameSpyInfo->getCurrentStagingRoom(); - if (!game->amIHost()) - return -1; - for (Int j=start; jgetGameSpySlot(j); - if (slot && slot->getStartPos() == -1 && - ( (j==game->getLocalSlotNum() && game->getConstSlot(j)->getPlayerTemplate()!=PLAYERTEMPLATE_OBSERVER) - || slot->isAI())) - { - return j; - } - } - return -1; -} - -static Int getFirstSelectablePlayer(const GameInfo *game) -{ - const GameSlot *slot = game->getConstSlot(game->getLocalSlotNum()); - if (!game->amIHost() || slot && slot->getPlayerTemplate() != PLAYERTEMPLATE_OBSERVER) - return game->getLocalSlotNum(); - - for (Int i=0; igetConstSlot(i); - if (slot && slot->isAI()) - return i; - } - - return game->getLocalSlotNum(); -} - -//------------------------------------------------------------------------------------------------- -/** WOL Game Options menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLGameSetupMenuSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - static buttonCommunicatorID = NAMEKEY_INVALID; - switch( msg ) - { - //------------------------------------------------------------------------------------------------- - case GWM_CREATE: - { - buttonCommunicatorID = NAMEKEY("GameSpyGameOptionsMenu.wnd:ButtonCommunicator"); - break; - } // case GWM_DESTROY: - //------------------------------------------------------------------------------------------------- - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - //------------------------------------------------------------------------------------------------- - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - //------------------------------------------------------------------------------------------------- - case GCM_SELECTED: - { - if (!initDone) - break; - if (buttonPushed) - break; - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if ( controlID == comboBoxStartingCashID ) - { - handleStartingCashSelection(); - } - else - { - GameSpyStagingRoom *myGame = TheGameSpyInfo->getCurrentStagingRoom(); - for (Int i = 0; i < MAX_SLOTS; i++) - { - if (controlID == comboBoxColorID[i]) - { - handleColorSelection(i); - } - else if (controlID == comboBoxPlayerTemplateID[i]) - { - handlePlayerTemplateSelection(i); - } - else if (controlID == comboBoxTeamID[i]) - { - handleTeamSelection(i); - } - else if( controlID == comboBoxPlayerID[i] && TheGameSpyInfo->amIHost() ) - { - // We don't have anything that'll happen if we click on ourselves - if(i == myGame->getLocalSlotNum()) - break; - // Get - Int pos = -1; - GadgetComboBoxGetSelectedPos(comboBoxPlayer[i], &pos); - if( pos != SLOT_PLAYER && pos >= 0) - { - if( myGame->getSlot(i)->getState() == SLOT_PLAYER ) - { - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - AsciiString aName; - aName.translate(myGame->getSlot(i)->getName()); - req.nick = aName.str(); - req.id = "KICK/"; - req.options = "true"; - TheGameSpyPeerMessageQueue->addRequest(req); - - UnicodeString name = myGame->getSlot(i)->getName(); - myGame->getSlot(i)->setState(SlotState(pos)); - myGame->resetAccepted(); - TheGameSpyInfo->setGameOptions(); - WOLDisplaySlotList(); - //TheLAN->OnPlayerLeave(name); - } - else if( myGame->getSlot(i)->getState() != pos ) - { - Bool wasAI = (myGame->getSlot(i)->isAI()); - myGame->getSlot(i)->setState(SlotState(pos)); - Bool isAI = (myGame->getSlot(i)->isAI()); - myGame->resetAccepted(); - if (wasAI ^ isAI) - PopulatePlayerTemplateComboBox(i, comboBoxPlayerTemplate, myGame, wasAI && myGame->getAllowObservers()); - TheGameSpyInfo->setGameOptions(); - WOLDisplaySlotList(); - } - } - break; - } - } - } - break; - }// case GCM_SELECTED: - //------------------------------------------------------------------------------------------------- - case GBM_SELECTED: - { - if (buttonPushed) - break; - - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - static buttonCommunicatorID = NAMEKEY("GameSpyGameOptionsMenu.wnd:ButtonCommunicator"); - if ( controlID == buttonBackID ) - { - savePlayerInfo(); - if( WOLMapSelectLayout ) - { - WOLMapSelectLayout->destroyWindows(); - WOLMapSelectLayout->deleteInstance(); - WOLMapSelectLayout = NULL; - } - - TheGameSpyInfo->getCurrentStagingRoom()->reset(); - //peerLeaveRoom(TheGameSpyChat->getPeer(), StagingRoom, NULL); - TheGameSpyInfo->leaveStagingRoom(); - buttonPushed = true; - nextScreen = "Menus/WOLCustomLobby.wnd"; - TheShell->pop(); - - } //if ( controlID == buttonBack ) - else if ( controlID == buttonCommunicatorID ) - { - GameSpyToggleOverlay( GSOVERLAY_BUDDY ); - - } - else if ( controlID == buttonEmoteID ) - { - // read the user's input - txtInput.set(GadgetTextEntryGetText( textEntryChat )); - // Clear the text entry line - GadgetTextEntrySetText(textEntryChat, UnicodeString::TheEmptyString); - // Clean up the text (remove leading/trailing chars, etc) - txtInput.trim(); - // Echo the user's input to the chat window - if (!txtInput.isEmpty()) - TheGameSpyInfo->sendChat(txtInput, FALSE, NULL); // 'emote' button is now carriage-return - } //if ( controlID == buttonEmote ) - else if ( controlID == buttonSelectMapID ) - { - WOLMapSelectLayout = TheWindowManager->winCreateLayout( "Menus/WOLMapSelectMenu.wnd" ); - WOLMapSelectLayout->runInit(); - WOLMapSelectLayout->hide( FALSE ); - WOLMapSelectLayout->bringForward(); - } - else if ( controlID == buttonStartID ) - { - savePlayerInfo(); - if (TheGameSpyInfo->amIHost()) - { - StartPressed(); - } - else - { - //I'm the Client... send an accept message to the host. - GameSlot *localSlot = TheGameSpyInfo->getCurrentStagingRoom()->getSlot(TheGameSpyInfo->getCurrentStagingRoom()->getLocalSlotNum()); - if (localSlot) - { - localSlot->setAccept(); - } - UnicodeString hostName = TheGameSpyInfo->getCurrentStagingRoom()->getSlot(0)->getName(); - AsciiString asciiName; - asciiName.translate(hostName); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "accept"; - req.nick = asciiName.str(); - req.options = "true"; - TheGameSpyPeerMessageQueue->addRequest(req); - //peerSetReady( PEER, PEERTrue ); - WOLDisplaySlotList(); - } - } - else if ( controlID == checkBoxLimitSuperweaponsID ) - { - handleLimitSuperweaponsClick(); - } - else - { - for (Int i = 0; i < MAX_SLOTS; i++) - { - if (controlID == buttonMapStartPositionID[i]) - { - GameSpyStagingRoom *game = TheGameSpyInfo->getCurrentStagingRoom(); - Int playerIdxInPos = -1; - for (Int j=0; jgetGameSpySlot(j); - if (slot && slot->getStartPos() == i) - { - playerIdxInPos = j; - break; - } - } - if (playerIdxInPos >= 0) - { - GameSpyGameSlot *slot = game->getGameSpySlot(playerIdxInPos); - if (playerIdxInPos == game->getLocalSlotNum() || (game->amIHost() && slot && slot->isAI())) - { - // it's one of my type. Try to change it. - Int nextPlayer = getNextSelectablePlayer(playerIdxInPos+1); - handleStartPositionSelection(playerIdxInPos, -1); - if (nextPlayer >= 0) - { - handleStartPositionSelection(nextPlayer, i); - } - } - } - else - { - // nobody in the slot - put us in - Int nextPlayer = getNextSelectablePlayer(0); - if (nextPlayer < 0) - nextPlayer = getFirstSelectablePlayer(game); - handleStartPositionSelection(nextPlayer, i); - } - } - } - } - - - break; - }// case GBM_SELECTED: - //------------------------------------------------------------------------------------------------- - case GBM_SELECTED_RIGHT: - { - if (buttonPushed) - break; - - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - for (Int i = 0; i < MAX_SLOTS; i++) - { - if (controlID == buttonMapStartPositionID[i]) - { - GameSpyStagingRoom *game = TheGameSpyInfo->getCurrentStagingRoom(); - Int playerIdxInPos = -1; - for (Int j=0; jgetGameSpySlot(j); - if (slot && slot->getStartPos() == i) - { - playerIdxInPos = j; - break; - } - } - if (playerIdxInPos >= 0) - { - GameSpyGameSlot *slot = game->getGameSpySlot(playerIdxInPos); - if (playerIdxInPos == game->getLocalSlotNum() || (game->amIHost() && slot && slot->isAI())) - { - // it's one of my type. Remove it. - handleStartPositionSelection(playerIdxInPos, -1); - } - } - } - } - break; - } - - //------------------------------------------------------------------------------------------------- - case GEM_EDIT_DONE: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - // Take the user's input and echo it into the chat window as well as - // send it to the other clients on the lan - if ( controlID == textEntryChatID ) - { - - // read the user's input - txtInput.set(GadgetTextEntryGetText( textEntryChat )); - // Clear the text entry line - GadgetTextEntrySetText(textEntryChat, UnicodeString::TheEmptyString); - // Clean up the text (remove leading/trailing chars, etc) - txtInput.trim(); - // Echo the user's input to the chat window - if (!txtInput.isEmpty()) - { - if (!handleGameSetupSlashCommands(txtInput)) - { - TheGameSpyInfo->sendChat(txtInput, false, NULL); - } - } - - }// if ( controlID == textEntryChatID ) - break; - } - //------------------------------------------------------------------------------------------------- - default: - return MSG_IGNORED; - }//Switch - return MSG_HANDLED; -}//WindowMsgHandledType WOLGameSetupMenuSystem( GameWindow *window, UnsignedInt msg, - - diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLadderScreen.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLadderScreen.cpp deleted file mode 100644 index 95899d4850e..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLadderScreen.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ReplayMenu.cpp ///////////////////////////////////////////////////////////////////// -// Author: Chris The masta Huybregts, December 2001 -// Description: Replay Menus -/////////////////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/MessageBox.h" - -// window ids ------------------------------------------------------------------------------------- -static NameKeyType parentWindowID = NAMEKEY_INVALID; -static NameKeyType buttonBackID = NAMEKEY_INVALID; -static NameKeyType windowLadderID = NAMEKEY_INVALID; - - -// window pointers -------------------------------------------------------------------------------- -static GameWindow *parentWindow = NULL; -static GameWindow *buttonBack = NULL; -static GameWindow *windowLadder = NULL; - - -//------------------------------------------------------------------------------------------------- -/** Initialize the single player menu */ -//------------------------------------------------------------------------------------------------- -void WOLLadderScreenInit( WindowLayout *layout, void *userData ) -{ - TheShell->showShellMap(TRUE); - - // get ids for our children controls - parentWindowID = TheNameKeyGenerator->nameToKey( AsciiString("WOLLadderScreen.wnd:LadderParent") ); - buttonBackID = TheNameKeyGenerator->nameToKey( AsciiString("WOLLadderScreen.wnd:ButtonBack") ); - windowLadderID = TheNameKeyGenerator->nameToKey( AsciiString("WOLLadderScreen.wnd:WindowLadder") ); - - parentWindow = TheWindowManager->winGetWindowFromId( NULL, parentWindowID ); - buttonBack = TheWindowManager->winGetWindowFromId( parentWindow, buttonBackID ); - windowLadder = TheWindowManager->winGetWindowFromId( parentWindow, windowLadderID ); - - //Load the listbox shiznit -// PopulateReplayFileListbox(listboxReplayFiles); - - // show menu - layout->hide( FALSE ); - - // set keyboard focus to main parent - TheWindowManager->winSetFocus( parentWindow ); - -} // end ReplayMenuInit - -//------------------------------------------------------------------------------------------------- -/** single player menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLLadderScreenShutdown( WindowLayout *layout, void *userData ) -{ - - // hide menu - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout ); - -} // end ReplayMenuShutdown - -//------------------------------------------------------------------------------------------------- -/** single player menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLLadderScreenUpdate( WindowLayout *layout, void *userData ) -{ - -} // end ReplayMenuUpdate - -//------------------------------------------------------------------------------------------------- -/** Replay menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLLadderScreenInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonBack, buttonBackID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; - -} // end ReplayMenuInput - -//------------------------------------------------------------------------------------------------- -/** single player menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLLadderScreenSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CREATE: - { - - - break; - - } // end create - - //--------------------------------------------------------------------------------------------- - case GWM_DESTROY: - { - - break; - - } // end case - - // -------------------------------------------------------------------------------------------- - case GWM_INPUT_FOCUS: - { - - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - - } // end input - //--------------------------------------------------------------------------------------------- - case GBM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if( controlID == buttonBackID ) - { - - // thou art directed to return to thy known solar system immediately! - TheShell->pop(); - - } // end else if - - break; - - } // end selected - - default: - return MSG_IGNORED; - } // end switch - - return MSG_HANDLED; -} // end ReplayMenuSystem - diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLobbyMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLobbyMenu.cpp deleted file mode 100644 index 6d4fb2c52e4..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLobbyMenu.cpp +++ /dev/null @@ -1,1876 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLLobbyMenu.cpp -// Author: Chris Huybregts, November 2001 -// Description: WOL Lobby Menu -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "Common/GameState.h" -#include "Common/MiniLog.h" -#include "Common/MultiplayerSettings.h" -#include "Common/PlayerTemplate.h" -#include "Common/CustomMatchPreferences.h" -#include "Common/Version.h" -#include "GameClient/AnimateWindowManager.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/GameClient.h" -#include "GameClient/Shell.h" -#include "GameClient/ShellHooks.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetComboBox.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetSlider.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/GameText.h" -#include "GameClient/MessageBox.h" -#include "GameClient/Mouse.h" -#include "GameClient/Display.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameClient/GameWindowTransitions.h" - -#include "GameLogic/GameLogic.h" - -#include "GameClient/LanguageFilter.h" -#include "GameNetwork/GameSpy/BuddyDefs.h" -#include "GameNetwork/GameSpy/GSConfig.h" -#include "GameNetwork/GameSpy/LadderDefs.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PersistentStorageDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpy/LobbyUtils.h" -#include "GameNetwork/RankPointValue.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif -void refreshGameList( Bool forceRefresh = FALSE ); -void refreshPlayerList( Bool forceRefresh = FALSE ); - -#ifdef DEBUG_LOGGING -#define PERF_TEST -static LogClass s_perfLog("Perf.txt"); -#define PERF_LOG(x) s_perfLog.log x -#else // DEBUG_LOGGING -#define PERF_LOG(x) {} -#endif // DEBUG_LOGGING - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -static Bool isShuttingDown = false; -static Bool buttonPushed = false; -static char *nextScreen = NULL; -static Bool raiseMessageBoxes = false; -static time_t gameListRefreshTime = 0; -static const time_t gameListRefreshInterval = 10000; -static time_t playerListRefreshTime = 0; -static const time_t playerListRefreshInterval = 5000; - -void setUnignoreText( WindowLayout *layout, AsciiString nick, GPProfile id); -static void doSliderTrack(GameWindow *control, Int val); -Bool DontShowMainMenu = FALSE; -enum { COLUMN_PLAYERNAME = 1 }; - -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentWOLLobbyID = NAMEKEY_INVALID; -static NameKeyType buttonBackID = NAMEKEY_INVALID; -static NameKeyType buttonHostID = NAMEKEY_INVALID; -static NameKeyType buttonRefreshID = NAMEKEY_INVALID; -static NameKeyType buttonJoinID = NAMEKEY_INVALID; -static NameKeyType buttonBuddyID = NAMEKEY_INVALID; -static NameKeyType buttonEmoteID = NAMEKEY_INVALID; -static NameKeyType textEntryChatID = NAMEKEY_INVALID; -static NameKeyType listboxLobbyPlayersID = NAMEKEY_INVALID; -static NameKeyType listboxLobbyChatID = NAMEKEY_INVALID; -static NameKeyType comboLobbyGroupRoomsID = NAMEKEY_INVALID; -//static NameKeyType // sliderChatAdjustID = NAMEKEY_INVALID; - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentWOLLobby = NULL; -static GameWindow *buttonBack = NULL; -static GameWindow *buttonHost = NULL; -static GameWindow *buttonRefresh = NULL; -static GameWindow *buttonJoin = NULL; -static GameWindow *buttonBuddy = NULL; -static GameWindow *buttonEmote = NULL; -static GameWindow *textEntryChat = NULL; -static GameWindow *listboxLobbyPlayers = NULL; -static GameWindow *listboxLobbyChat = NULL; -static GameWindow *comboLobbyGroupRooms = NULL; -static GameWindow *parent = NULL; - -static Int groupRoomToJoin = 0; -static Int initialGadgetDelay = 2; -static Bool justEntered = FALSE; - -#if defined(_INTERNAL) || defined(_DEBUG) -Bool g_fakeCRC = FALSE; -Bool g_debugSlots = FALSE; -#endif - -std::list TheLobbyQueuedUTMs; - -// Slash commands ------------------------------------------------------------------------- -//extern "C" { -//int getQR2HostingStatus(void); -//} -extern int isThreadHosting; - -Bool handleLobbySlashCommands(UnicodeString uText) -{ - AsciiString message; - message.translate(uText); - - if (message.getCharAt(0) != '/') - { - return FALSE; // not a slash command - } - - AsciiString remainder = message.str() + 1; - AsciiString token; - remainder.nextToken(&token); - token.toLower(); - - if (token == "host") - { - UnicodeString s; - s.format(L"Hosting qr2:%d thread:%d", 0, isThreadHosting); - TheGameSpyInfo->addText(s, GameSpyColor[GSCOLOR_DEFAULT], NULL); - return TRUE; // was a slash command - } - else if (token == "me" && uText.getLength()>4) - { - TheGameSpyInfo->sendChat(UnicodeString(uText.str()+4), TRUE, listboxLobbyPlayers); - return TRUE; // was a slash command - } - else if (token == "refresh") - { - // Added 2/19/03 added the game refresh - refreshGameList(TRUE); - refreshPlayerList(TRUE); - return TRUE; // was a slash command - } - /* - if (token == "togglegamelist") - { - NameKeyType buttonID = NAMEKEY("WOLCustomLobby.wnd:ButtonGameListToggle"); - GameWindow *button = TheWindowManager->winGetWindowFromId(parent, buttonID); - if (button) - { - button->winHide(!button->winIsHidden()); - } - return TRUE; // was a slash command - } - else if (token == "adjustchat") - { - NameKeyType sliderID = NAMEKEY("WOLCustomLobby.wnd:SliderChatAdjust"); - GameWindow *slider = TheWindowManager->winGetWindowFromId(parent, sliderID); - if (slider) - { - slider->winHide(!slider->winIsHidden()); - } - return TRUE; // was a slash command - } - */ -#if defined(_INTERNAL) || defined(_DEBUG) - else if (token == "fakecrc") - { - g_fakeCRC = !g_fakeCRC; - TheGameSpyInfo->addText(UnicodeString(L"Toggled CRC fakery"), GameSpyColor[GSCOLOR_DEFAULT], NULL); - return TRUE; // was a slash command - } - else if (token == "slots") - { - g_debugSlots = !g_debugSlots; - TheGameSpyInfo->addText(UnicodeString(L"Toggled SlotList debug"), GameSpyColor[GSCOLOR_DEFAULT], NULL); - return TRUE; // was a slash command - } -#endif - - return FALSE; // not a slash command -} - -static Bool s_tryingToHostOrJoin = FALSE; -void SetLobbyAttemptHostJoin(Bool start) -{ - s_tryingToHostOrJoin = start; -} - -// Tooltips ------------------------------------------------------------------------------- - -static void playerTooltip(GameWindow *window, - WinInstanceData *instData, - UnsignedInt mouse) -{ - Int x, y, row, col; - x = LOLONGTOSHORT(mouse); - y = HILONGTOSHORT(mouse); - - GadgetListBoxGetEntryBasedOnXY(window, x, y, row, col); - - if (row == -1 || col == -1) - { - TheMouse->setCursorTooltip( UnicodeString::TheEmptyString);//TheGameText->fetch("TOOLTIP:PlayersInLobby") ); - return; - } - - UnicodeString uName = GadgetListBoxGetText(window, row, COLUMN_PLAYERNAME); - AsciiString aName; - aName.translate(uName); - - PlayerInfoMap::iterator it = TheGameSpyInfo->getPlayerInfoMap()->find(aName); - PlayerInfo *info = &(it->second); - Bool isLocalPlayer = (TheGameSpyInfo->getLocalName().compareNoCase(info->m_name) == 0); - - if (col == 0) - { - if (info->m_preorder) - { - TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:LobbyOfficersClub") ); - } - else - { - TheMouse->setCursorTooltip( UnicodeString::TheEmptyString); - } - return; - } - - AsciiString playerLocale = info->m_locale; - AsciiString localeIdentifier; - localeIdentifier.format("WOL:Locale%2.2d", atoi(playerLocale.str())); - Int playerWins = info->m_wins; - Int playerLosses = info->m_losses; - UnicodeString playerInfo; - playerInfo.format(TheGameText->fetch("TOOLTIP:PlayerInfo"), TheGameText->fetch(localeIdentifier).str(), playerWins, playerLosses); - - UnicodeString tooltip = UnicodeString::TheEmptyString;//TheGameText->fetch("TOOLTIP:PlayersInLobby"); - if (isLocalPlayer) - { - tooltip.format(TheGameText->fetch("TOOLTIP:LocalPlayer"), uName.str()); - } - else - { - // not us - if (TheGameSpyInfo->getBuddyMap()->find(info->m_profileID) != TheGameSpyInfo->getBuddyMap()->end()) - { - // buddy - tooltip.format(TheGameText->fetch("TOOLTIP:BuddyPlayer"), uName.str()); - } - else - { - if (info->m_profileID) - { - // non-buddy profiled player - tooltip.format(TheGameText->fetch("TOOLTIP:ProfiledPlayer"), uName.str()); - } - else - { - // non-profiled player - tooltip.format(TheGameText->fetch("TOOLTIP:GenericPlayer"), uName.str()); - } - } - } - - if (info->isIgnored()) - { - tooltip.concat(TheGameText->fetch("TOOLTIP:IgnoredModifier")); - } - - if (info->m_profileID) - { - tooltip.concat(playerInfo); - } - - Int rank = 0; - Int i = 0; - while( info->m_rankPoints >= TheRankPointValues->m_ranks[i + 1]) - ++i; - rank = i; - AsciiString sideName = "GUI:RandomSide"; - if (info->m_side > 0) - { - const PlayerTemplate *fac = ThePlayerTemplateStore->getNthPlayerTemplate(info->m_side); - if (fac) - { - sideName.format("SIDE:%s", fac->getSide().str()); - } - } - AsciiString rankName; - rankName.format("GUI:GSRank%d", rank); - UnicodeString tmp; - tmp.format(L"\n%ls %ls", TheGameText->fetch(sideName).str(), TheGameText->fetch(rankName).str()); - tooltip.concat(tmp); - - TheMouse->setCursorTooltip( tooltip, -1, NULL, 1.5f ); // the text and width are the only params used. the others are the default values. -} - -static void populateGroupRoomListbox(GameWindow *lb) -{ - if (!lb) - return; - - GadgetComboBoxReset(lb); - Int indexToSelect = -1; - GroupRoomMap::iterator iter; - - // now populate the combo box - for (iter = TheGameSpyInfo->getGroupRoomList()->begin(); iter != TheGameSpyInfo->getGroupRoomList()->end(); ++iter) - { - GameSpyGroupRoom room = iter->second; - if (room.m_groupID != TheGameSpyConfig->getQMChannel()) - { - DEBUG_LOG(("populateGroupRoomListbox(): groupID %d\n", room.m_groupID)); - if (room.m_groupID == TheGameSpyInfo->getCurrentGroupRoom()) - { - Int selected = GadgetComboBoxAddEntry(lb, room.m_translatedName, GameSpyColor[GSCOLOR_CURRENTROOM]); - GadgetComboBoxSetItemData(lb, selected, (void *)(room.m_groupID)); - indexToSelect = selected; - } - else - { - Int selected = GadgetComboBoxAddEntry(lb, room.m_translatedName, GameSpyColor[GSCOLOR_ROOM]); - GadgetComboBoxSetItemData(lb, selected, (void *)(room.m_groupID)); - } - } - else - { - DEBUG_LOG(("populateGroupRoomListbox(): skipping QM groupID %d\n", room.m_groupID)); - } - } - - GadgetComboBoxSetSelectedPos(lb, indexToSelect); -} - -static const char *rankNames[] = { - "Private", - "Corporal", - "Sergeant", - "Lieutenant", - "Captain", - "Major", - "Colonel", - "General", - "Brigadier", - "Commander", -}; - -const Image* LookupSmallRankImage(Int side, Int rankPoints) -{ - if (rankPoints == 0) - return NULL; - - Int rank = 0; - Int i = 0; - while( rankPoints >= TheRankPointValues->m_ranks[i + 1]) - ++i; - rank = i; - - if (rank < 0 || rank >= 10) - return NULL; - - AsciiString sideStr = "N"; - switch(side) - { - case 2: //USA - case 5: //Super Weapon - case 6: //Laser - case 7: //Air Force - sideStr = "USA"; - break; - - case 3: //China - case 8: //Tank - case 9: //Infantry - case 10: //Nuke - sideStr = "CHA"; - break; - - case 4: //GLA - case 11: //Toxin - case 12: //Demolition - case 13: //Stealth - sideStr = "GLA"; - break; - } - - AsciiString fullImageName; - fullImageName.format("%s-%s", rankNames[rank], sideStr.str()); - const Image *img = TheMappedImageCollection->findImageByName(fullImageName); - DEBUG_ASSERTLOG(img, ("*** Could not load small rank image '%s' from TheMappedImageCollection!\n", fullImageName.str())); - return img; -} - -static Int insertPlayerInListbox(const PlayerInfo& info, Color color) -{ - UnicodeString uStr; - uStr.translate(info.m_name); - - Int currentRank = info.m_rankPoints; - Int currentSide = info.m_side; - /* since PersistentStorage updates now update PlayerInfo, we don't need this. - if (info.m_profileID) - { - PSPlayerStats psStats = TheGameSpyPSMessageQueue->findPlayerStatsByID(info.m_profileID); - if (psStats.id) - { - currentRank = CalculateRank(psStats); - - PerGeneralMap::iterator it; - Int numGames = 0; - for(it = psStats.games.begin(); it != psStats.games.end(); ++it) - { - if(it->second >= numGames) - { - numGames = it->second; - currentSide = it->first; - } - } - if(numGames == 0 || psStats.gamesAsRandom >= numGames ) - { - currentSide = 0; - } - } - } - */ - - Bool isPreorder = TheGameSpyInfo->didPlayerPreorder(info.m_profileID); - - const Image *preorderImg = TheMappedImageCollection->findImageByName("OfficersClubsmall"); - Int w = (preorderImg)?preorderImg->getImageWidth():10; - //Int h = (preorderImg)?preorderImg->getImageHeight():10; - w = min(GadgetListBoxGetColumnWidth(listboxLobbyPlayers, 0), w); - Int h = w; - if (!isPreorder) - preorderImg = NULL; - - const Image *rankImg = LookupSmallRankImage(currentSide, currentRank); - -#if 0 //Officer's Club (preorder image) no longer used in Zero Hour - Int index = GadgetListBoxAddEntryImage(listboxLobbyPlayers, preorderImg, -1, 0, w, h); - GadgetListBoxAddEntryImage(listboxLobbyPlayers, rankImg, index, 1, w, h); - GadgetListBoxAddEntryText(listboxLobbyPlayers, uStr, color, index, 2); -#else - Int index = GadgetListBoxAddEntryImage(listboxLobbyPlayers, rankImg, -1, 0, w, h); - GadgetListBoxAddEntryText(listboxLobbyPlayers, uStr, color, index, 1); -#endif - return index; -} - - -void PopulateLobbyPlayerListbox(void) -{ - - if (!listboxLobbyPlayers) - return; - - // Display players - PlayerInfoMap *players = TheGameSpyInfo->getPlayerInfoMap(); - PlayerInfoMap::iterator it; - BuddyInfoMap *buddies = TheGameSpyInfo->getBuddyMap(); - BuddyInfoMap::iterator bIt; - if (listboxLobbyPlayers) - { - // save off old selection - Int maxSelectedItems = GadgetListBoxGetNumEntries(listboxLobbyPlayers); - Int *selectedIndices; - GadgetListBoxGetSelected(listboxLobbyPlayers, (Int *)(&selectedIndices)); - std::set selectedNames; - std::set::const_iterator selIt; - std::set indicesToSelect; - UnicodeString uStr; - Int numSelected = 0; - for (Int i=0; ibegin(); it != players->end(); ++it) - { - PlayerInfo info = it->second; - if (info.m_flags & PEER_FLAG_OP || TheGameSpyConfig->isPlayerVIP(info.m_profileID)) - { - Int index = insertPlayerInListbox(info, info.isIgnored()?GameSpyColor[GSCOLOR_PLAYER_IGNORED]:GameSpyColor[GSCOLOR_PLAYER_OWNER]); - - selIt = selectedNames.find(info.m_name); - if (selIt != selectedNames.end()) - { - DEBUG_LOG(("Marking index %d (%s) to re-select\n", index, info.m_name.str())); - indicesToSelect.insert(index); - } - } - } - - // Buddies - for (it = players->begin(); it != players->end(); ++it) - { - PlayerInfo info = it->second; - bIt = buddies->find(info.m_profileID); - if ( !(info.m_flags & PEER_FLAG_OP || TheGameSpyConfig->isPlayerVIP(info.m_profileID)) && bIt != buddies->end() ) - { - Int index = insertPlayerInListbox(info, info.isIgnored()?GameSpyColor[GSCOLOR_PLAYER_IGNORED]:GameSpyColor[GSCOLOR_PLAYER_BUDDY]); - - selIt = selectedNames.find(info.m_name); - if (selIt != selectedNames.end()) - { - DEBUG_LOG(("Marking index %d (%s) to re-select\n", index, info.m_name.str())); - indicesToSelect.insert(index); - } - } - } - - // Everyone else - for (it = players->begin(); it != players->end(); ++it) - { - PlayerInfo info = it->second; - bIt = buddies->find(info.m_profileID); - if ( !(info.m_flags & PEER_FLAG_OP || TheGameSpyConfig->isPlayerVIP(info.m_profileID)) && bIt == buddies->end() ) - { - Int index = insertPlayerInListbox(info, info.isIgnored()?GameSpyColor[GSCOLOR_PLAYER_IGNORED]:GameSpyColor[GSCOLOR_PLAYER_NORMAL]); - - selIt = selectedNames.find(info.m_name); - if (selIt != selectedNames.end()) - { - DEBUG_LOG(("Marking index %d (%s) to re-select\n", index, info.m_name.str())); - indicesToSelect.insert(index); - } - } - } - - // restore selection - if (indicesToSelect.size()) - { - std::set::const_iterator indexIt; - Int *newIndices = NEW Int[indicesToSelect.size()]; - for (i=0, indexIt = indicesToSelect.begin(); indexIt != indicesToSelect.end(); ++i, ++indexIt) - { - newIndices[i] = *indexIt; - DEBUG_LOG(("Queueing up index %d to re-select\n", *indexIt)); - } - GadgetListBoxSetSelected(listboxLobbyPlayers, newIndices, indicesToSelect.size()); - delete[] newIndices; - } - - if (indicesToSelect.size() != numSelected) - { - TheWindowManager->winSetLoneWindow(NULL); - } - - // restore top visible entry - GadgetListBoxSetTopVisibleEntry(listboxLobbyPlayers, previousTopIndex); - } - -} - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Lobby Menu */ -//------------------------------------------------------------------------------------------------- -void WOLLobbyMenuInit( WindowLayout *layout, void *userData ) -{ - nextScreen = NULL; - buttonPushed = false; - isShuttingDown = false; - - SetLobbyAttemptHostJoin(FALSE); // not trying to host or join - - gameListRefreshTime = 0; - playerListRefreshTime = 0; - - parentWOLLobbyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLCustomLobby.wnd:WOLLobbyMenuParent" ) ); - parent = TheWindowManager->winGetWindowFromId(NULL, parentWOLLobbyID); - - buttonBackID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:ButtonBack")); - buttonBack = TheWindowManager->winGetWindowFromId(parent, buttonBackID); - - buttonHostID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:ButtonHost")); - buttonHost = TheWindowManager->winGetWindowFromId(parent, buttonHostID); - - buttonRefreshID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:ButtonRefresh")); - buttonRefresh = TheWindowManager->winGetWindowFromId(parent, buttonRefreshID); - - buttonJoinID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:ButtonJoin")); - buttonJoin = TheWindowManager->winGetWindowFromId(parent, buttonJoinID); - buttonJoin->winEnable(FALSE); - - buttonBuddyID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:ButtonBuddy")); - buttonBuddy = TheWindowManager->winGetWindowFromId(parent, buttonBuddyID); - - buttonEmoteID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:ButtonEmote")); - buttonEmote = TheWindowManager->winGetWindowFromId(parent, buttonEmoteID); - - textEntryChatID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:TextEntryChat")); - textEntryChat = TheWindowManager->winGetWindowFromId(parent, textEntryChatID); - - listboxLobbyPlayersID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:ListboxPlayers")); - listboxLobbyPlayers = TheWindowManager->winGetWindowFromId(parent, listboxLobbyPlayersID); - listboxLobbyPlayers->winSetTooltipFunc(playerTooltip); - - listboxLobbyChatID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:ListboxChat")); - listboxLobbyChat = TheWindowManager->winGetWindowFromId(parent, listboxLobbyChatID); - TheGameSpyInfo->registerTextWindow(listboxLobbyChat); - - comboLobbyGroupRoomsID = TheNameKeyGenerator->nameToKey(AsciiString("WOLCustomLobby.wnd:ComboBoxGroupRooms")); - comboLobbyGroupRooms = TheWindowManager->winGetWindowFromId(parent, comboLobbyGroupRoomsID); - - GadgetTextEntrySetText(textEntryChat, UnicodeString.TheEmptyString); - - populateGroupRoomListbox(comboLobbyGroupRooms); - - // Show Menu - layout->hide( FALSE ); - - // if we're not in a room, this will join the best available one - if (!TheGameSpyInfo->getCurrentGroupRoom()) - { - if (groupRoomToJoin) - { - DEBUG_LOG(("WOLLobbyMenuInit() - rejoining group room %d\n", groupRoomToJoin)); - TheGameSpyInfo->joinGroupRoom(groupRoomToJoin); - groupRoomToJoin = 0; - } - else - { - DEBUG_LOG(("WOLLobbyMenuInit() - joining best group room\n")); - TheGameSpyInfo->joinBestGroupRoom(); - } - } - else - { - DEBUG_LOG(("WOLLobbyMenuInit() - not joining group room because we're already in one\n")); - } - - GrabWindowInfo(); - - TheGameSpyInfo->clearStagingRoomList(); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_STARTGAMELIST; - req.gameList.restrictGameList = TheGameSpyConfig->restrictGamesToLobby(); - TheGameSpyPeerMessageQueue->addRequest(req); - - // animate controls -// TheShell->registerWithAnimateManager(parent, WIN_ANIMATION_SLIDE_TOP, TRUE); - TheShell->showShellMap(TRUE); - TheGameSpyGame->reset(); - - CustomMatchPreferences pref; -// GameWindow *slider = TheWindowManager->winGetWindowFromId(parent, sliderChatAdjustID); -// if (slider) -// { -// GadgetSliderSetPosition(slider, pref.getChatSizeSlider()); -// doSliderTrack(slider, pref.getChatSizeSlider()); -// } -// - if (pref.usesLongGameList()) - { - ToggleGameListType(); - } - - // Set Keyboard to chat window - TheWindowManager->winSetFocus( textEntryChat ); - raiseMessageBoxes = true; - - TheLobbyQueuedUTMs.clear(); - justEntered = TRUE; - initialGadgetDelay = 2; - GameWindow *win = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("WOLCustomLobby.wnd:GadgetParent")); - if(win) - win->winHide(TRUE); - DontShowMainMenu = TRUE; - -} // WOLLobbyMenuInit - -//------------------------------------------------------------------------------------------------- -/** This is called when a shutdown is complete for this menu */ -//------------------------------------------------------------------------------------------------- -static void shutdownComplete( WindowLayout *layout ) -{ - - isShuttingDown = false; - - // hide the layout - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout, (nextScreen != NULL) ); - - if (nextScreen != NULL) - { - TheShell->push(nextScreen); - } - - nextScreen = NULL; - -} // end if - -//------------------------------------------------------------------------------------------------- -/** WOL Lobby Menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLLobbyMenuShutdown( WindowLayout *layout, void *userData ) -{ - CustomMatchPreferences pref; -// GameWindow *slider = TheWindowManager->winGetWindowFromId(parent, sliderChatAdjustID); -// if (slider) -// { -// pref.setChatSizeSlider(GadgetSliderGetPosition(slider)); -// } - if (GetGameInfoListBox()) - { - pref.setUsesLongGameList(FALSE); - } - else - { - pref.setUsesLongGameList(TRUE); - } - pref.write(); - - ReleaseWindowInfo(); - - TheGameSpyInfo->unregisterTextWindow(listboxLobbyChat); - - //TheGameSpyChat->stopListingGames(); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_STOPGAMELIST; - TheGameSpyPeerMessageQueue->addRequest(req); - - listboxLobbyChat = NULL; - listboxLobbyPlayers = NULL; - - isShuttingDown = true; - - // if we are shutting down for an immediate pop, skip the animations - Bool popImmediate = *(Bool *)userData; - if( popImmediate ) - { - - shutdownComplete( layout ); - return; - - } //end if - - TheShell->reverseAnimatewindow(); - DontShowMainMenu = FALSE; - - RaiseGSMessageBox(); - TheTransitionHandler->reverse("WOLCustomLobbyFade"); - -} // WOLLobbyMenuShutdown - -static void fillPlayerInfo(const PeerResponse *resp, PlayerInfo *info) -{ - info->m_name = resp->nick.c_str(); - info->m_profileID = resp->player.profileID; - info->m_flags = resp->player.flags; - info->m_wins = resp->player.wins; - info->m_losses = resp->player.losses; - info->m_locale = resp->locale.c_str(); - info->m_rankPoints= resp->player.rankPoints; - info->m_side = resp->player.side; - info->m_preorder = resp->player.preorder; -} - -#ifdef PERF_TEST -static const char* getMessageString(Int t) -{ - switch(t) - { - case PeerResponse::PEERRESPONSE_LOGIN: - return "login"; - case PeerResponse::PEERRESPONSE_DISCONNECT: - return "disconnect"; - case PeerResponse::PEERRESPONSE_MESSAGE: - return "message"; - case PeerResponse::PEERRESPONSE_GROUPROOM: - return "group room"; - case PeerResponse::PEERRESPONSE_STAGINGROOM: - return "staging room"; - case PeerResponse::PEERRESPONSE_STAGINGROOMPLAYERINFO: - return "staging room player info"; - case PeerResponse::PEERRESPONSE_JOINGROUPROOM: - return "group room join"; - case PeerResponse::PEERRESPONSE_CREATESTAGINGROOM: - return "staging room create"; - case PeerResponse::PEERRESPONSE_JOINSTAGINGROOM: - return "staging room join"; - case PeerResponse::PEERRESPONSE_PLAYERJOIN: - return "player join"; - case PeerResponse::PEERRESPONSE_PLAYERLEFT: - return "player part"; - case PeerResponse::PEERRESPONSE_PLAYERCHANGEDNICK: - return "player nick"; - case PeerResponse::PEERRESPONSE_PLAYERINFO: - return "player info"; - case PeerResponse::PEERRESPONSE_PLAYERCHANGEDFLAGS: - return "player flags"; - case PeerResponse::PEERRESPONSE_ROOMUTM: - return "room UTM"; - case PeerResponse::PEERRESPONSE_PLAYERUTM: - return "player UTM"; - case PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS: - return "QM status"; - case PeerResponse::PEERRESPONSE_GAMESTART: - return "game start"; - case PeerResponse::PEERRESPONSE_FAILEDTOHOST: - return "host failure"; - } - return "unknown"; -} -#endif // PERF_TEST - -//------------------------------------------------------------------------------------------------- -/** refreshGameList - The Bool is used to force refresh if the refresh button was hit.*/ -//------------------------------------------------------------------------------------------------- -static void refreshGameList( Bool forceRefresh ) -{ - Int refreshInterval = gameListRefreshInterval; - - if (forceRefresh || ((gameListRefreshTime == 0) || ((gameListRefreshTime + refreshInterval) <= timeGetTime()))) - { - if (TheGameSpyInfo->hasStagingRoomListChanged()) - { - //DEBUG_LOG(("################### refreshing game list\n")); - //DEBUG_LOG(("gameRefreshTime=%d, refreshInterval=%d, now=%d\n", gameListRefreshTime, refreshInterval, timeGetTime())); - RefreshGameListBoxes(); - gameListRefreshTime = timeGetTime(); - } else { - //DEBUG_LOG(("-")); - } - } else { - //DEBUG_LOG(("gameListRefreshTime: %d refreshInterval: %d\n")); - } -} -//------------------------------------------------------------------------------------------------- -/** refreshPlayerList - The Bool is used to force refresh if the refresh button was hit.*/ -//------------------------------------------------------------------------------------------------- -static void refreshPlayerList( Bool forceRefresh ) -{ - Int refreshInterval = playerListRefreshInterval; - - if (forceRefresh ||((playerListRefreshTime == 0) || ((playerListRefreshTime + refreshInterval) <= timeGetTime()))) - { - PopulateLobbyPlayerListbox(); - playerListRefreshTime = timeGetTime(); - } -} -//------------------------------------------------------------------------------------------------- -/** WOL Lobby Menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLLobbyMenuUpdate( WindowLayout * layout, void *userData) -{ - if(justEntered) - { - if(initialGadgetDelay == 1) - { - TheTransitionHandler->remove("MainMenuDefaultMenuLogoFade"); - TheTransitionHandler->setGroup("WOLCustomLobbyFade"); - initialGadgetDelay = 2; - justEntered = FALSE; - } - else - initialGadgetDelay--; - } - if (TheGameLogic->isInShellGame() && TheGameLogic->getFrame() == 1) - { - SignalUIInteraction(SHELL_SCRIPT_HOOK_GENERALS_ONLINE_ENTERED_FROM_GAME); - } - - - // We'll only be successful if we've requested to - if(isShuttingDown && TheShell->isAnimFinished() && TheTransitionHandler->isFinished()) - shutdownComplete(layout); - - if (raiseMessageBoxes) - { - RaiseGSMessageBox(); - raiseMessageBoxes = false; - } - - if (TheShell->isAnimFinished() && TheTransitionHandler->isFinished() && !buttonPushed && TheGameSpyPeerMessageQueue) - { - HandleBuddyResponses(); - HandlePersistentStorageResponses(); - -#ifdef PERF_TEST - UnsignedInt start = timeGetTime(); - UnsignedInt end = timeGetTime(); - std::list responses; - Int numMessages = 0; -#endif // PERF_TEST - - Int allowedMessages = TheGameSpyInfo->getMaxMessagesPerUpdate(); - Bool sawImportantMessage = FALSE; - Bool shouldRepopulatePlayers = FALSE; - PeerResponse resp; - while (allowedMessages-- && !sawImportantMessage && TheGameSpyPeerMessageQueue->getResponse( resp )) - { -#ifdef PERF_TEST - ++numMessages; - responses.push_back(resp.peerResponseType); -#endif // PERF_TEST - switch (resp.peerResponseType) - { - case PeerResponse::PEERRESPONSE_JOINGROUPROOM: - sawImportantMessage = TRUE; - if (resp.joinGroupRoom.ok) - { - //buttonPushed = true; - TheGameSpyInfo->setCurrentGroupRoom(resp.joinGroupRoom.id); - TheGameSpyInfo->getPlayerInfoMap()->clear(); - GroupRoomMap::iterator iter = TheGameSpyInfo->getGroupRoomList()->find(resp.joinGroupRoom.id); - if (iter != TheGameSpyInfo->getGroupRoomList()->end()) - { - GameSpyGroupRoom room = iter->second; - UnicodeString msg; - msg.format(TheGameText->fetch("GUI:LobbyJoined"), room.m_translatedName.str()); - TheGameSpyInfo->addText(msg, GameSpyColor[GSCOLOR_DEFAULT], NULL); - } - } - else - { - DEBUG_LOG(("WOLLobbyMenuUpdate() - joining best group room\n")); - TheGameSpyInfo->joinBestGroupRoom(); - } - populateGroupRoomListbox(comboLobbyGroupRooms); - shouldRepopulatePlayers = TRUE; - break; - case PeerResponse::PEERRESPONSE_PLAYERCHANGEDFLAGS: - { - PlayerInfo p; - fillPlayerInfo(&resp, &p); - TheGameSpyInfo->updatePlayerInfo(p); - shouldRepopulatePlayers = TRUE; - } - break; - case PeerResponse::PEERRESPONSE_PLAYERCHANGEDNICK: - { - PlayerInfo p; - fillPlayerInfo(&resp, &p); - TheGameSpyInfo->updatePlayerInfo(p); - shouldRepopulatePlayers = TRUE; - } - break; - case PeerResponse::PEERRESPONSE_PLAYERINFO: - { - PlayerInfo p; - fillPlayerInfo(&resp, &p); - TheGameSpyInfo->updatePlayerInfo(p); - shouldRepopulatePlayers = TRUE; - } - break; - case PeerResponse::PEERRESPONSE_PLAYERJOIN: - { - if (resp.player.roomType == GroupRoom) - { - PlayerInfo p; - fillPlayerInfo(&resp, &p); - TheGameSpyInfo->updatePlayerInfo(p); - shouldRepopulatePlayers = TRUE; - } - } - break; - case PeerResponse::PEERRESPONSE_PLAYERUTM: - case PeerResponse::PEERRESPONSE_ROOMUTM: - { - DEBUG_LOG(("Putting off a UTM in the lobby\n")); - TheLobbyQueuedUTMs.push_back(resp); - } - break; - case PeerResponse::PEERRESPONSE_PLAYERLEFT: - { - PlayerInfo p; - fillPlayerInfo(&resp, &p); - TheGameSpyInfo->playerLeftGroupRoom(resp.nick.c_str()); - shouldRepopulatePlayers = TRUE; - } - break; - case PeerResponse::PEERRESPONSE_MESSAGE: - { - TheGameSpyInfo->addChat(resp.nick.c_str(), resp.message.profileID, - UnicodeString(resp.text.c_str()), !resp.message.isPrivate, resp.message.isAction, listboxLobbyChat); - } - break; - case PeerResponse::PEERRESPONSE_DISCONNECT: - { - sawImportantMessage = TRUE; - UnicodeString title, body; - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", resp.discon.reason); - title = TheGameText->fetch( "GUI:GSErrorTitle" ); - body = TheGameText->fetch( disconMunkee ); - GameSpyCloseAllOverlays(); - GSMessageBoxOk( title, body ); - TheGameSpyInfo->reset(); - TheShell->pop(); - } - case PeerResponse::PEERRESPONSE_CREATESTAGINGROOM: - { - sawImportantMessage = TRUE; - SetLobbyAttemptHostJoin(FALSE); - if (resp.createStagingRoom.result == PEERJoinSuccess) - { - // Woohoo! On to our next screen! - buttonPushed = true; - nextScreen = "Menus/GameSpyGameOptionsMenu.wnd"; - TheShell->pop(); - TheGameSpyInfo->markAsStagingRoomHost(); - TheGameSpyInfo->setGameOptions(); - } - } - break; - case PeerResponse::PEERRESPONSE_JOINSTAGINGROOM: - { - sawImportantMessage = TRUE; - SetLobbyAttemptHostJoin(FALSE); - Bool isHostPresent = TRUE; - if (resp.joinStagingRoom.ok == PEERTrue) - { - GameSpyStagingRoom *room = TheGameSpyInfo->getCurrentStagingRoom(); - if (!room) - { - isHostPresent = FALSE; - } - else - { - isHostPresent = FALSE; - for (Int i=0; igetConstSlot(0)->getName()); - const char *firstPlayer = resp.stagingRoomPlayerNames[i].c_str(); - if (!strcmp(hostName.str(), firstPlayer)) - { - DEBUG_LOG(("Saw host %s == %s in slot %d\n", hostName.str(), firstPlayer, i)); - isHostPresent = TRUE; - } - } - } - } - if (resp.joinStagingRoom.ok == PEERTrue && isHostPresent) - { - // Woohoo! On to our next screen! - buttonPushed = true; - nextScreen = "Menus/GameSpyGameOptionsMenu.wnd"; - TheShell->pop(); - } - else - { - UnicodeString s; - - switch(resp.joinStagingRoom.result) - { - case PEERFullRoom: // The room is full. - s = TheGameText->fetch("GUI:JoinFailedRoomFull"); - break; - case PEERInviteOnlyRoom: // The room is invite only. - s = TheGameText->fetch("GUI:JoinFailedInviteOnly"); - break; - case PEERBannedFromRoom: // The local user is banned from the room. - s = TheGameText->fetch("GUI:JoinFailedBannedFromRoom"); - break; - case PEERBadPassword: // An incorrect password (or none) was given for a passworded room. - s = TheGameText->fetch("GUI:JoinFailedBadPassword"); - break; - case PEERAlreadyInRoom: // The local user is already in or entering a room of the same type. - s = TheGameText->fetch("GUI:JoinFailedAlreadyInRoom"); - break; - case PEERNoConnection: // Can't join a room if there's no chat connection. - s = TheGameText->fetch("GUI:JoinFailedNoConnection"); - break; - default: - s = TheGameText->fetch("GUI:JoinFailedDefault"); - break; - } - GSMessageBoxOk(TheGameText->fetch("GUI:JoinFailedDefault"), s); - if (groupRoomToJoin) - { - DEBUG_LOG(("WOLLobbyMenuUpdate() - rejoining group room %d\n", groupRoomToJoin)); - TheGameSpyInfo->joinGroupRoom(groupRoomToJoin); - groupRoomToJoin = 0; - } - else - { - DEBUG_LOG(("WOLLobbyMenuUpdate() - joining best group room\n")); - TheGameSpyInfo->joinBestGroupRoom(); - } - } - } - break; - case PeerResponse::PEERRESPONSE_STAGINGROOMLISTCOMPLETE: - TheGameSpyInfo->sawFullGameList(); - break; - case PeerResponse::PEERRESPONSE_STAGINGROOM: - { - GameSpyStagingRoom room; - switch(resp.stagingRoom.action) - { - case PEER_CLEAR: - TheGameSpyInfo->clearStagingRoomList(); - //TheGameSpyInfo->addText( UnicodeString(L"gameList: PEER_CLEAR"), GameSpyColor[GSCOLOR_DEFAULT], listboxLobbyChat ); - break; - case PEER_ADD: - case PEER_UPDATE: - { - if (resp.stagingRoom.percentComplete == 100) - { - TheGameSpyInfo->sawFullGameList(); - } - - //if (ParseAsciiStringToGameInfo(&room, resp.stagingRoomMapName.c_str())) - //if (ParseAsciiStringToGameInfo(&room, resp.stagingServerGameOptions.c_str())) - Bool serverOk = TRUE; - if (!resp.stagingRoomMapName.length()) - { - serverOk = FALSE; - } - // fix for ghost game problem - need to iterate over all resp.stagingRoomPlayerNames[i] - Bool sawSelf = FALSE; - //for (Int i=0; igetLocalName() == resp.stagingRoomPlayerNames[0].c_str()) - { - sawSelf = TRUE; // don't show ghost games for myself - } - //} - if (sawSelf) - serverOk = FALSE; - - if (serverOk) - { - room.setGameName(UnicodeString(resp.stagingServerName.c_str())); - room.setID(resp.stagingRoom.id); - room.setHasPassword(resp.stagingRoom.requiresPassword); - room.setVersion(resp.stagingRoom.version); - room.setExeCRC(resp.stagingRoom.exeCRC); - room.setIniCRC(resp.stagingRoom.iniCRC); - room.setAllowObservers(resp.stagingRoom.allowObservers); - room.setUseStats(resp.stagingRoom.useStats); - room.setPingString(resp.stagingServerPingString.c_str()); - room.setLadderIP(resp.stagingServerLadderIP.c_str()); - room.setLadderPort(resp.stagingRoom.ladderPort); - room.setReportedNumPlayers(resp.stagingRoom.numPlayers); - room.setReportedMaxPlayers(resp.stagingRoom.maxPlayers); - room.setReportedNumObservers(resp.stagingRoom.numObservers); - - Int i; - AsciiString gsMapName = resp.stagingRoomMapName.c_str(); - AsciiString mapName = ""; - for (i=0; iportableMapPathToRealMapPath(mapName)); - - Int numPlayers = 0; - for (i=0; isetWins( resp.stagingRoom.wins[i] ); - slot->setLosses( resp.stagingRoom.losses[i] ); - slot->setProfileID( resp.stagingRoom.profileID[i] ); - slot->setPlayerTemplate( resp.stagingRoom.faction[i] ); - slot->setColor( resp.stagingRoom.color[i] ); - if (resp.stagingRoom.profileID[i] == SLOT_EASY_AI) - { - slot->setState(SLOT_EASY_AI); - ++numPlayers; - } - else if (resp.stagingRoom.profileID[i] == SLOT_MED_AI) - { - slot->setState(SLOT_MED_AI); - ++numPlayers; - } - else if (resp.stagingRoom.profileID[i] == SLOT_BRUTAL_AI) - { - slot->setState(SLOT_BRUTAL_AI); - ++numPlayers; - } - else if (resp.stagingRoomPlayerNames[i].length()) - { - UnicodeString nameUStr; - nameUStr.translate(resp.stagingRoomPlayerNames[i].c_str()); - slot->setState(SLOT_PLAYER, nameUStr); - ++numPlayers; - } - else - { - slot->setState(SLOT_OPEN); - } - } - } - DEBUG_ASSERTCRASH(numPlayers, ("Game had no players!\n")); - //DEBUG_LOG(("Saw room: hasPass=%d, allowsObservers=%d\n", room.getHasPassword(), room.getAllowObservers())); - if (resp.stagingRoom.action == PEER_ADD) - { - TheGameSpyInfo->addStagingRoom(room); - //TheGameSpyInfo->addText( UnicodeString(L"gameList: PEER_ADD"), GameSpyColor[GSCOLOR_DEFAULT], listboxLobbyChat ); - } - else - { - TheGameSpyInfo->updateStagingRoom(room); - //TheGameSpyInfo->addText( UnicodeString(L"gameList: PEER_UPDATE"), GameSpyColor[GSCOLOR_DEFAULT], listboxLobbyChat ); - } - } - else - { - room.setID(resp.stagingRoom.id); - TheGameSpyInfo->removeStagingRoom(room); - //TheGameSpyInfo->addText( UnicodeString(L"gameList: PEER_UPDATE FAILED"), GameSpyColor[GSCOLOR_DEFAULT], listboxLobbyChat ); - } - break; - } - case PEER_REMOVE: - room.setID(resp.stagingRoom.id); - TheGameSpyInfo->removeStagingRoom(room); - //TheGameSpyInfo->addText( UnicodeString(L"gameList: PEER_REMOVE"), GameSpyColor[GSCOLOR_DEFAULT], listboxLobbyChat ); - break; - default: - //TheGameSpyInfo->addText( UnicodeString(L"gameList: Unknown"), GameSpyColor[GSCOLOR_DEFAULT], listboxLobbyChat ); - break; - } - } - break; - } - } -#if 0 - if (shouldRepopulatePlayers) - { - PopulateLobbyPlayerListbox(); - } -#else - refreshPlayerList(); -#endif - -#ifdef PERF_TEST - // check performance - end = timeGetTime(); - PERF_LOG(("Frame time was %d ms\n", end-start)); - std::list::const_iterator it; - for (it = responses.begin(); it != responses.end(); ++it) - { - PERF_LOG((" %s\n", getMessageString(*it))); - } - PERF_LOG(("\n")); -#endif // PERF_TEST - -#if 0 -// Removed 2-17-03 to pull out into a function so we can do the same checks - Int refreshInterval = gameListRefreshInterval; - - if ((gameListRefreshTime == 0) || ((gameListRefreshTime + refreshInterval) <= timeGetTime())) - { - if (TheGameSpyInfo->hasStagingRoomListChanged()) - { - //DEBUG_LOG(("################### refreshing game list\n")); - //DEBUG_LOG(("gameRefreshTime=%d, refreshInterval=%d, now=%d\n", gameListRefreshTime, refreshInterval, timeGetTime())); - RefreshGameListBoxes(); - gameListRefreshTime = timeGetTime(); - } else { - //DEBUG_LOG(("-")); - } - } else { - //DEBUG_LOG(("gameListRefreshTime: %d refreshInterval: %d\n")); - } -#else - refreshGameList(); -#endif - } -}// WOLLobbyMenuUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Lobby Menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLLobbyMenuInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - if (buttonPushed) - break; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonBack, buttonBackID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// WOLLobbyMenuInput - -//static void doSliderTrack(GameWindow *control, Int val) -//{ -// Int sliderW, sliderH, sliderX, sliderY; -// control->winGetPosition(&sliderX, &sliderY); -// control->winGetSize(&sliderW, &sliderH); -// Real cursorY = sliderY + (100-val)*0.01f*sliderH; -// -// extern GameWindow *listboxLobbyGamesSmall; -// extern GameWindow *listboxLobbyGamesLarge; -// extern GameWindow *listboxLobbyGameInfo; -// -// static Int gwsX = 0, gwsY = 0, gwsW = 0, gwsH = 0; -// static Int gwlX = 0, gwlY = 0, gwlW = 0, gwlH = 0; -// static Int gwiX = 0, gwiY = 0, gwiW = 0, gwiH = 0; -// static Int pwX = 0, pwY = 0, pwW = 0, pwH = 0; -// static Int chatPosX = 0, chatPosY = 0, chatW = 0, chatH = 0; -// static Int spacing = 0; -// if (chatPosX == 0) -// { -// listboxLobbyChat->winGetPosition(&chatPosX, &chatPosY); -// listboxLobbyChat->winGetSize(&chatW, &chatH); -// -//// listboxLobbyGamesSmall->winGetPosition(&gwsX, &gwsY); -//// listboxLobbyGamesSmall->winGetSize(&gwsW, &gwsH); -// -// listboxLobbyGamesLarge->winGetPosition(&gwlX, &gwlY); -// listboxLobbyGamesLarge->winGetSize(&gwlW, &gwlH); -// -//// listboxLobbyGameInfo->winGetPosition(&gwiX, &gwiY); -//// listboxLobbyGameInfo->winGetSize(&gwiW, &gwiH); -//// -// listboxLobbyPlayers->winGetPosition(&pwX, &pwY); -// listboxLobbyPlayers->winGetSize(&pwW, &pwH); -// -// spacing = chatPosY - pwY - pwH; -// } -// -// Int newChatY = cursorY; -// Int newChatH = chatH + chatPosY - newChatY; -// listboxLobbyChat->winSetPosition(chatPosX, newChatY); -// listboxLobbyChat->winSetSize(chatW, newChatH); -// -// Int newH = cursorY - pwY - spacing; -// listboxLobbyPlayers->winSetSize(pwW, newH); -//// listboxLobbyGamesSmall->winSetSize(gwsW, newH); -// listboxLobbyGamesLarge->winSetSize(gwlW, newH); -//// listboxLobbyGameInfo->winSetSize(gwiW, newH); - - -//------------------------------------------------------------------------------------------------- -/** WOL Lobby Menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLLobbyMenuSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - static NameKeyType buttonGameListTypeToggleID = NAMEKEY_INVALID; - - switch( msg ) - { - - - //--------------------------------------------------------------------------------------------- - case GWM_CREATE: - { - buttonGameListTypeToggleID = NAMEKEY("WOLCustomLobby.wnd:ButtonGameListToggle"); -// sliderChatAdjustID = NAMEKEY("WOLCustomLobby.wnd:SliderChatAdjust"); - - break; - } // case GWM_DESTROY: - - //--------------------------------------------------------------------------------------------- - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - //--------------------------------------------------------------------------------------------- - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - //--------------------------------------------------------------------------------------------- - case GLM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if ( controlID == GetGameListBoxID() ) - { - int rowSelected = mData2; - if( rowSelected >= 0 ) - { - buttonJoin->winEnable(TRUE); - static UnsignedInt lastFrame = 0; - static Int lastID = -1; - UnsignedInt now = TheGameClient->getFrame(); - - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_GETEXTENDEDSTAGINGROOMINFO; - req.stagingRoom.id = (Int)GadgetListBoxGetItemData(control, rowSelected, 0); - - if (lastID != req.stagingRoom.id || now > lastFrame + 60) - { - TheGameSpyPeerMessageQueue->addRequest(req); - } - - lastID = req.stagingRoom.id; - lastFrame = now; - } - else - { - buttonJoin->winEnable(FALSE); - } - if (GetGameInfoListBox()) - { - RefreshGameInfoListBox(GetGameListBox(), GetGameInfoListBox()); - } - } //if ( controlID == GetGameListBoxID() ) - - break; - } - - //--------------------------------------------------------------------------------------------- - case GBM_SELECTED: - { - if (buttonPushed) - break; - - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if (HandleSortButton((NameKeyType)controlID)) - break; - - // If we back out, just bail - we haven't gotten far enough to need to log out - if ( controlID == buttonBackID ) - { - if (s_tryingToHostOrJoin) - break; - - // Leave any group room, then pop off the screen - TheGameSpyInfo->leaveGroupRoom(); - - SetLobbyAttemptHostJoin( TRUE ); // pretend, since we don't want to queue up another action - buttonPushed = true; - nextScreen = "Menus/WOLWelcomeMenu.wnd"; - TheShell->pop(); - - } //if ( controlID == buttonBack ) - else if ( controlID == buttonRefreshID ) - { - // Added 2/17/03 added the game refresh button - refreshGameList(TRUE); - refreshPlayerList(TRUE); - } - else if ( controlID == buttonHostID ) - { - if (s_tryingToHostOrJoin) - break; - - SetLobbyAttemptHostJoin( TRUE ); - TheLobbyQueuedUTMs.clear(); - groupRoomToJoin = TheGameSpyInfo->getCurrentGroupRoom(); - GameSpyOpenOverlay(GSOVERLAY_GAMEOPTIONS); - } - else if ( controlID == buttonJoinID ) - { - if (s_tryingToHostOrJoin) - break; - - TheLobbyQueuedUTMs.clear(); - // Look for a game to join - groupRoomToJoin = TheGameSpyInfo->getCurrentGroupRoom(); - Int selected; - GadgetListBoxGetSelected(GetGameListBox(), &selected); - if (selected >= 0) - { - Int selectedID = (Int)GadgetListBoxGetItemData(GetGameListBox(), selected); - if (selectedID > 0) - { - StagingRoomMap *srm = TheGameSpyInfo->getStagingRoomList(); - StagingRoomMap::iterator srmIt = srm->find(selectedID); - if (srmIt != srm->end()) - { - GameSpyStagingRoom *roomToJoin = srmIt->second; - if (!roomToJoin || roomToJoin->getExeCRC() != TheGlobalData->m_exeCRC || roomToJoin->getIniCRC() != TheGlobalData->m_iniCRC) - { - // bad crc. don't go. - DEBUG_LOG(("WOLLobbyMenuSystem - CRC mismatch with the game I'm trying to join. My CRC's - EXE:0x%08X INI:0x%08X Their CRC's - EXE:0x%08x INI:0x%08x\n", TheGlobalData->m_exeCRC, TheGlobalData->m_iniCRC, roomToJoin->getExeCRC(), roomToJoin->getIniCRC())); -#if defined(_DEBUG) || defined(_INTERNAL) - if (TheGlobalData->m_netMinPlayers) - { - GSMessageBoxOk(TheGameText->fetch("GUI:JoinFailedDefault"), TheGameText->fetch("GUI:JoinFailedCRCMismatch")); - break; - } - else if (g_fakeCRC) - { - TheWritableGlobalData->m_exeCRC = roomToJoin->getExeCRC(); - TheWritableGlobalData->m_iniCRC = roomToJoin->getIniCRC(); - } -#else - GSMessageBoxOk(TheGameText->fetch("GUI:JoinFailedDefault"), TheGameText->fetch("GUI:JoinFailedCRCMismatch")); - break; -#endif - } - Bool unknownLadder = (roomToJoin->getLadderPort() && TheLadderList->findLadder(roomToJoin->getLadderIP(), roomToJoin->getLadderPort()) == NULL); - if (unknownLadder) - { - GSMessageBoxOk(TheGameText->fetch("GUI:JoinFailedDefault"), TheGameText->fetch("GUI:JoinFailedUnknownLadder")); - break; - } - if (roomToJoin->getNumPlayers() == MAX_SLOTS) - { - GSMessageBoxOk(TheGameText->fetch("GUI:JoinFailedDefault"), TheGameText->fetch("GUI:JoinFailedRoomFull")); - break; - } - TheGameSpyInfo->markAsStagingRoomJoiner(selectedID); - TheGameSpyGame->setGameName(roomToJoin->getGameName()); - TheGameSpyGame->setLadderIP(roomToJoin->getLadderIP()); - TheGameSpyGame->setLadderPort(roomToJoin->getLadderPort()); - SetLobbyAttemptHostJoin( TRUE ); - if (roomToJoin->getHasPassword()) - { - GameSpyOpenOverlay(GSOVERLAY_GAMEPASSWORD); - } - else - { - // no password - just join it - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_JOINSTAGINGROOM; - req.text = srmIt->second->getGameName().str(); - req.stagingRoom.id = selectedID; - req.password = ""; - TheGameSpyPeerMessageQueue->addRequest(req); - } - } - } - else - { - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:NoGameInfo"), NULL); - } - } - else - { - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:NoGameSelected"), NULL); - } - } - else if ( controlID == buttonBuddyID ) - { - GameSpyToggleOverlay( GSOVERLAY_BUDDY ); - } - else if ( controlID == buttonGameListTypeToggleID ) - { - ToggleGameListType(); - } - else if ( controlID == buttonEmoteID ) - { - // read the user's input and clear the entry box - UnicodeString txtInput; - txtInput.set(GadgetTextEntryGetText( textEntryChat )); - GadgetTextEntrySetText(textEntryChat, UnicodeString::TheEmptyString); - txtInput.trim(); - if (!txtInput.isEmpty()) - { - // Send the message - TheGameSpyInfo->sendChat( txtInput, FALSE, listboxLobbyPlayers ); // 'emote' button now just sends text - } - } - - break; - }// case GBM_SELECTED: - - //--------------------------------------------------------------------------------------------- - case GCM_SELECTED: - { - if (s_tryingToHostOrJoin) - break; - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if( controlID == comboLobbyGroupRoomsID ) - { - int rowSelected = -1; - GadgetComboBoxGetSelectedPos(control, &rowSelected); - - DEBUG_LOG(("Row selected = %d\n", rowSelected)); - if (rowSelected >= 0) - { - Int groupID; - groupID = (Int)GadgetComboBoxGetItemData(comboLobbyGroupRooms, rowSelected); - DEBUG_LOG(("ItemData was %d, current Group Room is %d\n", groupID, TheGameSpyInfo->getCurrentGroupRoom())); - if (groupID && groupID != TheGameSpyInfo->getCurrentGroupRoom()) - { - TheGameSpyInfo->leaveGroupRoom(); - TheGameSpyInfo->joinGroupRoom(groupID); - - if (TheGameSpyConfig->restrictGamesToLobby()) - { - TheGameSpyInfo->clearStagingRoomList(); - RefreshGameListBoxes(); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_STARTGAMELIST; - req.gameList.restrictGameList = TRUE; - TheGameSpyPeerMessageQueue->addRequest(req); - } - } - } - } - } // case GCM_SELECTED - break; - - //--------------------------------------------------------------------------------------------- - case GLM_DOUBLE_CLICKED: - { - if (buttonPushed) - break; - - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if (controlID == GetGameListBoxID()) - { - int rowSelected = mData2; - - if (rowSelected >= 0) - { - GadgetListBoxSetSelected( control, rowSelected ); - GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonJoinID ); - - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)button, buttonJoinID ); - } - } - break; - }// case GLM_DOUBLE_CLICKED: - - //--------------------------------------------------------------------------------------------- - case GLM_RIGHT_CLICKED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if( controlID == listboxLobbyPlayersID ) - { - RightClickStruct *rc = (RightClickStruct *)mData2; - WindowLayout *rcLayout = NULL; - GameWindow *rcMenu; - if(rc->pos < 0) - { - GadgetListBoxSetSelected(control, -1); - break; - } - - GPProfile profileID = 0; - AsciiString aName; - aName.translate(GadgetListBoxGetText(control, rc->pos, COLUMN_PLAYERNAME)); - PlayerInfoMap::iterator it = TheGameSpyInfo->getPlayerInfoMap()->find(aName); - if (it != TheGameSpyInfo->getPlayerInfoMap()->end()) - profileID = it->second.m_profileID; - - Bool isBuddy = FALSE; - if (profileID <= 0) - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCNoProfileMenu.wnd")); - else - { - if (profileID == TheGameSpyInfo->getLocalProfileID()) - { - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCLocalPlayerMenu.wnd")); - } - else if(TheGameSpyInfo->isBuddy(profileID)) - { - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCBuddiesMenu.wnd")); - isBuddy = TRUE; - } - else - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCNonBuddiesMenu.wnd")); - } - if(!rcLayout) - break; - - GadgetListBoxSetSelected(control, rc->pos); - - rcMenu = rcLayout->getFirstWindow(); - rcMenu->winGetLayout()->runInit(); - rcMenu->winBringToTop(); - rcMenu->winHide(FALSE); - setUnignoreText( rcLayout, aName, profileID); - ICoord2D rcSize, rcPos; - rcMenu->winGetSize(&rcSize.x, &rcSize.y); - rcPos.x = rc->mouseX; - rcPos.y = rc->mouseY; - if(rc->mouseX + rcSize.x > TheDisplay->getWidth()) - rcPos.x = TheDisplay->getWidth() - rcSize.x; - if(rc->mouseY + rcSize.y > TheDisplay->getHeight()) - rcPos.y = TheDisplay->getHeight() - rcSize.y; - rcMenu->winSetPosition(rcPos.x, rcPos.y); - - GameSpyRCMenuData *rcData = NEW GameSpyRCMenuData; - rcData->m_id = profileID; - rcData->m_nick = aName; - rcData->m_itemType = (isBuddy)?ITEM_BUDDY:ITEM_NONBUDDY; - rcMenu->winSetUserData((void *)rcData); - TheWindowManager->winSetLoneWindow(rcMenu); - } - else if( controlID == GetGameListBoxID() ) - { - RightClickStruct *rc = (RightClickStruct *)mData2; - WindowLayout *rcLayout = NULL; - GameWindow *rcMenu; - if(rc->pos < 0) - { - GadgetListBoxSetSelected(control, -1); - break; - } - - Int selectedID = (Int)GadgetListBoxGetItemData(control, rc->pos); - if (selectedID > 0) - { - StagingRoomMap *srm = TheGameSpyInfo->getStagingRoomList(); - StagingRoomMap::iterator srmIt = srm->find(selectedID); - if (srmIt != srm->end()) - { - GameSpyStagingRoom *theRoom = srmIt->second; - if (!theRoom) - break; - const LadderInfo *linfo = TheLadderList->findLadder(theRoom->getLadderIP(), theRoom->getLadderPort()); - if (linfo) - { - rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCGameDetailsMenu.wnd")); - if (!rcLayout) - break; - - GadgetListBoxSetSelected(control, rc->pos); - - rcMenu = rcLayout->getFirstWindow(); - rcMenu->winGetLayout()->runInit(); - rcMenu->winBringToTop(); - rcMenu->winHide(FALSE); - rcMenu->winSetPosition(rc->mouseX, rc->mouseY); - - rcMenu->winSetUserData((void *)selectedID); - TheWindowManager->winSetLoneWindow(rcMenu); - } - } - } - } - break; - } - -// //--------------------------------------------------------------------------------------------- -// case GSM_SLIDER_TRACK: -// { -// if (buttonPushed) -// break; -// -// GameWindow *control = (GameWindow *)mData1; -// Int val = (Int)mData2; -// Int controlID = control->winGetWindowId(); -// if (controlID == sliderChatAdjustID) -// { -// doSliderTrack(control, val); -// } -// break; -// } - - //--------------------------------------------------------------------------------------------- - case GEM_EDIT_DONE: - { - if (buttonPushed) - break; - - // read the user's input and clear the entry box - UnicodeString txtInput; - txtInput.set(GadgetTextEntryGetText( textEntryChat )); - GadgetTextEntrySetText(textEntryChat, UnicodeString::TheEmptyString); - txtInput.trim(); - if (!txtInput.isEmpty()) - { - // Send the message - if (!handleLobbySlashCommands(txtInput)) - { - TheGameSpyInfo->sendChat( txtInput, false, listboxLobbyPlayers ); - } - } - break; - } - - //--------------------------------------------------------------------------------------------- - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLLobbyMenuSystem diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLocaleSelectPopup.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLocaleSelectPopup.cpp deleted file mode 100644 index 5da99177a7d..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLocaleSelectPopup.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLLocaleSelectPopup.cpp -// Author: Matt Campbell, December 2001 -// Description: WOL locale select popup -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "GameClient/GameText.h" -#include "Common/CustomMatchPreferences.h" -#include "Common/GameEngine.h" -#include "Common/GameSpyMiscPreferences.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetListBox.h" -#include "Common/GlobalData.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PersistentStorageDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentLocaleSelectID = NAMEKEY_INVALID; -static NameKeyType buttonOkID = NAMEKEY_INVALID; -static NameKeyType listboxLocaleID = NAMEKEY_INVALID; - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentLocaleSelect = NULL; -static GameWindow *buttonOk = NULL; -static GameWindow *listboxLocale = NULL; - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Status Menu */ -//------------------------------------------------------------------------------------------------- -void WOLLocaleSelectInit( WindowLayout *layout, void *userData ) -{ - parentLocaleSelectID = TheNameKeyGenerator->nameToKey( AsciiString( "PopupLocaleSelect.wnd:ParentLocaleSelect" ) ); - buttonOkID = TheNameKeyGenerator->nameToKey( AsciiString( "PopupLocaleSelect.wnd:ButtonOk" ) ); - listboxLocaleID = TheNameKeyGenerator->nameToKey( AsciiString( "PopupLocaleSelect.wnd:ListBoxLocaleSelect" ) ); - parentLocaleSelect = TheWindowManager->winGetWindowFromId( NULL, parentLocaleSelectID ); - buttonOk = TheWindowManager->winGetWindowFromId( NULL, buttonOkID); - listboxLocale = TheWindowManager->winGetWindowFromId( NULL, listboxLocaleID); - - for (int i=LOC_MIN; i<=LOC_MAX; ++i) - { - AsciiString id; - id.format("WOL:Locale%2.2d", i); - GadgetListBoxAddEntryText(listboxLocale, TheGameText->fetch(id.str()), GameSpyColor[GSCOLOR_DEFAULT], -1, -1); - } - GadgetListBoxSetSelected(listboxLocale, 0); - - // Show Menu - layout->hide( FALSE ); - - // Set Keyboard to Main Parent - TheWindowManager->winSetFocus( parentLocaleSelect ); - TheWindowManager->winSetModal( parentLocaleSelect ); -} // WOLLocaleSelectInit - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLLocaleSelectShutdown( WindowLayout *layout, void *userData ) -{ - - // hide menu - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout ); - -} // WOLLocaleSelectShutdown - - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLLocaleSelectUpdate( WindowLayout * layout, void *userData) -{ - -}// WOLLocaleSelectUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLLocaleSelectInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { -// UnsignedByte key = mData1; -// UnsignedByte state = mData2; - - // ---------------------------------------------------------------------------------------- - // don't let key fall through anywhere else - return MSG_HANDLED; - } // end char - } // end switch( msg ) - return MSG_IGNORED; -}// WOLLocaleSelectInput - -//Int getRegistryNicknameOffset(AsciiString nick); /// @todo: mdc remove this once we can save ini pref files -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLLocaleSelectSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - - switch( msg ) - { - - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - case GBM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if ( controlID == buttonOkID ) - { - int selected; - GadgetListBoxGetSelected(listboxLocale, &selected); - if (selected < 0) - return MSG_HANDLED; // can't select nothing! - PSRequest psReq; - psReq.requestType = PSRequest::PSREQUEST_UPDATEPLAYERLOCALE; - psReq.player.locale = selected + LOC_MIN; - psReq.email = TheGameSpyInfo->getLocalEmail().str(); - psReq.nick = TheGameSpyInfo->getLocalBaseName().str(); - psReq.password = TheGameSpyInfo->getLocalPassword().str(); - psReq.player.id = TheGameSpyInfo->getLocalProfileID(); - - TheGameSpyPSMessageQueue->addRequest(psReq); - GameSpyCloseOverlay(GSOVERLAY_LOCALESELECT); - - GameSpyMiscPreferences cPref; - cPref.setLocale(psReq.player.locale); - cPref.write(); - - PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(TheGameSpyInfo->getLocalProfileID()); - stats.locale = psReq.player.locale; - if (stats.id == TheGameSpyInfo->getLocalProfileID()) - TheGameSpyPSMessageQueue->trackPlayerStats(stats); - - if(stats.id == 0) - { - stats = TheGameSpyInfo->getCachedLocalPlayerStats(); - stats.locale = psReq.player.locale; - TheGameSpyInfo->setCachedLocalPlayerStats(stats); - } - else - { - // force an update of our shtuff - PSResponse newResp; - newResp.responseType = PSResponse::PSRESPONSE_PLAYERSTATS; - newResp.player = TheGameSpyPSMessageQueue->findPlayerStatsByID(TheGameSpyInfo->getLocalProfileID()); - TheGameSpyPSMessageQueue->addResponse(newResp); - } - CheckReOpenPlayerInfo(); - } //if ( controlID == buttonDisconnect ) - break; - }// case GBM_SELECTED: - - case GEM_EDIT_DONE: - { - break; - } - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLLocaleSelectSystem diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp deleted file mode 100644 index 3a4378ebb81..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp +++ /dev/null @@ -1,1511 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLLoginMenu.cpp -// Author: Chris Huybregts, November 2001 -// Description: Lan Lobby Menu -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/STLTypedefs.h" - -#include "Common/File.h" -#include "Common/FileSystem.h" -#include "Common/GameEngine.h" -#include "Common/GameSpyMiscPreferences.h" -#include "Common/QuotedPrintable.h" -#include "Common/Registry.h" -#include "Common/UserPreferences.h" -#include "GameClient/AnimateWindowManager.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/GameText.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetComboBox.h" -#include "GameClient/GadgetCheckBox.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/MessageBox.h" -#include "GameClient/ShellHooks.h" -#include "GameClient/GameWindowTransitions.h" - -#include "GameNetwork/GameSpy/GSConfig.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PingThread.h" -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/ThreadUtils.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" - -#include "GameNetwork/GameSpyOverlay.h" - - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -#ifdef ALLOW_NON_PROFILED_LOGIN -Bool GameSpyUseProfiles = false; -#endif // ALLOW_NON_PROFILED_LOGIN - - -static Bool isShuttingDown = false; -static Bool buttonPushed = false; -static char *nextScreen = NULL; - -static const UnsignedInt loginTimeoutInMS = 10000; -static UnsignedInt loginAttemptTime = 0; - -class GameSpyLoginPreferences : public UserPreferences -{ -public: - GameSpyLoginPreferences() { m_emailPasswordMap.clear(); m_emailNickMap.clear(); } - virtual ~GameSpyLoginPreferences() { m_emailPasswordMap.clear(); m_emailNickMap.clear(); } - - virtual Bool load(AsciiString fname); - virtual Bool write(void); - - AsciiString getPasswordForEmail( AsciiString email ); - AsciiString getDateForEmail( AsciiString email, AsciiString &month, AsciiString &date, AsciiString &year ); - AsciiStringList getNicksForEmail( AsciiString email ); - void addLogin( AsciiString email, AsciiString nick, AsciiString password, AsciiString date ); - void forgetLogin( AsciiString email ); - AsciiStringList getEmails( void ); - -private: - typedef std::map PassMap; - typedef std::map DateMap; - typedef std::map NickMap; - PassMap m_emailPasswordMap; - NickMap m_emailNickMap; - DateMap m_emailDateMap; -}; - -static AsciiString obfuscate( AsciiString in ) -{ - char *buf = NEW char[in.getLength() + 1]; - strcpy(buf, in.str()); - static const char *xor = "1337Munkee"; - char *c = buf; - const char *c2 = xor; - while (*c) - { - if (!*c2) - c2 = xor; - if (*c != *c2) - *c = *c++ ^ *c2++; - else - c++, c2++; - } - AsciiString out = buf; - delete buf; - return out; -} - -Bool GameSpyLoginPreferences::load( AsciiString fname ) -{ - if (!UserPreferences::load(fname)) - return false; - - UserPreferences::iterator upIt = begin(); - while (upIt != end()) - { - AsciiString key = upIt->first; - if (key.startsWith("pass_")) - { - AsciiString email, pass; - email = key.str() + 5; - pass = upIt->second; - - AsciiString quoPass = QuotedPrintableToAsciiString(pass); - pass = obfuscate(quoPass); - - m_emailPasswordMap[email] = pass; - } - if (key.startsWith("date_")) - { - AsciiString email, date; - email = key.str() + 5; - date = upIt->second; - - date = QuotedPrintableToAsciiString(date); - - m_emailDateMap[email] = date; - } - else if (key.startsWith("nick_")) - { - AsciiString email, nick, nicks; - email = key.str() + 5; - nicks = upIt->second; - while (nicks.nextToken(&nick, ",")) - { - m_emailNickMap[email].push_back(nick); - } - } - ++upIt; - } - - return true; -} - -Bool GameSpyLoginPreferences::write( void ) -{ - if (m_filename.isEmpty()) - return false; - - FILE *fp = fopen(m_filename.str(), "w"); - if (fp) - { - fprintf(fp, "lastEmail = %s\n", ((*this)["lastEmail"].str())); - fprintf(fp, "lastName = %s\n", ((*this)["lastName"].str())); - fprintf(fp, "useProfiles = %s\n", ((*this)["useProfiles"].str())); - PassMap::iterator passIt = m_emailPasswordMap.begin(); - while (passIt != m_emailPasswordMap.end()) - { - AsciiString pass = obfuscate(passIt->second); - AsciiString quoPass = AsciiStringToQuotedPrintable(pass); - - fprintf(fp, "pass_%s = %s\n", passIt->first.str(), quoPass.str()); - ++passIt; - } - - PassMap::iterator dateIt = m_emailDateMap.begin(); - while (dateIt != m_emailDateMap.end()) - { - AsciiString date = AsciiStringToQuotedPrintable(dateIt->second); - - fprintf(fp, "date_%s = %s\n", dateIt->first.str(), date.str()); - ++dateIt; - } - - NickMap::iterator nickIt = m_emailNickMap.begin(); - while (nickIt != m_emailNickMap.end()) - { - AsciiString nicks; - AsciiStringListIterator listIt = nickIt->second.begin(); - while (listIt != nickIt->second.end()) - { - nicks.concat(*listIt); - nicks.concat(','); - ++listIt; - } - fprintf(fp, "nick_%s = %s\n", nickIt->first.str(), nicks.str()); - ++nickIt; - } - - fclose(fp); - return true; - } - return false; -} -AsciiString GameSpyLoginPreferences::getDateForEmail( AsciiString email, AsciiString &month, AsciiString &date, AsciiString &year ) -{ - if ( m_emailDateMap.find(email) == m_emailDateMap.end() ) - return AsciiString::TheEmptyString; - AsciiString fullDate = m_emailDateMap[email]; - if(fullDate.getLength() != 8) - return AsciiString::TheEmptyString; - month.format("%c%c", fullDate.getCharAt(0), fullDate.getCharAt(1)); - date.format("%c%c", fullDate.getCharAt(2), fullDate.getCharAt(3)); - year.format("%c%c%c%c", fullDate.getCharAt(4), fullDate.getCharAt(5), fullDate.getCharAt(6), fullDate.getCharAt(7)); - return m_emailDateMap[email]; -} - -AsciiString GameSpyLoginPreferences::getPasswordForEmail( AsciiString email ) -{ - if ( m_emailPasswordMap.find(email) == m_emailPasswordMap.end() ) - return AsciiString::TheEmptyString; - return m_emailPasswordMap[email]; -} - -AsciiStringList GameSpyLoginPreferences::getNicksForEmail( AsciiString email ) -{ - if ( m_emailNickMap.find(email) == m_emailNickMap.end() ) - { - AsciiStringList empty; - return empty; - } - return m_emailNickMap[email]; -} - -void GameSpyLoginPreferences::addLogin( AsciiString email, AsciiString nick, AsciiString password, AsciiString date ) -{ - if ( std::find(m_emailNickMap[email].begin(), m_emailNickMap[email].end(), nick) == m_emailNickMap[email].end() ) - m_emailNickMap[email].push_back(nick); - m_emailPasswordMap[email] = password; - m_emailDateMap[email] = date; -} - -void GameSpyLoginPreferences::forgetLogin( AsciiString email ) -{ - m_emailNickMap.erase(email); - m_emailPasswordMap.erase(email); - m_emailDateMap.erase(email); - -} - -AsciiStringList GameSpyLoginPreferences::getEmails( void ) -{ - AsciiStringList theList; - NickMap::iterator it = m_emailNickMap.begin(); - while (it != m_emailNickMap.end()) - { - theList.push_back(it->first); - ++it; - } - return theList; -} - -static const char *PREF_FILENAME = "GameSpyLogin.ini"; -static GameSpyLoginPreferences *loginPref = NULL; - -static void startPings( void ) -{ - std::list pingServers = TheGameSpyConfig->getPingServers(); - Int timeout = TheGameSpyConfig->getPingTimeoutInMs(); - Int reps = TheGameSpyConfig->getNumPingRepetitions(); - - for (std::list::const_iterator it = pingServers.begin(); it != pingServers.end(); ++it) - { - AsciiString pingServer = *it; - PingRequest req; - req.hostname = pingServer.str(); - req.repetitions = reps; - req.timeout = timeout; - ThePinger->addRequest(req); - } -} - -//------------------------------------------------------------------------------------------------- -/** This is called when a shutdown is complete for this menu */ -//------------------------------------------------------------------------------------------------- -static void shutdownComplete( WindowLayout *layout ) -{ - - isShuttingDown = false; - - // hide the layout - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout, (nextScreen != NULL) ); - - if (nextScreen != NULL) - { - if (loginPref) - { - loginPref->write(); - delete loginPref; - loginPref = NULL; - } - TheShell->push(nextScreen); - } - else - { - DEBUG_ASSERTCRASH(loginPref != NULL, ("loginPref == NULL")); - if (loginPref) - { - loginPref->write(); - delete loginPref; - loginPref = NULL; - } - } - - nextScreen = NULL; - -} // end if - - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentWOLLoginID = NAMEKEY_INVALID; -static NameKeyType buttonBackID = NAMEKEY_INVALID; // profile, quick -static NameKeyType buttonLoginID = NAMEKEY_INVALID; // profile, quick -static NameKeyType buttonCreateAccountID = NAMEKEY_INVALID; // profile, quick -static NameKeyType buttonUseAccountID = NAMEKEY_INVALID; // quick -static NameKeyType buttonDontUseAccountID = NAMEKEY_INVALID; // profile -static NameKeyType buttonTOSID = NAMEKEY_INVALID; // TOS -static NameKeyType parentTOSID = NAMEKEY_INVALID; // TOS Parent -static NameKeyType buttonTOSOKID = NAMEKEY_INVALID; // TOS -static NameKeyType listboxTOSID = NAMEKEY_INVALID; // TOS -static NameKeyType comboBoxEmailID = NAMEKEY_INVALID; // profile -static NameKeyType comboBoxLoginNameID = NAMEKEY_INVALID; // profile -static NameKeyType textEntryLoginNameID = NAMEKEY_INVALID; // quick -static NameKeyType textEntryPasswordID = NAMEKEY_INVALID; // profile -static NameKeyType checkBoxRememberPasswordID = NAMEKEY_INVALID; // checkbox to remember information or not -static NameKeyType textEntryMonthID = NAMEKEY_INVALID; // profile -static NameKeyType textEntryDayID = NAMEKEY_INVALID; // profile -static NameKeyType textEntryYearID = NAMEKEY_INVALID; // profile - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentWOLLogin = NULL; -static GameWindow *buttonBack = NULL; -static GameWindow *buttonLogin = NULL; -static GameWindow *buttonCreateAccount = NULL; -static GameWindow *buttonUseAccount = NULL; -static GameWindow *buttonDontUseAccount = NULL; -static GameWindow *buttonTOS = NULL; -static GameWindow *parentTOS = NULL; -static GameWindow *buttonTOSOK = NULL; -static GameWindow *listboxTOS = NULL; -static GameWindow *comboBoxEmail = NULL; -static GameWindow *comboBoxLoginName = NULL; -static GameWindow *textEntryLoginName = NULL; -static GameWindow *textEntryPassword = NULL; -static GameWindow *checkBoxRememberPassword = NULL; -static GameWindow *textEntryMonth = NULL; -static GameWindow *textEntryDay = NULL; -static GameWindow *textEntryYear = NULL; - -void EnableLoginControls( Bool state ) -{ - if (buttonLogin) - buttonLogin->winEnable(state); - if (buttonCreateAccount) - buttonCreateAccount->winEnable(state); - if (buttonUseAccount) - buttonUseAccount->winEnable(state); - if (buttonDontUseAccount) - buttonDontUseAccount->winEnable(state); - if (comboBoxEmail) - comboBoxEmail->winEnable(state); - if (comboBoxLoginName) - comboBoxLoginName->winEnable(state); - if (textEntryLoginName) - textEntryLoginName->winEnable(state); - if (textEntryPassword) - textEntryPassword->winEnable(state); - if (checkBoxRememberPassword) - checkBoxRememberPassword->winEnable(state); - if( buttonTOS ) - buttonTOS->winEnable(state); - - if (textEntryMonth) - textEntryMonth->winEnable(state); - if (textEntryDay) - textEntryDay->winEnable(state); - if( textEntryYear ) - textEntryYear->winEnable(state); -} - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Login Menu */ -//------------------------------------------------------------------------------------------------- -void WOLLoginMenuInit( WindowLayout *layout, void *userData ) -{ - nextScreen = NULL; - buttonPushed = false; - isShuttingDown = false; - loginAttemptTime = 0; - - if (!loginPref) - { - loginPref = NEW GameSpyLoginPreferences; - loginPref->load(PREF_FILENAME); - } - - // if the ESRB warning is blank (other country) hide the box - GameWindow *esrbTitle = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("GameSpyLoginProfile.wnd:StaticTextESRBTop") ); - GameWindow *esrbParent = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("GameSpyLoginProfile.wnd:ParentESRB") ); - if (esrbTitle && esrbParent) - { - if ( GadgetStaticTextGetText( esrbTitle ).getLength() < 2 ) - { - esrbParent->winHide(TRUE); - } - } - - parentWOLLoginID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:WOLLoginMenuParent" ); - buttonBackID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ButtonBack" ); - buttonLoginID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ButtonLogin" ); - buttonCreateAccountID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ButtonCreateAccount" ); - buttonUseAccountID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ButtonUseAccount" ); - buttonDontUseAccountID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ButtonDontUseAccount" ); - buttonTOSID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ButtonTOS" ); - parentTOSID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ParentTOS" ); - buttonTOSOKID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ButtonTOSOK" ); - listboxTOSID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ListboxTOS" ); - comboBoxEmailID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ComboBoxEmail" ); - comboBoxLoginNameID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:ComboBoxLoginName" ); - textEntryLoginNameID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:TextEntryLoginName" ); - textEntryPasswordID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:TextEntryPassword" ); - checkBoxRememberPasswordID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:CheckBoxRememberInfo" ); - textEntryMonthID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:TextEntryMonth" ); - textEntryDayID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:TextEntryDay" ); - textEntryYearID = TheNameKeyGenerator->nameToKey( "GameSpyLoginProfile.wnd:TextEntryYear" ); - - parentWOLLogin = TheWindowManager->winGetWindowFromId( NULL, parentWOLLoginID ); - buttonBack = TheWindowManager->winGetWindowFromId( NULL, buttonBackID); - buttonLogin = TheWindowManager->winGetWindowFromId( NULL, buttonLoginID); - buttonCreateAccount = TheWindowManager->winGetWindowFromId( NULL, buttonCreateAccountID); - buttonUseAccount = TheWindowManager->winGetWindowFromId( NULL, buttonUseAccountID); - buttonDontUseAccount = TheWindowManager->winGetWindowFromId( NULL, buttonDontUseAccountID); - buttonTOS = TheWindowManager->winGetWindowFromId( NULL, buttonTOSID); - parentTOS = TheWindowManager->winGetWindowFromId( NULL, parentTOSID); - buttonTOSOK = TheWindowManager->winGetWindowFromId( NULL, buttonTOSOKID); - listboxTOS = TheWindowManager->winGetWindowFromId( NULL, listboxTOSID); - comboBoxEmail = TheWindowManager->winGetWindowFromId( NULL, comboBoxEmailID); - comboBoxLoginName = TheWindowManager->winGetWindowFromId( NULL, comboBoxLoginNameID); - textEntryLoginName = TheWindowManager->winGetWindowFromId( NULL, textEntryLoginNameID); - textEntryPassword = TheWindowManager->winGetWindowFromId( NULL, textEntryPasswordID); - checkBoxRememberPassword = TheWindowManager->winGetWindowFromId( NULL, checkBoxRememberPasswordID); - textEntryMonth = TheWindowManager->winGetWindowFromId( NULL, textEntryMonthID); - textEntryDay = TheWindowManager->winGetWindowFromId( NULL, textEntryDayID); - textEntryYear = TheWindowManager->winGetWindowFromId( NULL, textEntryYearID); - - GadgetTextEntrySetText(textEntryMonth, UnicodeString::TheEmptyString); - - GadgetTextEntrySetText(textEntryDay, UnicodeString::TheEmptyString); - - GadgetTextEntrySetText(textEntryYear, UnicodeString::TheEmptyString); - - - - GameWindowList tabList; - tabList.push_front(comboBoxEmail); - tabList.push_back(comboBoxLoginName); - tabList.push_back(textEntryPassword); - tabList.push_back(textEntryMonth); - tabList.push_back(textEntryDay); - tabList.push_back(textEntryYear); - tabList.push_back(checkBoxRememberPassword); - tabList.push_back(buttonLogin); - tabList.push_back(buttonCreateAccount); - tabList.push_back(buttonTOS); - tabList.push_back(buttonBack); - TheWindowManager->clearTabList(); - TheWindowManager->registerTabList(tabList); - TheWindowManager->winSetFocus( comboBoxEmail ); - // short form or long form? -#ifdef ALLOW_NON_PROFILED_LOGIN - if (parentWOLLogin) - { - GameSpyUseProfiles = true; -#endif // ALLOW_NON_PROFILED_LOGIN - - DEBUG_ASSERTCRASH(buttonBack, ("buttonBack missing!")); - DEBUG_ASSERTCRASH(buttonLogin, ("buttonLogin missing!")); - DEBUG_ASSERTCRASH(buttonCreateAccount, ("buttonCreateAccount missing!")); - //DEBUG_ASSERTCRASH(buttonDontUseAccount, ("buttonDontUseAccount missing!")); - DEBUG_ASSERTCRASH(comboBoxEmail, ("comboBoxEmail missing!")); - DEBUG_ASSERTCRASH(comboBoxLoginName, ("comboBoxLoginName missing!")); - DEBUG_ASSERTCRASH(textEntryPassword, ("textEntryPassword missing!")); - - //TheShell->registerWithAnimateManager(parentWOLLogin, WIN_ANIMATION_SLIDE_TOP, TRUE); - /**/ -// TheShell->registerWithAnimateManager(buttonTOS, WIN_ANIMATION_SLIDE_BOTTOM, TRUE); - //TheShell->registerWithAnimateManager(buttonCreateAccount, WIN_ANIMATION_SLIDE_LEFT, TRUE); - //TheShell->registerWithAnimateManager(buttonDontUseAccount, WIN_ANIMATION_SLIDE_LEFT, TRUE); -// TheShell->registerWithAnimateManager(buttonBack, WIN_ANIMATION_SLIDE_BOTTOM, TRUE); - /**/ -#ifdef ALLOW_NON_PROFILED_LOGIN - } - else - { - GameSpyUseProfiles = false; - - parentWOLLoginID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:WOLLoginMenuParent" ); - buttonBackID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ButtonBack" ); - buttonLoginID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ButtonLogin" ); - buttonCreateAccountID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ButtonCreateAccount" ); - buttonUseAccountID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ButtonUseAccount" ); - buttonDontUseAccountID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ButtonDontUseAccount" ); - buttonTOSID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ButtonTOS" ); - parentTOSID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ParentTOS" ); - buttonTOSOKID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ButtonTOSOK" ); - listboxTOSID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ListboxTOS" ); - comboBoxEmailID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:ComboBoxEmail" ); - textEntryLoginNameID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:TextEntryLoginName" ); - textEntryPasswordID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:TextEntryPassword" ); - checkBoxRememberPasswordID = TheNameKeyGenerator->nameToKey( "GameSpyLoginQuick.wnd:CheckBoxRememberPassword" ); - - parentWOLLogin = TheWindowManager->winGetWindowFromId( NULL, parentWOLLoginID ); - buttonBack = TheWindowManager->winGetWindowFromId( NULL, buttonBackID); - buttonLogin = TheWindowManager->winGetWindowFromId( NULL, buttonLoginID); - buttonCreateAccount = TheWindowManager->winGetWindowFromId( NULL, buttonCreateAccountID); - buttonUseAccount = TheWindowManager->winGetWindowFromId( NULL, buttonUseAccountID); - buttonDontUseAccount = TheWindowManager->winGetWindowFromId( NULL, buttonDontUseAccountID); - comboBoxEmail = TheWindowManager->winGetWindowFromId( NULL, comboBoxEmailID); - buttonTOS = TheWindowManager->winGetWindowFromId( NULL, buttonTOSID); - parentTOS = TheWindowManager->winGetWindowFromId( NULL, parentTOSID); - buttonTOSOK = TheWindowManager->winGetWindowFromId( NULL, buttonTOSOKID); - listboxTOS = TheWindowManager->winGetWindowFromId( NULL, listboxTOSID); - textEntryLoginName = TheWindowManager->winGetWindowFromId( NULL, textEntryLoginNameID); - textEntryPassword = TheWindowManager->winGetWindowFromId( NULL, textEntryPasswordID); - checkBoxRememberPassword = TheWindowManager->winGetWindowFromId( NULL, checkBoxRememberPasswordID); - - DEBUG_ASSERTCRASH(buttonBack, ("buttonBack missing!")); - DEBUG_ASSERTCRASH(buttonLogin, ("buttonLogin missing!")); - DEBUG_ASSERTCRASH(buttonCreateAccount, ("buttonCreateAccount missing!")); - DEBUG_ASSERTCRASH(buttonUseAccount, ("buttonUseAccount missing!")); - DEBUG_ASSERTCRASH(textEntryLoginName, ("textEntryLoginName missing!")); - TheWindowManager->winSetFocus( textEntryLoginName ); - //TheShell->registerWithAnimateManager(parentWOLLogin, WIN_ANIMATION_SLIDE_TOP, TRUE); - -// TheShell->registerWithAnimateManager(buttonTOS, WIN_ANIMATION_SLIDE_LEFT, TRUE); -// TheShell->registerWithAnimateManager(buttonCreateAccount, WIN_ANIMATION_SLIDE_LEFT, TRUE); -// TheShell->registerWithAnimateManager(buttonUseAccount, WIN_ANIMATION_SLIDE_LEFT, TRUE); -// TheShell->registerWithAnimateManager(buttonBack, WIN_ANIMATION_SLIDE_RIGHT, TRUE); - - } -#endif // ALLOW_NON_PROFILED_LOGIN - - -#ifdef ALLOW_NON_PROFILED_LOGIN - if (GameSpyUseProfiles) - { -#endif // ALLOW_NON_PROFILED_LOGIN - // Read login names from registry... - GadgetComboBoxReset(comboBoxEmail); - GadgetTextEntrySetText(textEntryPassword, UnicodeString.TheEmptyString); - - // look for cached nicks to add - AsciiString lastName; - AsciiString lastEmail; - Bool markCheckBox = FALSE; - UserPreferences::const_iterator it = loginPref->find("lastName"); - if (it != loginPref->end()) - { - lastName = it->second; - } - it = loginPref->find("lastEmail"); - if (it != loginPref->end()) - { - lastEmail = it->second; - } - - // fill in list of Emails, and select the most recent - AsciiStringList cachedEmails = loginPref->getEmails(); - AsciiStringListIterator eIt = cachedEmails.begin(); - Int selectedPos = -1; - while (eIt != cachedEmails.end()) - { - UnicodeString uniEmail; - uniEmail.translate(*eIt); - Int pos = GadgetComboBoxAddEntry(comboBoxEmail, uniEmail, GameSpyColor[GSCOLOR_DEFAULT]); - if (*eIt == lastEmail) - selectedPos = pos; - - ++eIt; - } - if (selectedPos >= 0) - { - GadgetComboBoxSetSelectedPos(comboBoxEmail, selectedPos); - - // fill in the password for the selected email - UnicodeString pass; - pass.translate(loginPref->getPasswordForEmail(lastEmail)); - GadgetTextEntrySetText(textEntryPassword, pass); - - AsciiString month,day,year; - loginPref->getDateForEmail(lastEmail, month, day, year); - pass.translate(month); - GadgetTextEntrySetText(textEntryMonth, pass); - pass.translate(day); - GadgetTextEntrySetText(textEntryDay, pass); - pass.translate(year); - GadgetTextEntrySetText(textEntryYear, pass); - - markCheckBox = TRUE; - } - - // fill in list of nicks for selected email, selecting the most recent - GadgetComboBoxReset(comboBoxLoginName); - AsciiStringList cachedNicks = loginPref->getNicksForEmail(lastEmail); - AsciiStringListIterator nIt = cachedNicks.begin(); - selectedPos = -1; - while (nIt != cachedNicks.end()) - { - UnicodeString uniNick; - uniNick.translate(*nIt); - Int pos = GadgetComboBoxAddEntry(comboBoxLoginName, uniNick, GameSpyColor[GSCOLOR_DEFAULT]); - if (*nIt == lastName) - selectedPos = pos; - - ++nIt; - } - if (selectedPos >= 0) - { - GadgetComboBoxSetSelectedPos(comboBoxLoginName, selectedPos); - markCheckBox = TRUE; - } - // always start with not storing information - if( markCheckBox) - GadgetCheckBoxSetChecked(checkBoxRememberPassword, TRUE); - else - GadgetCheckBoxSetChecked(checkBoxRememberPassword, FALSE); -#ifdef ALLOW_NON_PROFILED_LOGIN - } - else - { - // Read login names from registry... - GadgetComboBoxReset(comboBoxLoginName); - UnicodeString nick; - - UserPreferences::const_iterator it = loginPref->find("lastName"); - if (it != loginPref->end()) - { - nick.translate(it->second); - } - else - { - char userBuf[32] = ""; - unsigned long bufSize = 32; - GetUserName(userBuf, &bufSize); - nick.translate(userBuf); - } - - GadgetTextEntrySetText(textEntryLoginName, nick); - } -#endif // ALLOW_NON_PROFILED_LOGIN - - EnableLoginControls(TRUE); - - // Show Menu - layout->hide( FALSE ); - - // Set Keyboard to Main Parent - - RaiseGSMessageBox(); - - OptionPreferences optionPref; - if (!optionPref.getBool("SawTOS", TRUE)) - { - TheWindowManager->winSendSystemMsg( parentWOLLogin, GBM_SELECTED, - (WindowMsgData)buttonTOS, buttonTOSID ); - } - TheTransitionHandler->setGroup("GameSpyLoginProfileFade"); - -} // WOLLoginMenuInit - -//------------------------------------------------------------------------------------------------- -/** WOL Login Menu shutdown method */ -//------------------------------------------------------------------------------------------------- -static Bool loggedInOK = false; -void WOLLoginMenuShutdown( WindowLayout *layout, void *userData ) -{ - isShuttingDown = true; - loggedInOK = false; - TheWindowManager->clearTabList(); - - // if we are shutting down for an immediate pop, skip the animations - Bool popImmediate = *(Bool *)userData; - if( popImmediate ) - { - - shutdownComplete( layout ); - return; - - } //end if - - TheShell->reverseAnimatewindow(); - TheTransitionHandler->reverse("GameSpyLoginProfileFade"); - -} // WOLLoginMenuShutdown - - -// this is used to check if we've got all the pings -static void checkLogin( void ) -{ - if (loggedInOK && ThePinger && !ThePinger->arePingsInProgress()) - { - // save off our ping string, and end those threads - AsciiString pingStr = ThePinger->getPingString( 1000 ); - DEBUG_LOG(("Ping string is %s\n", pingStr.str())); - TheGameSpyInfo->setPingString(pingStr); - //delete ThePinger; - //ThePinger = NULL; - - buttonPushed = true; - loggedInOK = false; // don't try this again - - loginAttemptTime = 0; - - // start looking for group rooms - TheGameSpyInfo->clearGroupRoomList(); - - SignalUIInteraction(SHELL_SCRIPT_HOOK_GENERALS_ONLINE_LOGIN); - nextScreen = "Menus/WOLWelcomeMenu.wnd"; - TheShell->pop(); - - // read in some cached data - GameSpyMiscPreferences mPref; - PSPlayerStats localPSStats = GameSpyPSMessageQueueInterface::parsePlayerKVPairs(mPref.getCachedStats().str()); - localPSStats.id = TheGameSpyInfo->getLocalProfileID(); - TheGameSpyInfo->setCachedLocalPlayerStats(localPSStats); -// TheGameSpyPSMessageQueue->trackPlayerStats(localPSStats); - - // and push the info around to other players -// PSResponse newResp; -// newResp.responseType = PSResponse::PSRESPONSE_PLAYERSTATS; -// newResp.player = localPSStats; -// TheGameSpyPSMessageQueue->addResponse(newResp); - } -} - -//------------------------------------------------------------------------------------------------- -/** WOL Login Menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLLoginMenuUpdate( WindowLayout * layout, void *userData) -{ - - // We'll only be successful if we've requested to - if(isShuttingDown && TheShell->isAnimFinished() && TheTransitionHandler->isFinished()) - shutdownComplete(layout); - - if (TheShell->isAnimFinished() && !buttonPushed && TheGameSpyPeerMessageQueue) - { - PingResponse pingResp; - if (ThePinger && ThePinger->getResponse(pingResp)) - { - checkLogin(); - } - - PeerResponse resp; - if (!loggedInOK && TheGameSpyPeerMessageQueue->getResponse( resp )) - { - switch (resp.peerResponseType) - { - case PeerResponse::PEERRESPONSE_GROUPROOM: - { - GameSpyGroupRoom room; - room.m_groupID = resp.groupRoom.id; - room.m_maxWaiting = resp.groupRoom.maxWaiting; - room.m_name = resp.groupRoomName.c_str(); - room.m_translatedName = UnicodeString(L"TEST"); - room.m_numGames = resp.groupRoom.numGames; - room.m_numPlaying = resp.groupRoom.numPlaying; - room.m_numWaiting = resp.groupRoom.numWaiting; - TheGameSpyInfo->addGroupRoom( room ); - } - break; - case PeerResponse::PEERRESPONSE_LOGIN: - { - loggedInOK = true; - - // fetch our player info - TheGameSpyInfo->setLocalName( resp.nick.c_str() ); - TheGameSpyInfo->setLocalProfileID( resp.player.profileID ); - TheGameSpyInfo->loadSavedIgnoreList(); - TheGameSpyInfo->setLocalIPs(resp.player.internalIP, resp.player.externalIP); - TheGameSpyInfo->readAdditionalDisconnects(); - //TheGameSpyInfo->setLocalEmail( resp.player.email ); - //TheGameSpyInfo->setLocalPassword( resp) - - GameSpyMiscPreferences miscPref; - TheGameSpyInfo->setMaxMessagesPerUpdate(miscPref.getMaxMessagesPerUpdate()); - } - break; - case PeerResponse::PEERRESPONSE_DISCONNECT: - { - loginAttemptTime = 0; - UnicodeString title, body; - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", resp.discon.reason); - title = TheGameText->fetch( "GUI:GSErrorTitle" ); - body = TheGameText->fetch( disconMunkee ); - GSMessageBoxOk( title, body ); - EnableLoginControls( TRUE ); - - // kill & restart the threads - AsciiString motd = TheGameSpyInfo->getMOTD(); - AsciiString config = TheGameSpyInfo->getConfig(); - DEBUG_LOG(("Tearing down GameSpy from WOLLoginMenuUpdate(PEERRESPONSE_DISCONNECT)\n")); - TearDownGameSpy(); - SetUpGameSpy( motd.str(), config.str() ); - } - break; - } - } - - checkLogin(); - } - - if (TheGameSpyInfo && !buttonPushed && loginAttemptTime && (loginAttemptTime + loginTimeoutInMS < timeGetTime())) - { - // timed out a login attempt, so say so - loginAttemptTime = 0; - UnicodeString title, body; - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason4"); // ("could not connect to server") - title = TheGameText->fetch( "GUI:GSErrorTitle" ); - body = TheGameText->fetch( disconMunkee ); - GSMessageBoxOk( title, body ); - EnableLoginControls( TRUE ); - - // kill & restart the threads - AsciiString motd = TheGameSpyInfo->getMOTD(); - AsciiString config = TheGameSpyInfo->getConfig(); - DEBUG_LOG(("Tearing down GameSpy from WOLLoginMenuUpdate(login timeout)\n")); - TearDownGameSpy(); - SetUpGameSpy( motd.str(), config.str() ); - } - -}// WOLLoginMenuUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Login Menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLLoginMenuInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - if (buttonPushed) - break; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonBack, buttonBackID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// WOLLoginMenuInput - -static Bool isNickOkay(UnicodeString nick) -{ - static const WideChar * legalIRCChars = L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789[]`_^{|}-"; - - Int len = nick.getLength(); - if (len == 0) - return TRUE; - - if (len == 1 && nick.getCharAt(0) == L'-') - return FALSE; - - WideChar newChar = nick.getCharAt(len-1); - if (wcschr(legalIRCChars, newChar) == NULL) - return FALSE; - - return TRUE; -} - -static Bool isAgeOkay(AsciiString &month, AsciiString &day, AsciiString year) -{ - if(month.isEmpty() || day.isEmpty() || year.isEmpty() || year.getLength() != 4) - return FALSE; - - Int monthInt = atoi(month.str()); - Int dayInt = atoi(day.str()); - - if(monthInt > 12 || dayInt > 31) - return FALSE; - // setup date buffer for local region date format - month.format("%02.2d",monthInt); - day.format("%02.2d",dayInt); - - // test the year first - #define DATE_BUFFER_SIZE 256 - char dateBuffer[ DATE_BUFFER_SIZE ]; - GetDateFormat( LOCALE_SYSTEM_DEFAULT, - 0, NULL, - "yyyy", - dateBuffer, DATE_BUFFER_SIZE ); - Int sysVal = atoi(dateBuffer); - Int userVal = atoi(year.str()); - if(sysVal - userVal >= 14) - return TRUE; - else if( sysVal - userVal <= 12) - return FALSE; - - GetDateFormat( LOCALE_SYSTEM_DEFAULT, - 0, NULL, - "MM", - dateBuffer, DATE_BUFFER_SIZE ); - sysVal = atoi(dateBuffer); - userVal = atoi(month.str()); - if(sysVal - userVal >0 ) - return TRUE; - else if( sysVal -userVal < 0 ) - return FALSE; -// month.format("%02.2d",userVal); - GetDateFormat( LOCALE_SYSTEM_DEFAULT, - 0, NULL, - "dd", - dateBuffer, DATE_BUFFER_SIZE ); - sysVal = atoi(dateBuffer); - userVal = atoi(day.str()); - if(sysVal - userVal< 0) - return FALSE; -// day.format("%02.2d",userVal); - return TRUE; -} - -//------------------------------------------------------------------------------------------------- -/** WOL Login Menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLLoginMenuSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - - switch( msg ) - { - - - case GWM_CREATE: - { - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - // someone typed in a combo box. Clear password (or fill it in if the typed name matches a known login name) - case GCM_UPDATE_TEXT: - { - UnicodeString uNick = GadgetComboBoxGetText(comboBoxLoginName); - UnicodeString uEmail = GadgetComboBoxGetText(comboBoxEmail); - AsciiString nick, email; - nick.translate(uNick); - email.translate(uEmail); - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - UnicodeString trimmedNick = uNick, trimmedEmail = uEmail; - trimmedNick.trim(); - trimmedEmail.trim(); - if (!trimmedNick.isEmpty()) - { - if (trimmedNick.getCharAt(trimmedNick.getLength()-1) == L'\\') - trimmedNick.removeLastChar(); - if (trimmedNick.getCharAt(trimmedNick.getLength()-1) == L'/') - trimmedNick.removeLastChar(); - } - if (!trimmedEmail.isEmpty()) - { - if (trimmedEmail.getCharAt(trimmedEmail.getLength()-1) == L'\\') - trimmedEmail.removeLastChar(); - if (trimmedEmail.getCharAt(trimmedEmail.getLength()-1) == L'/') - trimmedEmail.removeLastChar(); - } - if (trimmedEmail.getLength() != uEmail.getLength()) - { - // we just trimmed a space. set the text back and bail - GadgetComboBoxSetText(comboBoxEmail, trimmedEmail); - break; - } - if (trimmedNick.getLength() != nick.getLength()) - { - // we just trimmed a space. set the text back and bail - GadgetComboBoxSetText(comboBoxLoginName, trimmedNick); - break; - } - - if (controlID == comboBoxEmailID) - { - // email changed. look up password, and choose new login names - - // fill in the password for the selected email - UnicodeString pass; - pass.translate(loginPref->getPasswordForEmail(email)); - GadgetTextEntrySetText(textEntryPassword, pass); - - // fill in list of nicks for selected email, selecting the first - AsciiStringList cachedNicks = loginPref->getNicksForEmail(email); - AsciiStringListIterator nIt = cachedNicks.begin(); - Int selectedPos = -1; - GadgetComboBoxReset(comboBoxLoginName); - while (nIt != cachedNicks.end()) - { - UnicodeString uniNick; - uniNick.translate(*nIt); - GadgetComboBoxAddEntry(comboBoxLoginName, uniNick, GameSpyColor[GSCOLOR_DEFAULT]); - selectedPos = 0; - ++nIt; - } - if (selectedPos >= 0) - { - GadgetComboBoxSetSelectedPos(comboBoxLoginName, selectedPos); - GadgetCheckBoxSetChecked(checkBoxRememberPassword, true); - AsciiString month,day,year; - loginPref->getDateForEmail(email, month, day, year); - pass.translate(month); - GadgetTextEntrySetText(textEntryMonth, pass); - pass.translate(day); - GadgetTextEntrySetText(textEntryDay, pass); - pass.translate(year); - GadgetTextEntrySetText(textEntryYear, pass); - - } - else - { - GadgetCheckBoxSetChecked(checkBoxRememberPassword, false); - GadgetTextEntrySetText(textEntryMonth, UnicodeString::TheEmptyString); - GadgetTextEntrySetText(textEntryDay, UnicodeString::TheEmptyString); - GadgetTextEntrySetText(textEntryYear, UnicodeString::TheEmptyString); - - } - } - else if (controlID == comboBoxLoginNameID) - { - // they typed a new login name. Email & pass shouldn't change - } - - break; - } - - case GCM_SELECTED: - { - if (buttonPushed) - break; - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if (controlID == comboBoxEmailID) - { - // email changed. look up password, and choose new login names - UnicodeString uEmail = GadgetComboBoxGetText(comboBoxEmail); - AsciiString email; - email.translate(uEmail); - - // fill in the password for the selected email - UnicodeString pass; - pass.translate(loginPref->getPasswordForEmail(email)); - GadgetTextEntrySetText(textEntryPassword, pass); - - // fill in list of nicks for selected email, selecting the first - AsciiStringList cachedNicks = loginPref->getNicksForEmail(email); - AsciiStringListIterator nIt = cachedNicks.begin(); - Int selectedPos = -1; - GadgetComboBoxReset(comboBoxLoginName); - while (nIt != cachedNicks.end()) - { - UnicodeString uniNick; - uniNick.translate(*nIt); - GadgetComboBoxAddEntry(comboBoxLoginName, uniNick, GameSpyColor[GSCOLOR_DEFAULT]); - selectedPos = 0; - ++nIt; - } - if (selectedPos >= 0) - { - GadgetComboBoxSetSelectedPos(comboBoxLoginName, selectedPos); - GadgetCheckBoxSetChecked(checkBoxRememberPassword, true); - AsciiString month,day,year; - loginPref->getDateForEmail(email, month, day, year); - pass.translate(month); - GadgetTextEntrySetText(textEntryMonth, pass); - pass.translate(day); - GadgetTextEntrySetText(textEntryDay, pass); - pass.translate(year); - GadgetTextEntrySetText(textEntryYear, pass); - - } - else - { - GadgetCheckBoxSetChecked(checkBoxRememberPassword, false); - GadgetTextEntrySetText(textEntryMonth, UnicodeString::TheEmptyString); - GadgetTextEntrySetText(textEntryDay, UnicodeString::TheEmptyString); - GadgetTextEntrySetText(textEntryYear, UnicodeString::TheEmptyString); - } - - } - else if (controlID == comboBoxLoginNameID) - { - // they typed a new login name. Email & pass shouldn't change - } - break; - } - - case GBM_SELECTED: - { - if (buttonPushed) - break; - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - // If we back out, just bail - we haven't gotten far enough to need to log out - if ( controlID == buttonBackID ) - { - buttonPushed = true; - TearDownGameSpy(); - TheShell->pop(); - } //if ( controlID == buttonBack ) -#ifdef ALLOW_NON_PROFILED_LOGIN - else if ( controlID == buttonUseAccountID ) - { - buttonPushed = true; - nextScreen = "Menus/GameSpyLoginProfile.wnd"; - TheShell->pop(); - //TheShell->push( "Menus/GameSpyLoginProfile.wnd" ); - } //if ( controlID == buttonUseAccount ) - else if ( controlID == buttonDontUseAccountID ) - { - buttonPushed = true; - nextScreen = "Menus/GameSpyLoginQuick.wnd"; - TheShell->pop(); - //TheShell->push( "Menus/GameSpyLoginQuick.wnd" ); - } //if ( controlID == buttonDontUseAccount ) -#endif // ALLOW_NON_PROFILED_LOGIN - else if ( controlID == buttonCreateAccountID ) - { -#ifdef ALLOW_NON_PROFILED_LOGIN - if (GameSpyUseProfiles) - { -#endif // ALLOW_NON_PROFILED_LOGIN - // actually attempt to create an account based on info entered - AsciiString month, day, year; - month.translate( GadgetTextEntryGetText(textEntryMonth) ); - day.translate( GadgetTextEntryGetText(textEntryDay) ); - year.translate( GadgetTextEntryGetText(textEntryYear) ); - - if(!isAgeOkay(month, day, year)) - { - GSMessageBoxOk(TheGameText->fetch("GUI:AgeFailedTitle"), TheGameText->fetch("GUI:AgeFailed")); - break; - } - - AsciiString login, password, email; - email.translate( GadgetComboBoxGetText(comboBoxEmail) ); - login.translate( GadgetComboBoxGetText(comboBoxLoginName) ); - password.translate( GadgetTextEntryGetText(textEntryPassword) ); - - if ( !email.isEmpty() && !login.isEmpty() && !password.isEmpty() ) - { - loginAttemptTime = timeGetTime(); - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_LOGINNEW; - strcpy(req.arg.login.nick, login.str()); - strcpy(req.arg.login.email, email.str()); - strcpy(req.arg.login.password, password.str()); - req.arg.login.hasFirewall = TRUE; - - TheGameSpyInfo->setLocalBaseName( login ); - //TheGameSpyInfo->setLocalProfileID( resp.player.profileID ); - TheGameSpyInfo->setLocalEmail( email ); - TheGameSpyInfo->setLocalPassword( password ); - DEBUG_LOG(("before create: TheGameSpyInfo->stuff(%s/%s/%s)\n", TheGameSpyInfo->getLocalBaseName().str(), TheGameSpyInfo->getLocalEmail().str(), TheGameSpyInfo->getLocalPassword().str())); - - TheGameSpyBuddyMessageQueue->addRequest( req ); - if(checkBoxRememberPassword && GadgetCheckBoxIsChecked(checkBoxRememberPassword)) - { - (*loginPref)["lastName"] = login; - (*loginPref)["lastEmail"] = email; - (*loginPref)["useProfiles"] = "yes"; - AsciiString date; - date = month; - date.concat(day); - date.concat(year); - - loginPref->addLogin(email, login, password, date); - } - - EnableLoginControls( FALSE ); - - // fire off some pings - startPings(); - } - else - { - // user didn't fill in all info. prompt him. - if(email.isEmpty() && login.isEmpty() && password.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSNoLoginInfoAll")); - else if( email.isEmpty() && login.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSNoLoginInfoEmailNickname")); - else if( email.isEmpty() && password.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSNoLoginInfoEmailPassword")); - else if( login.isEmpty() && password.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSNoLoginInfoNicknamePassword")); - else if( email.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSNoLoginInfoEmail")); - else if( password.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSNoLoginInfoPassword")); - else if( login.isEmpty() ) - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSNoLoginInfoNickname")); - else - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSNoLoginInfoAll")); - } -#ifdef ALLOW_NON_PROFILED_LOGIN - } - else - { - // not the profile screen - switch to it - buttonPushed = TRUE; - nextScreen = "Menus/GameSpyLoginProfile.wnd"; - TheShell->pop(); - } -#endif // ALLOW_NON_PROFILED_LOGIN - } //if ( controlID == buttonCreateAccount ) - else if ( controlID == buttonLoginID ) - { - AsciiString login, password, email; - -#ifdef ALLOW_NON_PROFILED_LOGIN - if (GameSpyUseProfiles) - { -#endif // ALLOW_NON_PROFILED_LOGIN - AsciiString month, day, year; - month.translate( GadgetTextEntryGetText(textEntryMonth) ); - day.translate( GadgetTextEntryGetText(textEntryDay) ); - year.translate( GadgetTextEntryGetText(textEntryYear) ); - - if(!isAgeOkay(month, day, year)) - { - GSMessageBoxOk(TheGameText->fetch("GUI:AgeFailedTitle"), TheGameText->fetch("GUI:AgeFailed")); - break; - } - - email.translate( GadgetComboBoxGetText(comboBoxEmail) ); - login.translate( GadgetComboBoxGetText(comboBoxLoginName) ); - password.translate( GadgetTextEntryGetText(textEntryPassword) ); - - if ( !email.isEmpty() && !login.isEmpty() && !password.isEmpty() ) - { - loginAttemptTime = timeGetTime(); - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_LOGIN; - strcpy(req.arg.login.nick, login.str()); - strcpy(req.arg.login.email, email.str()); - strcpy(req.arg.login.password, password.str()); - req.arg.login.hasFirewall = true; - - TheGameSpyInfo->setLocalBaseName( login ); - //TheGameSpyInfo->setLocalProfileID( resp.player.profileID ); - TheGameSpyInfo->setLocalEmail( email ); - TheGameSpyInfo->setLocalPassword( password ); - DEBUG_LOG(("before login: TheGameSpyInfo->stuff(%s/%s/%s)\n", TheGameSpyInfo->getLocalBaseName().str(), TheGameSpyInfo->getLocalEmail().str(), TheGameSpyInfo->getLocalPassword().str())); - - TheGameSpyBuddyMessageQueue->addRequest( req ); - if(checkBoxRememberPassword && GadgetCheckBoxIsChecked(checkBoxRememberPassword)) - { - (*loginPref)["lastName"] = login; - (*loginPref)["lastEmail"] = email; - (*loginPref)["useProfiles"] = "yes"; - AsciiString date; - date = month; - date.concat(day); - date.concat(year); - - loginPref->addLogin(email, login, password,date); - } - else - { - loginPref->forgetLogin(email); - } - EnableLoginControls( FALSE ); - - // fire off some pings - startPings(); - } - else - { - // user didn't fill in all info. prompt him. - if(email.isEmpty() && login.isEmpty() && password.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSNoLoginInfoAll")); - else if( email.isEmpty() && login.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSNoLoginInfoEmailNickname")); - else if( email.isEmpty() && password.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSNoLoginInfoEmailPassword")); - else if( login.isEmpty() && password.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSNoLoginInfoNicknamePassword")); - else if( email.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSNoLoginInfoEmail")); - else if( password.isEmpty()) - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSNoLoginInfoPassword")); - else if( login.isEmpty() ) - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSNoLoginInfoNickname")); - else - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSNoLoginInfoAll")); - } -#ifdef ALLOW_NON_PROFILED_LOGIN - } - else - { - login.translate( GadgetTextEntryGetText(textEntryLoginName) ); - - if ( !login.isEmpty() ) - { - loginAttemptTime = timeGetTime(); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_LOGIN; - req.nick = login.str(); - req.login.profileID = 0; - TheGameSpyPeerMessageQueue->addRequest( req ); - - (*loginPref)["lastName"] = login; - loginPref->erase("lastEmail"); - (*loginPref)["useProfiles"] = "no"; - EnableLoginControls( FALSE ); - - // fire off some pings - startPings(); - } - } -#endif // ALLOW_NON_PROFILED_LOGIN - - } //if ( controlID == buttonLogin ) - else if ( controlID == buttonTOSID ) - { - parentTOS->winHide(FALSE); - - if (1) - { - // Okay, no web browser. This means we're looking at a UTF-8 text file. - GadgetListBoxReset(listboxTOS); - AsciiString fileName; - fileName.format("Data\\%s\\TOS.txt", GetRegistryLanguage().str()); - File *theFile = TheFileSystem->openFile(fileName.str(), File::READ); - if (theFile) - { - Int size = theFile->size(); - - char *fileBuf = new char[size]; - Color tosColor = GameMakeColor(255, 255, 255, 255); - - Int bytesRead = theFile->read(fileBuf, size); - if (bytesRead == size && size > 2) - { - fileBuf[size-1] = 0; // just to be safe - AsciiString asciiBuf = fileBuf+2; - AsciiString asciiLine; - while (asciiBuf.nextToken(&asciiLine, "\r\n")) - { - UnicodeString uniLine; - uniLine = UnicodeString(MultiByteToWideCharSingleLine(asciiLine.str()).c_str()); - int len = uniLine.getLength(); - for (int index = len-1; index >= 0; index--) - { - if (iswspace(uniLine.getCharAt(index))) - { - uniLine.removeLastChar(); - } - else - { - break; - } - } - //uniLine.trim(); - DEBUG_LOG(("adding TOS line: [%ls]\n", uniLine.str())); - GadgetListBoxAddEntryText(listboxTOS, uniLine, tosColor, -1); - } - - } - - delete fileBuf; - fileBuf = NULL; - - theFile->close(); - theFile = NULL; - } - } - EnableLoginControls( FALSE ); - buttonBack->winEnable(FALSE); - - } - else if ( controlID == buttonTOSOKID ) - { - EnableLoginControls( TRUE ); - - parentTOS->winHide(TRUE); - - OptionPreferences optionPref; - optionPref["SawTOS"] = "yes"; - optionPref.write(); - buttonBack->winEnable(TRUE); - } - break; - }// case GBM_SELECTED: - - case GEM_EDIT_DONE: - { - break; - } - /* - case GEM_UPDATE_TEXT: - { - if (buttonPushed) - break; - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if ( controlID == textEntryLoginNameID ) - { - UnicodeString munkee = GadgetTextEntryGetText( textEntryLoginName ); - if ( !isNickOkay( munkee ) ) - { - munkee.removeLastChar(); - GadgetTextEntrySetText( textEntryLoginName, munkee ); - } - }// if ( controlID == textEntryLoginNameID ) - break; - }//case GEM_UPDATE_TEXT: - */ - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLLoginMenuSystem - - diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLMapSelectMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLMapSelectMenu.cpp deleted file mode 100644 index 7e140bbace7..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLMapSelectMenu.cpp +++ /dev/null @@ -1,483 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: WOLMapSelectMenu.cpp //////////////////////////////////////////////////////////////////////// -// Author: Matt Campbell, December 2001 -// Description: MapSelect menu window callbacks -/////////////////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/CustomMatchPreferences.h" -#include "Common/GameEngine.h" -#include "Common/MessageStream.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/GadgetRadioButton.h" -#include "GameClient/Shell.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetListBox.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameClient/MapUtil.h" -#include "GameNetwork/GUIUtil.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -static NameKeyType buttonBack = NAMEKEY_INVALID; -static NameKeyType buttonOK = NAMEKEY_INVALID; -static NameKeyType listboxMap = NAMEKEY_INVALID; -static GameWindow *parent = NULL; -static Bool raiseMessageBoxes = FALSE; -static GameWindow *winMapPreview = NULL; -static NameKeyType winMapPreviewID = NAMEKEY_INVALID; - -static NameKeyType radioButtonSystemMapsID = NAMEKEY_INVALID; -static NameKeyType radioButtonUserMapsID = NAMEKEY_INVALID; - -extern WindowLayout *WOLMapSelectLayout; ///< Map selection overlay -static GameWindow *mapList = NULL; - -static GameWindow *buttonMapStartPosition[MAX_SLOTS] = {NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL }; -static NameKeyType buttonMapStartPositionID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; - -static GameWindow *winMapWindow = NULL; - -static void NullifyControls(void) -{ - parent = NULL; - winMapPreview = NULL; - mapList = NULL; - for (Int i=0; iwinGetWindowFromId( NULL, TheNameKeyGenerator->nameToKey("GameSpyGameOptionsMenu.wnd:ButtonBack") ); - if(win) - win->winEnable( show ); -} - -// PUBLIC FUNCTIONS /////////////////////////////////////////////////////////////////////////////// - -//------------------------------------------------------------------------------------------------- -/** Initialize the MapSelect menu */ -//------------------------------------------------------------------------------------------------- -void WOLMapSelectMenuInit( WindowLayout *layout, void *userData ) -{ - - // set keyboard focus to main parent - AsciiString parentName( "WOLMapSelectMenu.wnd:WOLMapSelectMenuParent" ); - NameKeyType parentID = TheNameKeyGenerator->nameToKey( parentName ); - parent = TheWindowManager->winGetWindowFromId( NULL, parentID ); - - TheWindowManager->winSetFocus( parent ); - - CustomMatchPreferences pref; - Bool usesSystemMapDir = pref.usesSystemMapDir(); - winMapPreviewID = TheNameKeyGenerator->nameToKey( AsciiString("WOLMapSelectMenu.wnd:WinMapPreview") ); - winMapPreview = TheWindowManager->winGetWindowFromId(parent, winMapPreviewID); - - const MapMetaData *mmd = TheMapCache->findMap(TheGameSpyGame->getMap()); - if (mmd) - { - usesSystemMapDir = mmd->m_isOfficial; - } - - //if stats are enabled, only official maps can be used - if( TheGameSpyInfo->getCurrentStagingRoom()->getUseStats() ) - usesSystemMapDir = true; - - buttonBack = TheNameKeyGenerator->nameToKey( AsciiString("WOLMapSelectMenu.wnd:ButtonBack") ); - buttonOK = TheNameKeyGenerator->nameToKey( AsciiString("WOLMapSelectMenu.wnd:ButtonOK") ); - listboxMap = TheNameKeyGenerator->nameToKey( AsciiString("WOLMapSelectMenu.wnd:ListboxMap") ); - radioButtonSystemMapsID = TheNameKeyGenerator->nameToKey( "WOLMapSelectMenu.wnd:RadioButtonSystemMaps" ); - radioButtonUserMapsID = TheNameKeyGenerator->nameToKey( "WOLMapSelectMenu.wnd:RadioButtonUserMaps" ); - winMapWindow = TheWindowManager->winGetWindowFromId( parent, listboxMap ); - - GameWindow *radioButtonSystemMaps = TheWindowManager->winGetWindowFromId( parent, radioButtonSystemMapsID ); - GameWindow *radioButtonUserMaps = TheWindowManager->winGetWindowFromId( parent, radioButtonUserMapsID ); - if( TheGameSpyInfo->getCurrentStagingRoom()->getUseStats() ) - { //disable unofficial maps if stats are being recorded - GadgetRadioSetSelection( radioButtonSystemMaps, FALSE ); - radioButtonUserMaps->winEnable( FALSE ); - } - else if (usesSystemMapDir) - GadgetRadioSetSelection( radioButtonSystemMaps, FALSE ); - else - GadgetRadioSetSelection( radioButtonUserMaps, FALSE ); - - AsciiString tmpString; - for (Int i = 0; i < MAX_SLOTS; i++) - { - tmpString.format("WOLMapSelectMenu.wnd:ButtonMapStartPosition%d", i); - buttonMapStartPositionID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - buttonMapStartPosition[i] = TheWindowManager->winGetWindowFromId( winMapPreview, buttonMapStartPositionID[i] ); - DEBUG_ASSERTCRASH(buttonMapStartPosition[i], ("Could not find the ButtonMapStartPosition[%d]",i )); - buttonMapStartPosition[i]->winHide(TRUE); - buttonMapStartPosition[i]->winEnable(FALSE); - } - - raiseMessageBoxes = TRUE; - showGameSpyGameOptionsUnderlyingGUIElements( FALSE ); - - // get the listbox window - AsciiString listString( "WOLMapSelectMenu.wnd:ListboxMap" ); - NameKeyType mapListID = TheNameKeyGenerator->nameToKey( listString ); - mapList = TheWindowManager->winGetWindowFromId( parent, mapListID ); - if( mapList ) - { - if (TheMapCache) - TheMapCache->updateCache(); - populateMapListbox( mapList, usesSystemMapDir, TRUE, TheGameSpyGame->getMap() ); - } - -} // end WOLMapSelectMenuInit - -//------------------------------------------------------------------------------------------------- -/** MapSelect menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLMapSelectMenuShutdown( WindowLayout *layout, void *userData ) -{ - NullifyControls(); - - // hide menu - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout ); - -} // end WOLMapSelectMenuShutdown - -//------------------------------------------------------------------------------------------------- -/** MapSelect menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLMapSelectMenuUpdate( WindowLayout *layout, void *userData ) -{ - - if (raiseMessageBoxes) - { - RaiseGSMessageBox(); - raiseMessageBoxes = false; - } - - // No update because the game setup screen is up at the same - // time and it does the update for us... -} // end WOLMapSelectMenuUpdate - -//------------------------------------------------------------------------------------------------- -/** Map select menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLMapSelectMenuInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - AsciiString buttonName( "WOLMapSelectMenu.wnd:ButtonBack" ); - NameKeyType buttonID = TheNameKeyGenerator->nameToKey( buttonName ); - GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonID ); - - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)button, buttonID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; - -} // end WOLMapSelectMenuInput -void WOLPositionStartSpots( void ); - -//------------------------------------------------------------------------------------------------- -/** MapSelect menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLMapSelectMenuSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CREATE: - { - break; - - } // end create - - //--------------------------------------------------------------------------------------------- - case GWM_DESTROY: - { - NullifyControls(); - break; - - } // end case - - // -------------------------------------------------------------------------------------------- - case GWM_INPUT_FOCUS: - { - - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - - } // end input - - //--------------------------------------------------------------------------------------------- - case GLM_DOUBLE_CLICKED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if( controlID == listboxMap ) - { - int rowSelected = mData2; - - if (rowSelected >= 0) - { - GadgetListBoxSetSelected( control, rowSelected ); - GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonOK ); - - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)button, buttonOK ); - } - } - break; - } - //--------------------------------------------------------------------------------------------- - - - - case GLM_SELECTED: - { - - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - if( controlID == listboxMap ) - { - int rowSelected = mData2; - if( rowSelected < 0 ) - { - positionStartSpots( AsciiString::TheEmptyString, buttonMapStartPosition, winMapPreview); -// winMapPreview->winClearStatus(WIN_STATUS_IMAGE); - break; - } - winMapPreview->winSetStatus(WIN_STATUS_IMAGE); - UnicodeString map; - // get text of the map to load - map = GadgetListBoxGetText( winMapWindow, rowSelected, 0 ); - - // set the map name in the global data map name - AsciiString asciiMap; - const char *mapFname = (const char *)GadgetListBoxGetItemData( winMapWindow, rowSelected ); - DEBUG_ASSERTCRASH(mapFname, ("No map item data")); - if (mapFname) - asciiMap = mapFname; - else - asciiMap.translate( map ); - asciiMap.toLower(); - Image *image = getMapPreviewImage(asciiMap); - winMapPreview->winSetUserData((void *)TheMapCache->findMap(asciiMap)); - if(image) - { - winMapPreview->winSetEnabledImage(0, image); - } - else - { - winMapPreview->winClearStatus(WIN_STATUS_IMAGE); - } - positionStartSpots( asciiMap, buttonMapStartPosition, winMapPreview); - } - break; - } - //--------------------------------------------------------------------------------------------- - case GBM_SELECTED: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if( controlID == buttonBack ) - { - showGameSpyGameOptionsUnderlyingGUIElements( TRUE ); - - WOLMapSelectLayout->destroyWindows(); - WOLMapSelectLayout->deleteInstance(); - WOLMapSelectLayout = NULL; - WOLPositionStartSpots(); - } // end if - else if ( controlID == radioButtonSystemMapsID ) - { - if (TheMapCache) - TheMapCache->updateCache(); - populateMapListbox( mapList, TRUE, TRUE, TheGameSpyGame->getMap() ); - CustomMatchPreferences pref; - pref.setUsesSystemMapDir(TRUE); - pref.write(); - } - else if ( controlID == radioButtonUserMapsID ) - { - if (TheMapCache) - TheMapCache->updateCache(); - populateMapListbox( mapList, FALSE, TRUE, TheGameSpyGame->getMap() ); - CustomMatchPreferences pref; - pref.setUsesSystemMapDir(FALSE); - pref.write(); - } - else if( controlID == buttonOK ) - { - Int selected; - UnicodeString map; - - // get the selected index - GadgetListBoxGetSelected( winMapWindow, &selected ); - - if( selected != -1 ) - { - - // get text of the map to load - map = GadgetListBoxGetText( winMapWindow, selected, 0 ); - - - // set the map name in the global data map name - AsciiString asciiMap; - const char *mapFname = (const char *)GadgetListBoxGetItemData( winMapWindow, selected ); - DEBUG_ASSERTCRASH(mapFname, ("No map item data")); - if (mapFname) - asciiMap = mapFname; - else - asciiMap.translate( map ); - TheGameSpyGame->setMap(asciiMap); - asciiMap.toLower(); - std::map::iterator it = TheMapCache->find(asciiMap); - if (it != TheMapCache->end()) - { - TheGameSpyGame->getGameSpySlot(0)->setMapAvailability(TRUE); - TheGameSpyGame->setMapCRC( it->second.m_CRC ); - TheGameSpyGame->setMapSize( it->second.m_filesize ); - } - - TheGameSpyGame->adjustSlotsForMap(); // BGC- adjust the slots for the new map. - TheGameSpyGame->resetAccepted(); - TheGameSpyGame->resetStartSpots(); - TheGameSpyInfo->setGameOptions(); - - WOLDisplaySlotList(); - WOLDisplayGameOptions(); - - WOLMapSelectLayout->destroyWindows(); - WOLMapSelectLayout->deleteInstance(); - WOLMapSelectLayout = NULL; - - showGameSpyGameOptionsUnderlyingGUIElements( TRUE ); - - WOLPositionStartSpots(); - - } // end if - - } // end else if - - break; - - } // end selected - - default: - return MSG_IGNORED; - - } // end switch - - return MSG_HANDLED; - -} // end WOLMapSelectMenuSystem diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLMessageWindow.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLMessageWindow.cpp deleted file mode 100644 index 5f93a32d7cd..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLMessageWindow.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLMessageWindow.cpp -// Author: Chris Huybregts, November 2001 -// Description: Lan Lobby Menu -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameNetwork/IPEnumeration.h" -//#include "GameNetwork/WOL.h" - - - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentWOLMessageWindowID = NAMEKEY_INVALID; -static NameKeyType buttonCancelID = NAMEKEY_INVALID; - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentWOLMessageWindow = NULL; -static GameWindow *buttonCancel = NULL; - - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOLMessage Window */ -//------------------------------------------------------------------------------------------------- -void WOLMessageWindowInit( WindowLayout *layout, void *userData ) -{ - parentWOLMessageWindowID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLMessageWindow.wnd:WOLMessageWindowParent" ) ); - buttonCancelID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLMessageWindow.wnd:ButtonCancel" ) ); - parentWOLMessageWindow = TheWindowManager->winGetWindowFromId( NULL, parentWOLMessageWindowID ); - buttonCancel = TheWindowManager->winGetWindowFromId( NULL, buttonCancelID); - - - // Show Menu - layout->hide( FALSE ); - - // Set Keyboard to Main Parent - TheWindowManager->winSetFocus( parentWOLMessageWindow ); - -} // WOLMessageWindowInit - -//------------------------------------------------------------------------------------------------- -/** WOLMessage Window shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLMessageWindowShutdown( WindowLayout *layout, void *userData ) -{ - - // hide menu - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout ); -} // WOLMessageWindowShutdown - - -//------------------------------------------------------------------------------------------------- -/** WOLMessage Window update method */ -//------------------------------------------------------------------------------------------------- -void WOLMessageWindowUpdate( WindowLayout * layout, void *userData) -{ - /* - if (WOL::TheWOL) - WOL::TheWOL->update(); - */ - -}// WOLMessageWindowUpdate - -//------------------------------------------------------------------------------------------------- -/** WOLMessage Window input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLMessageWindowInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonCancel, buttonCancelID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// WOLMessageWindowInput - -//------------------------------------------------------------------------------------------------- -/** WOLMessage Window window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLMessageWindowSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - - switch( msg ) - { - - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - case GBM_SELECTED: - { - break; - }// case GBM_SELECTED: - - case GEM_EDIT_DONE: - { - break; - } - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLMessageWindowSystem diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQMScoreScreen.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQMScoreScreen.cpp deleted file mode 100644 index 80ecc295549..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQMScoreScreen.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLQMScoreScreen.cpp -// Author: Matt Campbell, November 2001 -// Description: QuickMatch score screen (different from normal screen in that it has 'QM' and 'Discon' buttons) -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetTextEntry.h" -//#include "GameNetwork/WOL.h" -//#include "GameNetwork/WOLmenus.h" - - - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentWOLQMScoreID = NAMEKEY_INVALID; -static NameKeyType buttonDisconnectID = NAMEKEY_INVALID; -static NameKeyType buttonQuickmatchID = NAMEKEY_INVALID; - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentWOLQMScore = NULL; -static GameWindow *buttonDisconnect = NULL; -static GameWindow *buttonQuickmatch = NULL; - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Status Menu */ -//------------------------------------------------------------------------------------------------- -void WOLQMScoreScreenInit( WindowLayout *layout, void *userData ) -{ - parentWOLQMScoreID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLQMScoreScreen.wnd:WOLQMScoreScreenParent" ) ); - buttonDisconnectID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLQMScoreScreen.wnd:ButtonDisconnect" ) ); - buttonQuickmatchID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLQMScoreScreen.wnd:ButtonQuickMatch" ) ); - parentWOLQMScore = TheWindowManager->winGetWindowFromId( NULL, parentWOLQMScoreID ); - buttonDisconnect = TheWindowManager->winGetWindowFromId( NULL, buttonDisconnectID); - buttonQuickmatch = TheWindowManager->winGetWindowFromId( NULL, buttonQuickmatchID); - - /* - if (WOL::TheWOL->getState() == WOL::WOLAPI_FATAL_ERROR) - { - // We can get to the score screen even though we've been disconnected. Just hide - // any buttons that lead back into WOL. - - buttonQuickmatch->winHide( TRUE ); - } - */ - - // Show Menu - layout->hide( FALSE ); - - // Set Keyboard to Main Parent - TheWindowManager->winSetFocus( parentWOLQMScore ); - - //progressLayout = TheShell->top(); - -} // WOLQMScoreScreenInit - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLQMScoreScreenShutdown( WindowLayout *layout, void *userData ) -{ - - // hide menu - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout ); - - //progressLayout = NULL; - -} // WOLQMScoreScreenShutdown - - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLQMScoreScreenUpdate( WindowLayout * layout, void *userData) -{ - /* - if (WOL::TheWOL) - WOL::TheWOL->update(); - */ -}// WOLQMScoreScreenUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLQMScoreScreenInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonDisconnect, buttonDisconnectID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// WOLQMScoreScreenInput - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLQMScoreScreenSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - - switch( msg ) - { - - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're given the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - case GBM_SELECTED: - { - /* - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if ( controlID == buttonDisconnectID ) - { - //TheShell->pop(); - if (WOL::TheWOL->setState( WOL::WOLAPI_FATAL_ERROR )) - { - WOL::TheWOL->addCommand( WOL::WOLCOMMAND_RESET ); // don't display an error, log out, or anything - } - - } //if ( controlID == buttonDisconnect ) - else if ( controlID == buttonQuickmatchID ) - { - //TheShell->pop(); - if (WOL::TheWOL->getState() != WOL::WOLAPI_FATAL_ERROR) - { - if (WOL::TheWOL->setState( WOL::WOLAPI_TOURNAMENT )) - { - WOL::TheWOL->setScreen( WOL::WOLAPI_MENU_QUICKMATCH ); - WOL::TheWOL->addCommand( WOL::WOLCOMMAND_FIND_MATCH_CHANNEL ); - } - } - - } //if ( controlID == buttonDisconnect ) - */ - break; - }// case GBM_SELECTED: - - case GEM_EDIT_DONE: - { - break; - } - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLQMScoreScreenSystem diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp deleted file mode 100644 index d119217f1f2..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp +++ /dev/null @@ -1,1897 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLQuickMatchMenu.cpp -// Author: Chris Huybregts, November 2001 -// Description: Lan Lobby Menu -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "Common/QuickmatchPreferences.h" -#include "Common/LadderPreferences.h" -#include "Common/MultiplayerSettings.h" -#include "Common/PlayerTemplate.h" -#include "GameClient/AnimateWindowManager.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/GameText.h" -#include "GameClient/InGameUI.h" -#include "GameClient/Shell.h" -#include "GameClient/ShellHooks.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetComboBox.h" -#include "GameClient/GadgetPushButton.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/MapUtil.h" -#include "GameClient/GameWindowTransitions.h" -#include "GameClient/ChallengeGenerals.h" - -#include "GameLogic/GameLogic.h" - -#include "GameNetwork/NAT.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameNetwork/GameSpy/BuddyDefs.h" -#include "GameNetwork/GameSpy/GSConfig.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PersistentStorageDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/RankPointValue.h" -#include "GameNetwork/GameSpy/LadderDefs.h" -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -#ifdef DEBUG_LOGGING -#include "Common/MiniLog.h" -//#define PERF_TEST -static LogClass s_perfLog("QMPerf.txt"); -static Bool s_inQM = FALSE; -#define PERF_LOG(x) s_perfLog.log x -#else // DEBUG_LOGGING -#define PERF_LOG(x) {} -#endif // DEBUG_LOGGING - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentWOLQuickMatchID = NAMEKEY_INVALID; -static NameKeyType buttonBackID = NAMEKEY_INVALID; -static NameKeyType buttonStartID = NAMEKEY_INVALID; -static NameKeyType buttonStopID = NAMEKEY_INVALID; -static NameKeyType buttonWidenID = NAMEKEY_INVALID; -static NameKeyType buttonBuddiesID = NAMEKEY_INVALID; -static NameKeyType listboxQuickMatchID = NAMEKEY_INVALID; -static NameKeyType listboxMapSelectID = NAMEKEY_INVALID; -static NameKeyType buttonSelectAllMapsID = NAMEKEY_INVALID; -static NameKeyType buttonSelectNoMapsID = NAMEKEY_INVALID; -//static NameKeyType textEntryMaxDisconnectsID = NAMEKEY_INVALID; -//static NameKeyType textEntryMaxPointsID = NAMEKEY_INVALID; -//static NameKeyType textEntryMinPointsID = NAMEKEY_INVALID; -static NameKeyType textEntryWaitTimeID = NAMEKEY_INVALID; -static NameKeyType comboBoxNumPlayersID = NAMEKEY_INVALID; -static NameKeyType comboBoxMaxPingID = NAMEKEY_INVALID; -static NameKeyType comboBoxLadderID = NAMEKEY_INVALID; -static NameKeyType comboBoxMaxDisconnectsID = NAMEKEY_INVALID; -static NameKeyType staticTextNumPlayersID = NAMEKEY_INVALID; -static NameKeyType comboBoxSideID = NAMEKEY_INVALID; -static NameKeyType comboBoxColorID = NAMEKEY_INVALID; - - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentWOLQuickMatch = NULL; -static GameWindow *buttonBack = NULL; -static GameWindow *buttonStart = NULL; -static GameWindow *buttonStop = NULL; -static GameWindow *buttonWiden = NULL; -GameWindow *quickmatchTextWindow = NULL; -static GameWindow *listboxMapSelect = NULL; -//static GameWindow *textEntryMaxDisconnects = NULL; -//static GameWindow *textEntryMaxPoints = NULL; -//static GameWindow *textEntryMinPoints = NULL; -static GameWindow *textEntryWaitTime = NULL; -static GameWindow *comboBoxNumPlayers = NULL; -static GameWindow *comboBoxMaxPing = NULL; -static GameWindow *comboBoxLadder = NULL; -static GameWindow *comboBoxDisabledLadder = NULL; // enable and disable this, but never use it. it is a stand-in for comboBoxLadder for when there are no ladders -static GameWindow *comboBoxMaxDisconnects = NULL; -static GameWindow *staticTextNumPlayers = NULL; -static GameWindow *comboBoxSide = NULL; -static GameWindow *comboBoxColor = NULL; - -static Bool isShuttingDown = false; -static Bool buttonPushed = false; -static char *nextScreen = NULL; -static Bool raiseMessageBoxes = false; -static Bool isInInit = FALSE; -static const Image *selectedImage = NULL; -static const Image *unselectedImage = NULL; - -static bool isPopulatingLadderBox = false; -static Int maxPingEntries = 0; -static Int maxPoints= 100; -static Int minPoints = 0; - -static const LadderInfo * getLadderInfo( void ); - -static Bool isInfoShown(void) -{ - static NameKeyType parentStatsID = NAMEKEY("WOLQuickMatchMenu.wnd:ParentStats"); - GameWindow *parentStats = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, parentStatsID ); - if (parentStats) - return !parentStats->winIsHidden(); - return FALSE; -} - -static void hideInfoGadgets(Bool doIt) -{ - static NameKeyType parentStatsID = NAMEKEY("WOLQuickMatchMenu.wnd:ParentStats"); - GameWindow *parentStats = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, parentStatsID ); - if (parentStats) - { - parentStats->winHide(doIt); - } -} - -static void hideOptionsGadgets(Bool doIt) -{ - static NameKeyType parentOptionsID = NAMEKEY("WOLQuickMatchMenu.wnd:ParentOptions"); - GameWindow *parentOptions = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, parentOptionsID ); - if (parentOptions) - { - parentOptions->winHide(doIt); - if (comboBoxSide) - comboBoxSide->winHide(doIt); - if (comboBoxColor) - comboBoxColor->winHide(doIt); - if (comboBoxNumPlayers) - comboBoxNumPlayers->winHide(doIt); - if (comboBoxLadder) - comboBoxLadder->winHide(doIt); - if (comboBoxDisabledLadder) - comboBoxDisabledLadder->winHide(doIt); - if (comboBoxMaxPing) - comboBoxMaxPing->winHide(doIt); - if (comboBoxMaxDisconnects) - comboBoxMaxDisconnects->winHide(doIt); - } -} - -static void enableOptionsGadgets(Bool doIt) -{ -#ifdef PERF_TEST - s_inQM = !doIt; -#endif // PERF_TEST - static NameKeyType parentOptionsID = NAMEKEY("WOLQuickMatchMenu.wnd:ParentOptions"); - GameWindow *parentOptions = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, parentOptionsID ); - const LadderInfo *li = getLadderInfo(); - if (parentOptions) - { - parentOptions->winEnable(doIt); - if (comboBoxSide) - comboBoxSide->winEnable(doIt && (!li || !li->randomFactions)); - if (comboBoxColor) - comboBoxColor->winEnable(doIt); - if (comboBoxNumPlayers) - comboBoxNumPlayers->winEnable(doIt); - if (comboBoxLadder) - comboBoxLadder->winEnable(doIt); - if (comboBoxDisabledLadder) - comboBoxDisabledLadder->winEnable(FALSE); - if (comboBoxMaxPing) - comboBoxMaxPing->winEnable(doIt); - if (comboBoxMaxDisconnects) - comboBoxMaxDisconnects->winEnable(doIt); - } -} - -enum -{ - MAX_DISCONNECTS_ANY = 0, - MAX_DISCONNECTS_5 = 5, - MAX_DISCONNECTS_10 = 10, - MAX_DISCONNECTS_25 = 25, - MAX_DISCONNECTS_50 = 50, -}; -enum{ MAX_DISCONNECTS_COUNT = 5 }; - -static Int MAX_DISCONNECTS[MAX_DISCONNECTS_COUNT] = {MAX_DISCONNECTS_ANY, MAX_DISCONNECTS_5, - MAX_DISCONNECTS_10, MAX_DISCONNECTS_25, - MAX_DISCONNECTS_50}; - - -void UpdateStartButton(void) -{ - if (!comboBoxLadder || !buttonStart || !listboxMapSelect) - return; - - Int index; - Int selected; - GadgetComboBoxGetSelectedPos( comboBoxLadder, &selected ); - index = (Int)GadgetComboBoxGetItemData( comboBoxLadder, selected ); - const LadderInfo *li = TheLadderList->findLadderByIndex( index ); - if (li) - { - buttonStart->winEnable(TRUE); - return; - } - - Int numMaps = GadgetListBoxGetNumEntries(listboxMapSelect); - for ( Int i=0; iwinEnable(TRUE); - return; - } - } - buttonStart->winEnable(FALSE); -} - -// ----------------------------------------------------------------------------- - -static void populateQMColorComboBox(QuickMatchPreferences& pref) -{ - Int numColors = TheMultiplayerSettings->getNumColors(); - UnicodeString colorName; - - GadgetComboBoxReset(comboBoxColor); - - MultiplayerColorDefinition *def = TheMultiplayerSettings->getColor(PLAYERTEMPLATE_RANDOM); - Int newIndex = GadgetComboBoxAddEntry(comboBoxColor, TheGameText->fetch("GUI:???"), def->getColor()); - GadgetComboBoxSetItemData(comboBoxColor, newIndex, (void *)-1); - - for (Int c=0; cgetColor(c); - if (!def) - continue; - - colorName = TheGameText->fetch(def->getTooltipName().str()); - newIndex = GadgetComboBoxAddEntry(comboBoxColor, colorName, def->getColor()); - GadgetComboBoxSetItemData(comboBoxColor, newIndex, (void *)c); - } - GadgetComboBoxSetSelectedPos(comboBoxColor, pref.getColor()); -} - -// ----------------------------------------------------------------------------- - -static void populateQMSideComboBox(Int favSide, const LadderInfo *li = NULL) -{ - Int numPlayerTemplates = ThePlayerTemplateStore->getPlayerTemplateCount(); - UnicodeString playerTemplateName; - - GadgetComboBoxReset(comboBoxSide); - - MultiplayerColorDefinition *def = TheMultiplayerSettings->getColor(PLAYERTEMPLATE_RANDOM); - Int newIndex = GadgetComboBoxAddEntry(comboBoxSide, TheGameText->fetch("GUI:Random"), def->getColor()); - GadgetComboBoxSetItemData(comboBoxSide, newIndex, (void *)PLAYERTEMPLATE_RANDOM); - - std::set seenSides; - - Int entryToSelect = 0; // select Random by default - - for (Int c=0; cgetNthPlayerTemplate(c); - if (!fac) - continue; - - if (fac->getStartingBuilding().isEmpty()) - continue; - - AsciiString side; - side.format("SIDE:%s", fac->getSide().str()); - if (seenSides.find(side) != seenSides.end()) - continue; - - if (li) - { - if (std::find(li->validFactions.begin(), li->validFactions.end(), fac->getSide()) == li->validFactions.end()) - continue; // ladder doesn't allow it. - } - - // Remove disallowed generals from the choice list. - // This is also enforced at GUI setup (GUIUtil.cpp and UserPreferences.cpp). - // @todo: unlock these when something rad happens - Bool disallowLockedGenerals = TRUE; - const GeneralPersona *general = TheChallengeGenerals->getGeneralByTemplateName(fac->getName()); - Bool startsLocked = general ? !general->isStartingEnabled() : FALSE; - if (disallowLockedGenerals && startsLocked) - continue; - - seenSides.insert(side); - - newIndex = GadgetComboBoxAddEntry(comboBoxSide, TheGameText->fetch(side), def->getColor()); - GadgetComboBoxSetItemData(comboBoxSide, newIndex, (void *)c); - - if (c == favSide) - entryToSelect = newIndex; - } - seenSides.clear(); - - GadgetComboBoxSetSelectedPos(comboBoxSide, entryToSelect); - if (li && li->randomFactions) - comboBoxSide->winEnable(FALSE); - else - comboBoxSide->winEnable(TRUE); -} - -void HandleQMLadderSelection(Int ladderID) -{ - if (!parentWOLQuickMatch) - return; - - QuickMatchPreferences pref; - - if (ladderID < 1) - { - pref.setLastLadder(AsciiString::TheEmptyString, 0); - pref.write(); - return; - } - - const LadderInfo *info = TheLadderList->findLadderByIndex(ladderID); - if (!info) - { - pref.setLastLadder(AsciiString::TheEmptyString, 0); - } - else - { - pref.setLastLadder(info->address, info->port); - } - - pref.write(); -} - -static inline Bool isValidLadder( const LadderInfo *lad ) -{ - if (lad && lad->index > 0 && lad->validQM) - { - PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(TheGameSpyInfo->getLocalProfileID()); - Int numWins = 0; - PerGeneralMap::iterator it; - for (it = stats.wins.begin(); it != stats.wins.end(); ++it) - { - numWins += it->second; - } - if (!lad->maxWins || lad->maxWins >=numWins) - { - if (!lad->minWins || lad->minWins<=numWins) - { - return TRUE; - } - } - } - return FALSE; -} - -void PopulateQMLadderListBox( GameWindow *win ) -{ - if (!parentWOLQuickMatch || !comboBoxLadder) - return; - - isPopulatingLadderBox = true; - - QuickMatchPreferences pref; - AsciiString userPrefFilename; - Int localProfile = TheGameSpyInfo->getLocalProfileID(); - - Color specialColor = GameSpyColor[GSCOLOR_MAP_SELECTED]; - Color normalColor = GameSpyColor[GSCOLOR_MAP_UNSELECTED]; - Color favoriteColor = GameSpyColor[GSCOLOR_MAP_UNSELECTED]; - Int index; - GadgetListBoxReset( win ); - - std::set usedLadders; - - // start with "No Ladder" - index = GadgetListBoxAddEntryText( win, TheGameText->fetch("GUI:NoLadder"), normalColor, -1 ); - GadgetListBoxSetItemData( win, 0, index ); - - // add the last ladder - Int selectedPos = 0; - AsciiString lastLadderAddr = pref.getLastLadderAddr(); - UnsignedShort lastLadderPort = pref.getLastLadderPort(); - const LadderInfo *info = TheLadderList->findLadder( lastLadderAddr, lastLadderPort ); - if (isValidLadder(info)) - { - usedLadders.insert(info); - index = GadgetListBoxAddEntryText( win, info->name, favoriteColor, -1 ); - GadgetListBoxSetItemData( win, (void *)(info->index), index ); - selectedPos = index; - } - - // our recent ladders - LadderPreferences ladPref; - ladPref.loadProfile( localProfile ); - const LadderPrefMap recentLadders = ladPref.getRecentLadders(); - for (LadderPrefMap::const_iterator cit = recentLadders.begin(); cit != recentLadders.end(); ++cit) - { - AsciiString addr = cit->second.address; - UnsignedShort port = cit->second.port; - if (addr == lastLadderAddr && port == lastLadderPort) - continue; - const LadderInfo *info = TheLadderList->findLadder( addr, port ); - if (isValidLadder(info) && usedLadders.find(info) == usedLadders.end()) - { - usedLadders.insert(info); - index = GadgetListBoxAddEntryText( win, info->name, favoriteColor, -1 ); - GadgetListBoxSetItemData( win, (void *)(info->index), index ); - } - } - - // special ladders - const LadderInfoList *lil = TheLadderList->getSpecialLadders(); - LadderInfoList::const_iterator lit; - for (lit = lil->begin(); lit != lil->end(); ++lit) - { - const LadderInfo *info = *lit; - if (isValidLadder(info) && usedLadders.find(info) == usedLadders.end()) - { - usedLadders.insert(info); - index = GadgetListBoxAddEntryText( win, info->name, specialColor, -1 ); - GadgetListBoxSetItemData( win, (void *)(info->index), index ); - } - } - - // standard ladders - lil = TheLadderList->getStandardLadders(); - for (lit = lil->begin(); lit != lil->end(); ++lit) - { - const LadderInfo *info = *lit; - if (isValidLadder(info) && usedLadders.find(info) == usedLadders.end()) - { - usedLadders.insert(info); - index = GadgetListBoxAddEntryText( win, info->name, normalColor, -1 ); - GadgetListBoxSetItemData( win, (void *)(info->index), index ); - } - } - - GadgetListBoxSetSelected( win, selectedPos ); - isPopulatingLadderBox = false; -} - -static const LadderInfo * getLadderInfo( void ) -{ - Int index; - Int selected; - GadgetComboBoxGetSelectedPos( comboBoxLadder, &selected ); - index = (Int)GadgetComboBoxGetItemData( comboBoxLadder, selected ); - const LadderInfo *li = TheLadderList->findLadderByIndex( index ); - return li; -} - -void PopulateQMLadderComboBox( void ) -{ - if (!parentWOLQuickMatch || !comboBoxLadder) - return; - - isPopulatingLadderBox = true; - - QuickMatchPreferences pref; - Int localProfile = TheGameSpyInfo->getLocalProfileID(); - - Color specialColor = GameSpyColor[GSCOLOR_MAP_SELECTED]; - Color normalColor = GameSpyColor[GSCOLOR_MAP_UNSELECTED]; - Int index; - GadgetComboBoxReset( comboBoxLadder ); - index = GadgetComboBoxAddEntry( comboBoxLadder, TheGameText->fetch("GUI:NoLadder"), normalColor ); - GadgetComboBoxSetItemData( comboBoxLadder, index, 0 ); - - std::set usedLadders; - - Int selectedPos = 0; - AsciiString lastLadderAddr = pref.getLastLadderAddr(); - UnsignedShort lastLadderPort = pref.getLastLadderPort(); - const LadderInfo *info = TheLadderList->findLadder( lastLadderAddr, lastLadderPort ); - if (isValidLadder(info)) - { - usedLadders.insert(info); - index = GadgetComboBoxAddEntry( comboBoxLadder, info->name, specialColor ); - GadgetComboBoxSetItemData( comboBoxLadder, index, (void *)(info->index) ); - selectedPos = index; - - // we selected a ladder? No game size choice for us... - GadgetComboBoxSetSelectedPos(comboBoxNumPlayers, info->playersPerTeam-1); - comboBoxNumPlayers->winEnable( FALSE ); - } - else - { - comboBoxNumPlayers->winEnable( TRUE ); - } - - LadderPreferences ladPref; - ladPref.loadProfile( localProfile ); - const LadderPrefMap recentLadders = ladPref.getRecentLadders(); - for (LadderPrefMap::const_iterator cit = recentLadders.begin(); cit != recentLadders.end(); ++cit) - { - AsciiString addr = cit->second.address; - UnsignedShort port = cit->second.port; - if (addr == lastLadderAddr && port == lastLadderPort) - continue; - const LadderInfo *info = TheLadderList->findLadder( addr, port ); - if (isValidLadder(info) && usedLadders.find(info) == usedLadders.end()) - { - usedLadders.insert(info); - index = GadgetComboBoxAddEntry( comboBoxLadder, info->name, normalColor ); - GadgetComboBoxSetItemData( comboBoxLadder, index, (void *)(info->index) ); - } - } - - index = GadgetComboBoxAddEntry( comboBoxLadder, TheGameText->fetch("GUI:ChooseLadder"), normalColor ); - GadgetComboBoxSetItemData( comboBoxLadder, index, (void *)-1 ); - - GadgetComboBoxSetSelectedPos( comboBoxLadder, selectedPos ); - isPopulatingLadderBox = false; - - populateQMSideComboBox(pref.getSide(), getLadderInfo()); // this will set side to random and disable if necessary -} - -static void populateQuickMatchMapSelectListbox( QuickMatchPreferences& pref ) -{ - std::list maps = TheGameSpyConfig->getQMMaps(); - - // enable/disable box based on ladder status - Int index; - Int selected; - GadgetComboBoxGetSelectedPos( comboBoxLadder, &selected ); - index = (Int)GadgetComboBoxGetItemData( comboBoxLadder, selected ); - const LadderInfo *li = TheLadderList->findLadderByIndex( index ); - //listboxMapSelect->winEnable( li == NULL || li->randomMaps == FALSE ); - - Int numPlayers = 0; - if (li) - { - numPlayers = li->playersPerTeam*2; - - maps = li->validMaps; - } - else - { - GadgetComboBoxGetSelectedPos(comboBoxNumPlayers, &selected); - if (selected < 0) - selected = 0; - numPlayers = (selected+1)*2; - } - - - GadgetListBoxReset(listboxMapSelect); - for (std::list::const_iterator it = maps.begin(); it != maps.end(); ++it) - { - AsciiString theMap = *it; - const MapMetaData *md = TheMapCache->findMap(theMap); - if (md && md->m_numPlayers >= numPlayers) - { - UnicodeString displayName; - displayName = md->m_displayName; - Bool isSelected = pref.isMapSelected(theMap); - if (li && li->randomMaps) - isSelected = TRUE; - Int width = 10; - Int height = 10; - const Image *img = (isSelected)?selectedImage:unselectedImage; - if ( img ) - { - width = min(GadgetListBoxGetColumnWidth(listboxMapSelect, 0), img->getImageWidth()); - height = width; - } - Int index = GadgetListBoxAddEntryImage(listboxMapSelect, img, -1, 0, height, width); - GadgetListBoxAddEntryText(listboxMapSelect, displayName, GameSpyColor[(isSelected)?GSCOLOR_MAP_SELECTED:GSCOLOR_MAP_UNSELECTED], index, 1); - GadgetListBoxSetItemData(listboxMapSelect, (void *)isSelected, index); - GadgetListBoxSetItemData(listboxMapSelect, (void *)md, index, 1); - } - } -} - -static void saveQuickMatchOptions( void ) -{ - if(isInInit) - return; - QuickMatchPreferences pref; - - std::list maps = TheGameSpyConfig->getQMMaps(); - - Int index; - Int selected; - GadgetComboBoxGetSelectedPos( comboBoxLadder, &selected ); - index = (Int)GadgetComboBoxGetItemData( comboBoxLadder, selected ); - const LadderInfo *li = TheLadderList->findLadderByIndex( index ); - Int numPlayers = 0; - - if (li) - { - pref.setLastLadder( li->address, li->port ); - numPlayers = li->playersPerTeam*2; - - pref.write(); - //return; // don't save our defaults based on the tournament's defaults - } - else - { - pref.setLastLadder( AsciiString::TheEmptyString, 0 ); - GadgetComboBoxGetSelectedPos(comboBoxNumPlayers, &selected); - if (selected < 0) - selected = 0; - numPlayers = (selected+1)*2; - } - - if (!li || !li->randomMaps) // don't save the map as selected if we couldn't choose - { - Int row = 0; - Int entries = GadgetListBoxGetNumEntries(listboxMapSelect); - while ( row < entries) - { - const MapMetaData *md = (const MapMetaData *)GadgetListBoxGetItemData(listboxMapSelect, row, 1); - if(md) - pref.setMapSelected(md->m_fileName, (Bool)GadgetListBoxGetItemData(listboxMapSelect, row)); - row++; - } - } - - UnicodeString u; - AsciiString a; -// u = GadgetTextEntryGetText(textEntryMaxDisconnects); -// a.translate(u); -// pref.setMaxDisconnects(atoi(a.str())); -// u = GadgetTextEntryGetText(textEntryMaxPoints); -// a.translate(u); -// pref.setMaxPoints(max(100, atoi(a.str()))); -// u = GadgetTextEntryGetText(textEntryMinPoints); -// a.translate(u); -// pref.setMinPoints(min(100, atoi(a.str()))); - //u = GadgetTextEntryGetText(textEntryWaitTime); - //a.translate(u); - //pref.setWaitTime(atoi(a.str())); - - GadgetComboBoxGetSelectedPos(comboBoxNumPlayers, &selected); - pref.setNumPlayers(selected); - GadgetComboBoxGetSelectedPos(comboBoxMaxPing, &selected); - pref.setMaxPing(selected); - - Int item; - GadgetComboBoxGetSelectedPos(comboBoxSide, &selected); - item = (Int)GadgetComboBoxGetItemData(comboBoxSide, selected); - pref.setSide(max(0, item)); - GadgetComboBoxGetSelectedPos(comboBoxColor, &selected); - pref.setColor(max(0, selected)); - - GadgetComboBoxGetSelectedPos(comboBoxMaxDisconnects, &selected); - pref.setMaxDisconnects(selected); - - - pref.write(); -} - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Quick Match Menu */ -//------------------------------------------------------------------------------------------------- -void WOLQuickMatchMenuInit( WindowLayout *layout, void *userData ) -{ - isInInit = TRUE; - if (TheGameSpyGame && TheGameSpyGame->isGameInProgress()) - { - TheGameSpyGame->setGameInProgress(FALSE); - - // check if we were disconnected - Int disconReason; - if (TheGameSpyInfo->isDisconnectedAfterGameStart(&disconReason)) - { - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", disconReason); - UnicodeString title, body; - title = TheGameText->fetch( "GUI:GSErrorTitle" ); - body = TheGameText->fetch( disconMunkee ); - GameSpyCloseAllOverlays(); - GSMessageBoxOk( title, body ); - TheGameSpyInfo->reset(); - DEBUG_LOG(("WOLQuickMatchMenuInit() - game was in progress, and we were disconnected, so pop immediate back to main menu\n")); - TheShell->popImmediate(); - return; - } - } - - nextScreen = NULL; - buttonPushed = false; - isShuttingDown = false; - raiseMessageBoxes = true; - - if (TheNAT != NULL) { - delete TheNAT; - TheNAT = NULL; - } - - parentWOLQuickMatchID = NAMEKEY( "WOLQuickMatchMenu.wnd:WOLQuickMatchMenuParent" ); - buttonBackID = NAMEKEY( "WOLQuickMatchMenu.wnd:ButtonBack" ); - buttonBuddiesID = NAMEKEY( "WOLQuickMatchMenu.wnd:ButtonBuddies" ); - buttonStartID = NAMEKEY( "WOLQuickMatchMenu.wnd:ButtonStart" ); - buttonStopID = NAMEKEY( "WOLQuickMatchMenu.wnd:ButtonStop" ); - buttonWidenID = NAMEKEY( "WOLQuickMatchMenu.wnd:ButtonWiden" ); - listboxQuickMatchID = NAMEKEY( "WOLQuickMatchMenu.wnd:ListboxQuickMatch" ); - listboxMapSelectID = NAMEKEY( "WOLQuickMatchMenu.wnd:ListBoxMapSelect" ); - buttonSelectAllMapsID = NAMEKEY( "WOLQuickMatchMenu.wnd:ButtonSelectAllMaps" ); - buttonSelectNoMapsID = NAMEKEY( "WOLQuickMatchMenu.wnd:ButtonSelectNoMaps" ); - //textEntryMaxDisconnectsID = NAMEKEY( "WOLQuickMatchMenu.wnd:TextEntryMaxDisconnects" ); - //textEntryMaxPointsID = NAMEKEY( "WOLQuickMatchMenu.wnd:TextEntryMaxPointPercent" ); - //textEntryMinPointsID = NAMEKEY( "WOLQuickMatchMenu.wnd:TextEntryMinPointPercent" ); - textEntryWaitTimeID = NAMEKEY( "WOLQuickMatchMenu.wnd:TextEntryWaitTime" ); - comboBoxMaxPingID = NAMEKEY( "WOLQuickMatchMenu.wnd:ComboBoxMaxPing" ); - comboBoxNumPlayersID = NAMEKEY( "WOLQuickMatchMenu.wnd:ComboBoxNumPlayers" ); - comboBoxLadderID = NAMEKEY( "WOLQuickMatchMenu.wnd:ComboBoxLadder" ); - comboBoxMaxDisconnectsID = NAMEKEY( "WOLQuickMatchMenu.wnd:ComboBoxMaxDisconnects" ); - staticTextNumPlayersID = NAMEKEY( "WOLQuickMatchMenu.wnd:StaticTextNumPlayers" ); - comboBoxSideID = NAMEKEY( "WOLQuickMatchMenu.wnd:ComboBoxSide" ); - comboBoxColorID = NAMEKEY( "WOLQuickMatchMenu.wnd:ComboBoxColor" ); - - parentWOLQuickMatch = TheWindowManager->winGetWindowFromId( NULL, parentWOLQuickMatchID ); - buttonBack = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, buttonBackID); - buttonStart = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, buttonStartID); - buttonStop = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, buttonStopID); - buttonWiden = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, buttonWidenID); - quickmatchTextWindow = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, listboxQuickMatchID); - listboxMapSelect = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, listboxMapSelectID); - //textEntryMaxDisconnects = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, textEntryMaxDisconnectsID ); - //textEntryMaxPoints = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, textEntryMaxPointsID ); - //textEntryMinPoints = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, textEntryMinPointsID ); - textEntryWaitTime = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, textEntryWaitTimeID ); - comboBoxMaxPing = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, comboBoxMaxPingID ); - comboBoxNumPlayers = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, comboBoxNumPlayersID ); - comboBoxLadder = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, comboBoxLadderID ); - comboBoxMaxDisconnects = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, comboBoxMaxDisconnectsID ); - TheGameSpyInfo->registerTextWindow(quickmatchTextWindow); - staticTextNumPlayers = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, staticTextNumPlayersID ); - comboBoxSide = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, comboBoxSideID ); - comboBoxColor = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, comboBoxColorID ); - - if (TheLadderList->getStandardLadders()->size() == 0 - && TheLadderList->getSpecialLadders()->size() == 0 - && TheLadderList->getLocalLadders()->size() == 0) - { - // no ladders, so just disable them - comboBoxDisabledLadder = comboBoxLadder; - comboBoxLadder = NULL; - - isPopulatingLadderBox = TRUE; - - Color normalColor = GameSpyColor[GSCOLOR_MAP_UNSELECTED]; - Int index; - GadgetComboBoxReset( comboBoxDisabledLadder ); - index = GadgetComboBoxAddEntry( comboBoxDisabledLadder, TheGameText->fetch("GUI:NoLadder"), normalColor ); - GadgetComboBoxSetItemData( comboBoxDisabledLadder, index, 0 ); - GadgetComboBoxSetSelectedPos( comboBoxDisabledLadder, index ); - - isPopulatingLadderBox = FALSE; - - /** This code would actually *hide* the combo box, but it doesn't look as good. Left here since someone will want to - ** see it at some point. :P - if (comboBoxLadder) - { - comboBoxLadder->winHide(TRUE); - comboBoxLadder->winEnable(FALSE); - } - comboBoxLadder = NULL; - GameWindow *staticTextLadder = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, - NAMEKEY("WOLQuickMatchMenu.wnd:StaticTextLadder") ); - if (staticTextLadder) - staticTextLadder->winHide(TRUE); - */ - } - - GameWindow *buttonBuddies = TheWindowManager->winGetWindowFromId(NULL, buttonBuddiesID); - if (buttonBuddies) - buttonBuddies->winEnable(TRUE); - - GameWindow *staticTextTitle = TheWindowManager->winGetWindowFromId( parentWOLQuickMatch, - NAMEKEY("WOLQuickMatchMenu.wnd:StaticTextTitle") ); - if (staticTextTitle) - { - UnicodeString tmp; - tmp.format(TheGameText->fetch("GUI:QuickMatchTitle"), TheGameSpyInfo->getLocalName().str()); - GadgetStaticTextSetText(staticTextTitle, tmp); - } - - // QM is not going yet, so disable the Widen Search button - buttonWiden->winEnable( FALSE ); - buttonStop->winHide( TRUE ); - buttonStart->winHide( FALSE ); - GadgetListBoxReset(quickmatchTextWindow); - enableOptionsGadgets(TRUE); - - // Show Menu - layout->hide( FALSE ); - - // Set Keyboard to Main Parent - TheWindowManager->winSetFocus( parentWOLQuickMatch ); - - // fill in preferences - selectedImage = TheMappedImageCollection->findImageByName("CustomMatch_selected"); - unselectedImage = TheMappedImageCollection->findImageByName("CustomMatch_deselected"); - QuickMatchPreferences pref; - - - UnicodeString s; -// s.format(L"%d", pref.getMaxDisconnects()); -// GadgetTextEntrySetText(textEntryMaxDisconnects, s); -// s.format(L"%d", pref.getMaxPoints()); -// GadgetTextEntrySetText(textEntryMaxPoints, s); -// s.format(L"%d", pref.getMinPoints()); -// GadgetTextEntrySetText(textEntryMinPoints, s); - //s.format(L"%d", pref.getWaitTime()); - //GadgetTextEntrySetText(textEntryWaitTime, s); - maxPoints= pref.getMaxPoints(); - minPoints = pref.getMinPoints(); - - Color c = GameSpyColor[GSCOLOR_DEFAULT]; - GadgetComboBoxReset( comboBoxNumPlayers ); - Int i; - for (i=1; i<5; ++i) - { - s.format(TheGameText->fetch("GUI:PlayersVersusPlayers"), i, i); - GadgetComboBoxAddEntry( comboBoxNumPlayers, s, c ); - } - GadgetComboBoxSetSelectedPos( comboBoxNumPlayers, max(0, pref.getNumPlayers()) ); - - GadgetComboBoxReset(comboBoxMaxDisconnects); - GadgetComboBoxAddEntry( comboBoxMaxDisconnects, TheGameText->fetch("GUI:Any"), c); - for( i = 1; i < MAX_DISCONNECTS_COUNT; ++i ) - { - s.format(L"%d", MAX_DISCONNECTS[i]); - GadgetComboBoxAddEntry( comboBoxMaxDisconnects, s, c ); - } - Int maxDisconIndex = max(0, pref.getMaxDisconnects()); - GadgetComboBoxSetSelectedPos(comboBoxMaxDisconnects, maxDisconIndex); - - GadgetComboBoxReset( comboBoxMaxPing ); - maxPingEntries = (TheGameSpyConfig->getPingTimeoutInMs() - 1) / 100; - maxPingEntries++; // need to add the entry for the actual timeout - for (i=1; i fetch("GUI:TimeInMilliseconds"), i*100); - GadgetComboBoxAddEntry( comboBoxMaxPing, s, c ); - } - GadgetComboBoxAddEntry( comboBoxMaxPing, TheGameText->fetch("GUI:ANY"), c ); - i = pref.getMaxPing(); - if( i < 0 ) - i = 0; - if( i >= maxPingEntries ) - i = maxPingEntries - 1; - GadgetComboBoxSetSelectedPos( comboBoxMaxPing, i ); - - populateQMColorComboBox(pref); - populateQMSideComboBox(pref.getSide(), getLadderInfo()); - - PopulateQMLadderComboBox(); - TheShell->showShellMap(TRUE); - TheGameSpyGame->reset(); - - GadgetListBoxReset(listboxMapSelect); - populateQuickMatchMapSelectListbox(pref); - - UpdateLocalPlayerStats(); - UpdateStartButton(); - TheTransitionHandler->setGroup("WOLQuickMatchMenuFade"); - isInInit= FALSE; -} // WOLQuickMatchMenuInit - -//------------------------------------------------------------------------------------------------- -/** This is called when a shutdown is complete for this menu */ -//------------------------------------------------------------------------------------------------- -static void shutdownComplete( WindowLayout *layout ) -{ - - isShuttingDown = false; - - // hide the layout - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout, (nextScreen != NULL) ); - - if (nextScreen != NULL) - { - TheShell->push(nextScreen); - } - - nextScreen = NULL; - -} // end if - -//------------------------------------------------------------------------------------------------- -/** WOL Quick Match Menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLQuickMatchMenuShutdown( WindowLayout *layout, void *userData ) -{ - TheGameSpyInfo->unregisterTextWindow(quickmatchTextWindow); - - if (!TheGameEngine->getQuitting()) - saveQuickMatchOptions(); - - parentWOLQuickMatch = NULL; - buttonBack = NULL; - quickmatchTextWindow = NULL; - selectedImage = unselectedImage = NULL; - - isShuttingDown = true; - - // if we are shutting down for an immediate pop, skip the animations - Bool popImmediate = *(Bool *)userData; - if( popImmediate ) - { - - shutdownComplete( layout ); - return; - - } //end if - - TheShell->reverseAnimatewindow(); - TheTransitionHandler->reverse("WOLQuickMatchMenuFade"); - - RaiseGSMessageBox(); -} // WOLQuickMatchMenuShutdown - - -#ifdef PERF_TEST -static const char* getMessageString(Int t) -{ - switch(t) - { - case PeerResponse::PEERRESPONSE_LOGIN: - return "login"; - case PeerResponse::PEERRESPONSE_DISCONNECT: - return "disconnect"; - case PeerResponse::PEERRESPONSE_MESSAGE: - return "message"; - case PeerResponse::PEERRESPONSE_GROUPROOM: - return "group room"; - case PeerResponse::PEERRESPONSE_STAGINGROOM: - return "staging room"; - case PeerResponse::PEERRESPONSE_STAGINGROOMPLAYERINFO: - return "staging room player info"; - case PeerResponse::PEERRESPONSE_JOINGROUPROOM: - return "group room join"; - case PeerResponse::PEERRESPONSE_CREATESTAGINGROOM: - return "staging room create"; - case PeerResponse::PEERRESPONSE_JOINSTAGINGROOM: - return "staging room join"; - case PeerResponse::PEERRESPONSE_PLAYERJOIN: - return "player join"; - case PeerResponse::PEERRESPONSE_PLAYERLEFT: - return "player part"; - case PeerResponse::PEERRESPONSE_PLAYERCHANGEDNICK: - return "player nick"; - case PeerResponse::PEERRESPONSE_PLAYERINFO: - return "player info"; - case PeerResponse::PEERRESPONSE_PLAYERCHANGEDFLAGS: - return "player flags"; - case PeerResponse::PEERRESPONSE_ROOMUTM: - return "room UTM"; - case PeerResponse::PEERRESPONSE_PLAYERUTM: - return "player UTM"; - case PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS: - return "QM status"; - case PeerResponse::PEERRESPONSE_GAMESTART: - return "game start"; - case PeerResponse::PEERRESPONSE_FAILEDTOHOST: - return "host failure"; - } - return "unknown"; -} -#endif // PERF_TEST - -//------------------------------------------------------------------------------------------------- -/** WOL Quick Match Menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLQuickMatchMenuUpdate( WindowLayout * layout, void *userData) -{ - if (TheGameLogic->isInShellGame() && TheGameLogic->getFrame() == 1) - { - SignalUIInteraction(SHELL_SCRIPT_HOOK_GENERALS_ONLINE_ENTERED_FROM_GAME); - } - - // We'll only be successful if we've requested to - if(isShuttingDown && TheShell->isAnimFinished()&& TheTransitionHandler->isFinished()) - shutdownComplete(layout); - - if (raiseMessageBoxes) - { - RaiseGSMessageBox(); - raiseMessageBoxes = false; - } - - /// @todo: MDC handle disconnects in-game the same way as Custom Match! - - if (TheShell->isAnimFinished() && !buttonPushed && TheGameSpyPeerMessageQueue) - { - HandleBuddyResponses(); - HandlePersistentStorageResponses(); - - if (TheGameSpyGame && TheGameSpyGame->isGameInProgress()) - { - if (TheGameSpyInfo->isDisconnectedAfterGameStart(NULL)) - { - return; // already been disconnected, so don't worry. - } - - Int allowedMessages = TheGameSpyInfo->getMaxMessagesPerUpdate(); - Bool sawImportantMessage = FALSE; - PeerResponse resp; - while (allowedMessages-- && !sawImportantMessage && TheGameSpyPeerMessageQueue->getResponse( resp )) - { - switch (resp.peerResponseType) - { - case PeerResponse::PEERRESPONSE_DISCONNECT: - { - sawImportantMessage = TRUE; - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", resp.discon.reason); - - // check for scorescreen - NameKeyType listboxChatWindowScoreScreenID = NAMEKEY("ScoreScreen.wnd:ListboxChatWindowScoreScreen"); - GameWindow *listboxChatWindowScoreScreen = TheWindowManager->winGetWindowFromId( NULL, listboxChatWindowScoreScreenID ); - if (listboxChatWindowScoreScreen) - { - GadgetListBoxAddEntryText(listboxChatWindowScoreScreen, TheGameText->fetch(disconMunkee), - GameSpyColor[GSCOLOR_DEFAULT], -1); - } - else - { - // still ingame - TheInGameUI->message(disconMunkee); - } - TheGameSpyInfo->markAsDisconnectedAfterGameStart(resp.discon.reason); - } - } - } - - return; // if we're in game, all we care about is if we've been disconnected from the chat server - } - - if (TheNAT != NULL) { - NATStateType NATState = TheNAT->update(); - if (NATState == NATSTATE_DONE) - { - TheGameSpyGame->launchGame(); - if (TheGameSpyInfo) // this can be blown away by a disconnect on the map transfer screen - TheGameSpyInfo->leaveStagingRoom(); - return; // don't do any more processing this frame, in case the screen goes away - } - else if (NATState == NATSTATE_FAILED) - { - // delete TheNAT, its no good for us anymore. - delete TheNAT; - TheNAT = NULL; - - // Just back out. This cleans up some slot list problems - buttonPushed = true; - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:NATNegotiationFailed")); - nextScreen = "Menus/WOLWelcomeMenu.wnd"; - TheShell->pop(); - return; // don't do any more processing this frame, in case the screen goes away - } - } - -#ifdef PERF_TEST - UnsignedInt start = timeGetTime(); - UnsignedInt end = timeGetTime(); - std::list responses; - Int numMessages = 0; -#endif // PERF_TEST - - Int allowedMessages = TheGameSpyInfo->getMaxMessagesPerUpdate(); - Bool sawImportantMessage = FALSE; - PeerResponse resp; - while (allowedMessages-- && !sawImportantMessage && TheGameSpyPeerMessageQueue->getResponse( resp )) - { -#ifdef PERF_TEST - ++numMessages; - responses.push_back(resp.peerResponseType); -#endif // PERF_TEST - switch (resp.peerResponseType) - { - case PeerResponse::PEERRESPONSE_PLAYERUTM: - { - if (!stricmp(resp.command.c_str(), "STATS")) - { - DEBUG_LOG(("Saw STATS from %s, data was '%s'\n", resp.nick.c_str(), resp.commandOptions.c_str())); - AsciiString data = resp.commandOptions.c_str(); - AsciiString idStr; - data.nextToken(&idStr, " "); - Int id = atoi(idStr.str()); - DEBUG_LOG(("data: %d(%s) - '%s'\n", id, idStr.str(), data.str())); - - PSPlayerStats stats = TheGameSpyPSMessageQueue->parsePlayerKVPairs(data.str()); - PSPlayerStats oldStats = TheGameSpyPSMessageQueue->findPlayerStatsByID(id); - stats.id = id; - DEBUG_LOG(("Parsed ID is %d, old ID is %d\n", stats.id, oldStats.id)); - if (stats.id && (oldStats.id == 0)) - TheGameSpyPSMessageQueue->trackPlayerStats(stats); - - // now fill in the profileID in the game slot - AsciiString nick = resp.nick.c_str(); - for (Int i=0; igetGameSpySlot(i); - if (slot && slot->isHuman() && (slot->getLoginName().compareNoCase(nick) == 0)) - { - slot->setProfileID(id); - break; - } - } - } - Int slotNum = TheGameSpyGame->getSlotNum(resp.nick.c_str()); - if ((slotNum >= 0) && (slotNum < MAX_SLOTS) && (!stricmp(resp.command.c_str(), "NAT"))) { - // this is a command for NAT negotiations, pass if off to TheNAT - sawImportantMessage = TRUE; - if (TheNAT != NULL) { - TheNAT->processGlobalMessage(slotNum, resp.commandOptions.c_str()); - } - } - /* - else if (key == "NAT") - { - if ((val >= FirewallHelperClass::FIREWALL_TYPE_SIMPLE) && - (val <= FirewallHelperClass::FIREWALL_TYPE_DESTINATION_PORT_DELTA)) - { - slot->setNATBehavior((FirewallHelperClass::FirewallBehaviorType)val); - DEBUG_LOG(("Setting NAT behavior to %d for player %d\n", val, slotNum)); - change = true; - } - else - { - DEBUG_LOG(("Rejecting invalid NAT behavior %d from player %d\n", val, slotNum)); - } - } - */ - } - break; - - case PeerResponse::PEERRESPONSE_DISCONNECT: - { - sawImportantMessage = TRUE; - UnicodeString title, body; - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", resp.discon.reason); - title = TheGameText->fetch( "GUI:GSErrorTitle" ); - body = TheGameText->fetch( disconMunkee ); - GameSpyCloseAllOverlays(); - GSMessageBoxOk( title, body ); - TheGameSpyInfo->reset(); - TheShell->pop(); - } - break; // LORENZEN ADDED. SORRY IF THIS "BREAKS" IT... - - - case PeerResponse::PEERRESPONSE_JOINGROUPROOM: - /* - if (resp.joinGroupRoom.ok) - { - TheGameSpyInfo->addText(UnicodeString(L"Joined group room"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - } - else - { - TheGameSpyInfo->addText(UnicodeString(L"Didn't join group room"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - } - */ - break; - case PeerResponse::PEERRESPONSE_PLAYERJOIN: - { - //UnicodeString str; - //str.format(L"Player %hs joined the room", resp.nick.c_str()); - //TheGameSpyInfo->addText(str, GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - } - break; - case PeerResponse::PEERRESPONSE_PLAYERLEFT: - { - //UnicodeString str; - //str.format(L"Player %hs left the room", resp.nick.c_str()); - //TheGameSpyInfo->addText(str, GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - } - break; - case PeerResponse::PEERRESPONSE_MESSAGE: - { - //UnicodeString m; - //m.format(L"[%hs]: %ls", resp.nick.c_str(), resp.text.c_str()); - //TheGameSpyInfo->addText(m, GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - } - break; - - -// LORENZEN EXPRESSES DOUBT ABOUT THIS ONE, AS IT MAY HAVE SUFFERED MERGE MANGLING... SORRY - // I THINK THIS IS THE OBSOLETE VERSION... SEE THE NEWER LOOKING ONE ABOVE -/* - case PeerResponse::PEERRESPONSE_DISCONNECT: - { - UnicodeString title, body; - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", resp.discon.reason); - title = TheGameText->fetch( "GUI:GSErrorTitle" ); - body = TheGameText->fetch( disconMunkee ); - GameSpyCloseAllOverlays(); - GSMessageBoxOk( title, body ); - TheGameSpyInfo->reset(); - TheShell->pop(); - } -*/ - - - - case PeerResponse::PEERRESPONSE_CREATESTAGINGROOM: - { - if (resp.createStagingRoom.result == PEERJoinSuccess) - { - // Woohoo! On to our next screen! - UnicodeString str; - str.format(L"Created staging room"); - TheGameSpyInfo->addText(str, GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - } - else - { - UnicodeString s; - s.format(L"createStagingRoom result: %d", resp.createStagingRoom.result); - TheGameSpyInfo->addText( s, GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow ); - } - } - break; - case PeerResponse::PEERRESPONSE_JOINSTAGINGROOM: - { - if (resp.joinStagingRoom.ok == PEERTrue) - { - // Woohoo! On to our next screen! - UnicodeString s; - s.format(L"joinStagingRoom result: %d", resp.joinStagingRoom.ok); - TheGameSpyInfo->addText( s, GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow ); - } - else - { - UnicodeString s; - s.format(L"joinStagingRoom result: %d", resp.joinStagingRoom.ok); - TheGameSpyInfo->addText( s, GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow ); - } - } - break; - case PeerResponse::PEERRESPONSE_STAGINGROOM: - { - UnicodeString str; - str.format(L"Staging room list callback", resp.nick.c_str()); - TheGameSpyInfo->addText(str, GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - } - break; - case PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS: - { - sawImportantMessage = TRUE; - switch( resp.qmStatus.status ) - { - case QM_IDLE: - //TheGameSpyInfo->addText(UnicodeString(L"Status: QM_IDLE"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - break; - case QM_JOININGQMCHANNEL: - TheGameSpyInfo->addText(TheGameText->fetch("QM:JOININGQMCHANNEL"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - break; - case QM_LOOKINGFORBOT: - TheGameSpyInfo->addText(TheGameText->fetch("QM:LOOKINGFORBOT"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - break; - case QM_SENTINFO: - TheGameSpyInfo->addText(TheGameText->fetch("QM:SENTINFO"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - break; - case QM_WORKING: - { - UnicodeString s; - s.format(TheGameText->fetch("QM:WORKING"), resp.qmStatus.poolSize); - TheGameSpyInfo->addText(s, GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - } - buttonWiden->winEnable( TRUE ); - break; - case QM_POOLSIZE: - { - UnicodeString s; - s.format(TheGameText->fetch("QM:POOLSIZE"), resp.qmStatus.poolSize); - TheGameSpyInfo->addText(s, GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - } - break; - case QM_WIDENINGSEARCH: - TheGameSpyInfo->addText(TheGameText->fetch("QM:WIDENINGSEARCH"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - buttonWiden->winEnable( FALSE ); - break; - case QM_MATCHED: - { - TheGameSpyInfo->addText(TheGameText->fetch("QM:MATCHED"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - buttonWiden->winEnable( FALSE ); - - TheGameSpyGame->enterGame(); - TheGameSpyGame->setSeed(resp.qmStatus.seed); - - TheGameSpyGame->markGameAsQM(); - - const LadderInfo *info = getLadderInfo(); - if (!info) - { - TheGameSpyGame->setLadderIP("localhost"); - TheGameSpyGame->setLadderPort(0); - } - else - { - TheGameSpyGame->setLadderIP(info->address); - TheGameSpyGame->setLadderPort(info->port); - } - - Int i; - Int numPlayers = 0; - for (i=0; i maps = TheGameSpyConfig->getQMMaps(); - for (std::list::const_iterator it = maps.begin(); it != maps.end(); ++it) - { - AsciiString theMap = *it; - theMap.toLower(); - const MapMetaData *md = TheMapCache->findMap(theMap); - if (md && md->m_numPlayers >= numPlayers) - { - TheGameSpyGame->setMap(*it); - if (resp.qmStatus.mapIdx-- == 0) - break; - } - } - - Int numPlayersPerTeam = numPlayers/2; - DEBUG_ASSERTCRASH(numPlayersPerTeam, ("0 players per team???")); - if (!numPlayersPerTeam) - numPlayersPerTeam = 1; - - for (i=0; igetGameSpySlot(i); - if (resp.stagingRoomPlayerNames[i].empty()) - { - slot->setState(SLOT_CLOSED); - } - else - { - AsciiString aName = resp.stagingRoomPlayerNames[i].c_str(); - UnicodeString uName; - uName.translate(aName); - slot->setState(SLOT_PLAYER, uName, resp.qmStatus.IP[i]); - slot->setColor(resp.qmStatus.color[i]); - slot->setPlayerTemplate(resp.qmStatus.side[i]); - //slot->setProfileID(0); - slot->setNATBehavior((FirewallHelperClass::FirewallBehaviorType)resp.qmStatus.nat[i]); - slot->setLocale(""); - slot->setTeamNumber( i/numPlayersPerTeam ); - if (i==0) - TheGameSpyGame->setGameName(uName); - } - } - - DEBUG_LOG(("Starting a QM game: options=[%s]\n", GameInfoToAsciiString(TheGameSpyGame).str())); - SendStatsToOtherPlayers(TheGameSpyGame); - TheGameSpyGame->startGame(0); - GameWindow *buttonBuddies = TheWindowManager->winGetWindowFromId(NULL, buttonBuddiesID); - if (buttonBuddies) - buttonBuddies->winEnable(FALSE); - GameSpyCloseOverlay(GSOVERLAY_BUDDY); - } - break; - case QM_INCHANNEL: - TheGameSpyInfo->addText(TheGameText->fetch("QM:INCHANNEL"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - break; - case QM_NEGOTIATINGFIREWALLS: - TheGameSpyInfo->addText(TheGameText->fetch("QM:NEGOTIATINGFIREWALLS"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - break; - case QM_STARTINGGAME: - TheGameSpyInfo->addText(TheGameText->fetch("QM:STARTINGGAME"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - break; - case QM_COULDNOTFINDBOT: - TheGameSpyInfo->addText(TheGameText->fetch("QM:COULDNOTFINDBOT"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - buttonWiden->winEnable( FALSE ); - buttonStart->winHide( FALSE ); - buttonStop->winHide( TRUE ); - enableOptionsGadgets(TRUE); - break; - case QM_COULDNOTFINDCHANNEL: - TheGameSpyInfo->addText(TheGameText->fetch("QM:COULDNOTFINDCHANNEL"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - buttonWiden->winEnable( FALSE ); - buttonStart->winHide( FALSE ); - buttonStop->winHide( TRUE ); - enableOptionsGadgets(TRUE); - break; - case QM_COULDNOTNEGOTIATEFIREWALLS: - TheGameSpyInfo->addText(TheGameText->fetch("QM:COULDNOTNEGOTIATEFIREWALLS"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - buttonWiden->winEnable( FALSE ); - buttonStart->winHide( FALSE ); - buttonStop->winHide( TRUE ); - enableOptionsGadgets(TRUE); - break; - case QM_STOPPED: - TheGameSpyInfo->addText(TheGameText->fetch("QM:STOPPED"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - buttonWiden->winEnable( FALSE ); - buttonStart->winHide( FALSE ); - buttonStop->winHide( TRUE ); - enableOptionsGadgets(TRUE); - break; - } - } - break; - } - } -#ifdef PERF_TEST - // check performance - end = timeGetTime(); - UnsignedInt frameTime = end-start; - if (frameTime > 100 || responses.size() > 20) - { - UnicodeString munkee; - munkee.format(L"inQM:%d %d ms, %d messages", s_inQM, frameTime, responses.size()); - TheGameSpyInfo->addText(munkee, GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - PERF_LOG(("%ls\n", munkee.str())); - - std::list::const_iterator it; - for (it = responses.begin(); it != responses.end(); ++it) - { - PERF_LOG((" %s\n", getMessageString(*it))); - } - } -#endif // PERF_TEST - } -}// WOLQuickMatchMenuUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Quick Match Menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLQuickMatchMenuInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - if (buttonPushed) - break; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - if(!buttonBack->winIsHidden()) - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonBack, buttonBackID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// WOLQuickMatchMenuInput - -//------------------------------------------------------------------------------------------------- -/** WOL Quick Match Menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLQuickMatchMenuSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - - switch( msg ) - { - - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - case GCM_SELECTED: - { - if (buttonPushed) - break; - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - Int pos = -1; - GadgetComboBoxGetSelectedPos(control, &pos); - - saveQuickMatchOptions(); - if (controlID == comboBoxLadderID && !isPopulatingLadderBox) - { - if (pos >= 0) - { - QuickMatchPreferences pref; - Int ladderID = (Int)GadgetComboBoxGetItemData(control, pos); - if (ladderID == 0) - { - // no ladder selected - enable buttons - GadgetComboBoxSetSelectedPos(comboBoxNumPlayers, max(0, pref.getNumPlayers()/2-1)); - comboBoxNumPlayers->winEnable( TRUE ); - populateQMSideComboBox(pref.getSide()); // this will set side to random and disable if necessary - } - else if (ladderID > 0) - { - // ladder selected - disable buttons - const LadderInfo *li = TheLadderList->findLadderByIndex(ladderID); - if (li) - GadgetComboBoxSetSelectedPos(comboBoxNumPlayers, li->playersPerTeam-1); - else - GadgetComboBoxSetSelectedPos(comboBoxNumPlayers, 0); - comboBoxNumPlayers->winEnable( FALSE ); - - populateQMSideComboBox(pref.getSide(), li); // this will set side to random and disable if necessary - } - else - { - // "Choose a ladder" selected - open overlay - PopulateQMLadderComboBox(); // this restores the non-"Choose a ladder" selection - GameSpyOpenOverlay( GSOVERLAY_LADDERSELECT ); - } - } - } - if (!isInInit) - { - QuickMatchPreferences pref; - populateQuickMatchMapSelectListbox(pref); - UpdateStartButton(); - } - break; - } // case GCM_SELECTED - - case GBM_SELECTED: - { - if (buttonPushed) - break; - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - static NameKeyType buttonOptionsID = NAMEKEY("WOLQuickMatchMenu.wnd:ButtonOptions"); - - if ( controlID == buttonStopID ) - { - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_STOPQUICKMATCH; - TheGameSpyPeerMessageQueue->addRequest(req); - buttonWiden->winEnable( FALSE ); - buttonStart->winHide( FALSE ); - buttonStop->winHide( TRUE ); - enableOptionsGadgets(TRUE); - TheGameSpyInfo->addText(TheGameText->fetch("GUI:QMAborted"), GameSpyColor[GSCOLOR_DEFAULT], quickmatchTextWindow); - } - else if ( controlID == buttonOptionsID ) - { - GameWindow *win =TheWindowManager->winGetWindowFromId(parentWOLQuickMatch,buttonOptionsID); - if (isInfoShown()) - { - hideInfoGadgets(TRUE); - hideOptionsGadgets(FALSE); - GadgetButtonSetText(win, TheGameText->fetch("GUI:PlayerInfo")); - } - else - { - hideInfoGadgets(FALSE); - hideOptionsGadgets(TRUE); - GadgetButtonSetText(win, TheGameText->fetch("GUI:Setup")); - } - } - else if ( controlID == buttonWidenID ) - { - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_WIDENQUICKMATCHSEARCH; - TheGameSpyPeerMessageQueue->addRequest(req); - buttonWiden->winEnable( FALSE ); - } - else if ( controlID == buttonStartID ) - { - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_STARTQUICKMATCH; - req.qmMaps.clear(); - Int numMaps = GadgetListBoxGetNumEntries(listboxMapSelect); - for ( Int i=0; i= maxPingEntries - 1) - { - req.QM.maxPing = TheGameSpyConfig->getPingTimeoutInMs(); - } - else - req.QM.maxPing = (val+1)*100; - - PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(TheGameSpyInfo->getLocalProfileID()); - req.QM.points = CalculateRank(stats); - - Int ladderIndex, index, selected; - GadgetComboBoxGetSelectedPos( comboBoxLadder, &selected ); - ladderIndex = (Int)GadgetComboBoxGetItemData( comboBoxLadder, selected ); - const LadderInfo *ladderInfo = NULL; - if (ladderIndex < 0) - { - ladderIndex = 0; - } - if (ladderIndex) - { - ladderInfo = TheLadderList->findLadderByIndex( ladderIndex ); - if (!ladderInfo) - { - ladderIndex = 0; // sanity - } - } - req.QM.ladderID = ladderIndex; - - req.QM.ladderPassCRC = 0; - - index = -1; - GadgetComboBoxGetSelectedPos( comboBoxSide, &selected ); - if (selected >= 0) - index = (Int)GadgetComboBoxGetItemData( comboBoxSide, selected ); - req.QM.side = index; - if (ladderInfo && ladderInfo->randomFactions) - { - Int sideNum = GameClientRandomValue(0, ladderInfo->validFactions.size()-1); - DEBUG_LOG(("Looking for %d out of %d random sides\n", sideNum, ladderInfo->validFactions.size())); - AsciiStringListConstIterator cit = ladderInfo->validFactions.begin(); - while (sideNum) - { - ++cit; - --sideNum; - } - if (cit != ladderInfo->validFactions.end()) - { - Int numPlayerTemplates = ThePlayerTemplateStore->getPlayerTemplateCount(); - AsciiString sideStr = *cit; - DEBUG_LOG(("Chose %s as our side... finding\n", sideStr.str())); - for (Int c=0; cgetNthPlayerTemplate(c); - if (fac && fac->getSide() == sideStr) - { - DEBUG_LOG(("Found %s in index %d\n", sideStr.str(), c)); - req.QM.side = c; - break; - } - } - } - } - else if( index == PLAYERTEMPLATE_RANDOM ) - { - // If not a forced random ladder, then we need to resolve our pick of random right now anyway, or else - // we will get the same pick every darn time. - Int randomTries = 0;// Rare to hit Random 10 times in a row, but if it does then random will be converted to a set side by the very bug this tries to fix, so no harm done. - - while( randomTries < 10 && index == PLAYERTEMPLATE_RANDOM ) - { - Int numberComboBoxEntries = GadgetComboBoxGetLength(comboBoxSide); - Int randomPick = GameClientRandomValue(0, numberComboBoxEntries - 1); - index = (Int)GadgetComboBoxGetItemData( comboBoxSide, randomPick ); - req.QM.side = index; - - randomTries++; - } - } - - index = -1; - GadgetComboBoxGetSelectedPos( comboBoxColor, &selected ); - if (selected >= 0) - index = (Int)GadgetComboBoxGetItemData( comboBoxColor, selected ); - req.QM.color = index; - - OptionPreferences natPref; - req.QM.NAT = natPref.getFirewallBehavior(); - - if (ladderIndex) - { - req.QM.numPlayers = (ladderInfo)?ladderInfo->playersPerTeam*2 : 2; - } - else - { - GadgetComboBoxGetSelectedPos(comboBoxNumPlayers, &val); - if (val < 0) - val = 0; - req.QM.numPlayers = (val+1)*2; - } - - Int numDiscons = 0; - PerGeneralMap::iterator it; - for(it =stats.discons.begin(); it != stats.discons.end(); ++it) - { - numDiscons += it->second; - } - for(it =stats.desyncs.begin(); it != stats.desyncs.end(); ++it) - { - numDiscons += it->second; - } - req.QM.discons = numDiscons; - - - strncpy(req.QM.pings, TheGameSpyInfo->getPingString().str(), 17); - req.QM.pings[16] = 0; - - req.QM.botID = TheGameSpyConfig->getQMBotID(); - req.QM.roomID = TheGameSpyConfig->getQMChannel(); - - req.QM.exeCRC = TheGlobalData->m_exeCRC; - req.QM.iniCRC = TheGlobalData->m_iniCRC; - - TheGameSpyPeerMessageQueue->addRequest(req); - buttonWiden->winEnable( FALSE ); - buttonStart->winHide( TRUE ); - buttonStop->winHide( FALSE ); - enableOptionsGadgets(FALSE); - - if (ladderIndex > 0) - { - // save the ladder as being played upon even if we cancel out of matching early... - LadderPreferences ladPref; - ladPref.loadProfile( TheGameSpyInfo->getLocalProfileID() ); - LadderPref p; - p.lastPlayDate = time(NULL); - p.address = ladderInfo->address; - p.port = ladderInfo->port; - p.name = ladderInfo->name; - ladPref.addRecentLadder( p ); - ladPref.write(); - } - } - else if ( controlID == buttonBuddiesID ) - { - GameSpyToggleOverlay( GSOVERLAY_BUDDY ); - } - else if ( controlID == buttonBackID ) - { - buttonPushed = true; - TheGameSpyInfo->leaveGroupRoom(); - nextScreen = "Menus/WOLWelcomeMenu.wnd"; - TheShell->pop(); - } //if ( controlID == buttonBack ) - else if ( controlID == buttonSelectAllMapsID ) - { - Int numMaps = GadgetListBoxGetNumEntries(listboxMapSelect); - for ( Int i=0; iwinGetWindowId(); - Int selected = (Int)mData2; - - if ( controlID == listboxMapSelectID ) - { - const LadderInfo *li = getLadderInfo(); - if (selected >= 0 && (!li || !li->randomMaps)) - { - Bool wasSelected = (Bool)GadgetListBoxGetItemData(control, selected, 0); - GadgetListBoxSetItemData(control, (void *)(!wasSelected), selected, 0); - Int width = 10; - Int height = 10; - const Image *img = (!wasSelected)?selectedImage:unselectedImage; - if ( img ) - { - width = min(GadgetListBoxGetColumnWidth(control, 0), img->getImageWidth()); - height = width; - } - GadgetListBoxAddEntryImage(control, img, selected, 0, height, width); - GadgetListBoxAddEntryText(control, GadgetListBoxGetText(control, selected, 1), GameSpyColor[(wasSelected)?GSCOLOR_MAP_UNSELECTED:GSCOLOR_MAP_SELECTED], selected, 1); - } - if (selected >= 0) - GadgetListBoxSetSelected(control, -1); - } - UpdateStartButton(); - break; - }// case GLM_SELECTED - - case GEM_EDIT_DONE: - { - break; - } - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLQuickMatchMenuSystem diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLStatusMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLStatusMenu.cpp deleted file mode 100644 index e951b7ed935..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLStatusMenu.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLLoginMenu.cpp -// Author: Chris Huybregts, November 2001 -// Description: Lan Lobby Menu -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetTextEntry.h" -//#include "GameNetwork/WOL.h" -//#include "GameNetwork/WOLmenus.h" - - - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentWOLStatusID = NAMEKEY_INVALID; -static NameKeyType buttonDisconnectID = NAMEKEY_INVALID; - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentWOLStatus = NULL; -static GameWindow *buttonDisconnect = NULL; -GameWindow *progressTextWindow = NULL; - -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Status Menu */ -//------------------------------------------------------------------------------------------------- -void WOLStatusMenuInit( WindowLayout *layout, void *userData ) -{ - parentWOLStatusID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLStatusMenu.wnd:WOLStatusMenuParent" ) ); - buttonDisconnectID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLStatusMenu.wnd:ButtonDisconnect" ) ); - parentWOLStatus = TheWindowManager->winGetWindowFromId( NULL, parentWOLStatusID ); - buttonDisconnect = TheWindowManager->winGetWindowFromId( NULL, buttonDisconnectID); - - progressTextWindow = TheWindowManager->winGetWindowFromId( NULL, - TheNameKeyGenerator->nameToKey( AsciiString( "WOLStatusMenu.wnd:ListboxStatus" ) ) ); - - // Show Menu - layout->hide( FALSE ); - - // Set Keyboard to Main Parent - TheWindowManager->winSetFocus( parentWOLStatus ); - - //progressLayout = TheShell->top(); - - //WOL::raiseWOLMessageBox(); -} // WOLStatusMenuInit - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLStatusMenuShutdown( WindowLayout *layout, void *userData ) -{ - - // hide menu - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout ); - - //progressLayout = NULL; - - //WOL::raiseWOLMessageBox(); -} // WOLStatusMenuShutdown - - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLStatusMenuUpdate( WindowLayout * layout, void *userData) -{ - //if (WOL::TheWOL) - //WOL::TheWOL->update(); -}// WOLStatusMenuUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLStatusMenuInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonDisconnect, buttonDisconnectID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// WOLStatusMenuInput - -//------------------------------------------------------------------------------------------------- -/** WOL Status Menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLStatusMenuSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - - switch( msg ) - { - - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - case GBM_SELECTED: - { - /* - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if ( controlID == buttonDisconnectID ) - { - //TheShell->pop(); - if (WOL::TheWOL->setState( WOL::WOLAPI_FATAL_ERROR )) - { - WOL::TheWOL->addCommand( WOL::WOLCOMMAND_RESET ); // don't display an error, log out, or anything - } - - } //if ( controlID == buttonDisconnect ) - */ - break; - }// case GBM_SELECTED: - - case GEM_EDIT_DONE: - { - break; - } - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLStatusMenuSystem diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLWelcomeMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLWelcomeMenu.cpp deleted file mode 100644 index 6aaf468ffd5..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLWelcomeMenu.cpp +++ /dev/null @@ -1,905 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: WOLWelcomeMenu.cpp -// Author: Chris Huybregts, November 2001 -// Description: Lan Lobby Menu -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "GameSpy/peer/peer.h" - -#include "Common/GameEngine.h" -#include "Common/GameSpyMiscPreferences.h" -#include "Common/CustomMatchPreferences.h" -#include "Common/GlobalData.h" -#include "Common/UserPreferences.h" -#include "Common/PlayerTemplate.h" - -#include "GameClient/AnimateWindowManager.h" -#include "GameClient/Display.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/GameText.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/GadgetCheckBox.h" -#include "GameClient/MessageBox.h" -#include "GameClient/GameWindowTransitions.h" - -#include "GameNetwork/FirewallHelper.h" -#include "GameNetwork/GameSpyOverlay.h" - -#include "GameNetwork/GameSpy/BuddyDefs.h" -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PersistentStorageDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/ThreadUtils.h" -#include "GameNetwork/GameSpy/MainMenuUtils.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -static Bool isShuttingDown = FALSE; -static Bool buttonPushed = FALSE; -static char *nextScreen = NULL; - -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentWOLWelcomeID = NAMEKEY_INVALID; -static NameKeyType buttonBackID = NAMEKEY_INVALID; -static NameKeyType buttonQuickMatchID = NAMEKEY_INVALID; -static NameKeyType buttonLobbyID = NAMEKEY_INVALID; -static NameKeyType buttonBuddiesID = NAMEKEY_INVALID; -static NameKeyType buttonLadderID = NAMEKEY_INVALID; -static NameKeyType buttonMyInfoID = NAMEKEY_INVALID; - -static NameKeyType listboxInfoID = NAMEKEY_INVALID; -static NameKeyType buttonOptionsID = NAMEKEY_INVALID; -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parentWOLWelcome = NULL; -static GameWindow *buttonBack = NULL; -static GameWindow *buttonQuickMatch = NULL; -static GameWindow *buttonLobby = NULL; -static GameWindow *buttonBuddies = NULL; -static GameWindow *buttonLadder = NULL; -static GameWindow *buttonMyInfo = NULL; -static GameWindow *buttonbuttonOptions = NULL; -static WindowLayout *welcomeLayout = NULL; -static GameWindow *listboxInfo = NULL; - -static GameWindow *staticTextServerName = NULL; -static GameWindow *staticTextLastUpdated = NULL; - -static GameWindow *staticTextLadderWins = NULL; -static GameWindow *staticTextLadderLosses = NULL; -static GameWindow *staticTextLadderRank = NULL; -static GameWindow *staticTextLadderPoints = NULL; -static GameWindow *staticTextLadderDisconnects = NULL; - -static GameWindow *staticTextHighscoreWins = NULL; -static GameWindow *staticTextHighscoreLosses = NULL; -static GameWindow *staticTextHighscoreRank = NULL; -static GameWindow *staticTextHighscorePoints = NULL; - -static UnicodeString gServerName; -void updateServerDisplay(UnicodeString serverName) -{ - if (staticTextServerName) - { - GadgetStaticTextSetText(staticTextServerName, serverName); - } - gServerName = serverName; -} - -/* -void updateLocalPlayerScores(AsciiString name, const WOL::Ladder *ladder, const WOL::Highscore *highscore) -{ - if (ladder) - { - AsciiString a; - UnicodeString u; - - a.format("%d", ladder->wins); - u.translate(a); - GadgetStaticTextSetText(staticTextLadderWins, u); - - a.format("%d", ladder->losses); - u.translate(a); - GadgetStaticTextSetText(staticTextLadderLosses, u); - - a.format("%d", ladder->rank); - u.translate(a); - GadgetStaticTextSetText(staticTextLadderRank, u); - - a.format("%d", ladder->points); - u.translate(a); - GadgetStaticTextSetText(staticTextLadderPoints, u); - - a.format("%d", ladder->disconnects); - u.translate(a); - GadgetStaticTextSetText(staticTextLadderDisconnects, u); - } - if (highscore) - { - AsciiString a; - UnicodeString u; - - a.format("%d", highscore->wins); - u.translate(a); - GadgetStaticTextSetText(staticTextHighscoreWins, u); - - a.format("%d", highscore->losses); - u.translate(a); - GadgetStaticTextSetText(staticTextHighscoreLosses, u); - - a.format("%d", highscore->rank); - u.translate(a); - GadgetStaticTextSetText(staticTextHighscoreRank, u); - - a.format("%d", highscore->points); - u.translate(a); - GadgetStaticTextSetText(staticTextHighscorePoints, u); - } -} -*/ - - -static void enableControls( Bool state ) -{ - if (buttonQuickMatch) - buttonQuickMatch->winEnable(state); - if (buttonLobby) - buttonLobby->winEnable(state); -} - -//------------------------------------------------------------------------------------------------- -/** This is called when a shutdown is complete for this menu */ -//------------------------------------------------------------------------------------------------- -static void shutdownComplete( WindowLayout *layout ) -{ - - isShuttingDown = FALSE; - - // hide the layout - layout->hide( TRUE ); - - // our shutdown is complete - TheShell->shutdownComplete( layout, (nextScreen != NULL) ); - - if (nextScreen != NULL) - { - TheShell->push(nextScreen); - } - - nextScreen = NULL; - -} // end if - -//------------------------------------------------------------------------------------------------- -/** Handle Num Players Online data */ -//------------------------------------------------------------------------------------------------- - -static Int lastNumPlayersOnline = 0; - -static UnsignedByte grabUByte(const char *s) -{ - char tmp[5] = "0xff"; - tmp[2] = s[0]; - tmp[3] = s[1]; - UnsignedByte b = strtol(tmp, NULL, 16); - return b; -} - -static void updateNumPlayersOnline(void) -{ - GameWindow *playersOnlineWindow = TheWindowManager->winGetWindowFromId( - NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextNumPlayersOnline") ); - - if (playersOnlineWindow) - { - UnicodeString valStr; - valStr.format(TheGameText->fetch("GUI:NumPlayersOnline"), lastNumPlayersOnline); - GadgetStaticTextSetText(playersOnlineWindow, valStr); - } - - if (listboxInfo && TheGameSpyInfo) - { - GadgetListBoxReset(listboxInfo); - AsciiString aLine; - UnicodeString line; - AsciiString aMotd = TheGameSpyInfo->getMOTD(); - UnicodeString headingStr; - //Kris: Patch 1.01 - November 12, 2003 - //Removed number of players from string, and removed the argument. The number is incorrect anyways... - //This was a Harvard initiated fix. - headingStr.format(TheGameText->fetch("MOTD:NumPlayersHeading")); - - while (headingStr.nextToken(&line, UnicodeString(L"\n"))) - { - if (line.getCharAt(line.getLength()-1) == '\r') - line.removeLastChar(); // there is a trailing '\r' - - line.trim(); - - if (line.isEmpty()) - { - line = UnicodeString(L" "); - } - - GadgetListBoxAddEntryText(listboxInfo, line, GameSpyColor[GSCOLOR_MOTD_HEADING], -1, -1); - } - GadgetListBoxAddEntryText(listboxInfo, UnicodeString(L" "), GameSpyColor[GSCOLOR_MOTD_HEADING], -1, -1); - - while (aMotd.nextToken(&aLine, "\n")) - { - if (aLine.getCharAt(aLine.getLength()-1) == '\r') - aLine.removeLastChar(); // there is a trailing '\r' - - aLine.trim(); - - if (aLine.isEmpty()) - { - aLine = " "; - } - - Color c = GameSpyColor[GSCOLOR_MOTD]; - if (aLine.startsWith("\\\\")) - { - aLine = aLine.str()+1; - } - else if (aLine.startsWith("\\") && aLine.getLength() > 9) - { - // take out the hex value from strings starting as "\ffffffffText" - UnsignedByte a, r, g, b; - a = grabUByte(aLine.str()+1); - r = grabUByte(aLine.str()+3); - g = grabUByte(aLine.str()+5); - b = grabUByte(aLine.str()+7); - c = GameMakeColor(r, g, b, a); - DEBUG_LOG(("MOTD line '%s' has color %X\n", aLine.str(), c)); - aLine = aLine.str() + 9; - } - line = UnicodeString(MultiByteToWideCharSingleLine(aLine.str()).c_str()); - - GadgetListBoxAddEntryText(listboxInfo, line, c, -1, -1); - } - } -} - -void HandleNumPlayersOnline( Int numPlayersOnline ) -{ - lastNumPlayersOnline = numPlayersOnline; - if (lastNumPlayersOnline < 1) - lastNumPlayersOnline = 1; - updateNumPlayersOnline(); -} - -//------------------------------------------------------------------------------------------------- -/** Handle Overall Stats data */ -//------------------------------------------------------------------------------------------------- -static std::map s_winStats; -static float s_totalWinPercent = 0; - -static const char* FindNextNumber( const char* pStart ) -{ - char* pNum = strchr( pStart, '\n' ); //go to next line - if( !pNum ) - return pStart; //error - - while( !isdigit(*pNum) ) - ++pNum; //go to next number - return pNum; -} - - -//parse win/loss stats received from GameSpy -void HandleOverallStats( const char* szHTTPStats, unsigned len ) -{ -//x DEBUG_LOG(("Parsing win percent stats:\n%s\n", szHTTPStats)); - //find today's stats - const char* pToday = strstr( szHTTPStats, "Today" ); - if( !pToday ) - { //error - DEBUG_LOG(( "Unable to parse win/loss stats. Could not find 'Today' in:\n%s\n", szHTTPStats )); - return; - } - s_winStats.clear(); - s_totalWinPercent = 0; - - //find win/loss for each side - for( int i = 0; i < ThePlayerTemplateStore->getPlayerTemplateCount(); i++) - { //get current side (USA, GLA, etc.) - const PlayerTemplate* pTemplate = ThePlayerTemplateStore->getNthPlayerTemplate(i); - if( !pTemplate->isPlayableSide() || pTemplate->getSide().compare("Boss") == 0 ) - continue; //skip non-players - - AsciiString side = pTemplate->getSide(); - if( side == "America" ) - side = "USA"; //conform to GameSpy name - - //find this side - const char* pSide = strstr( pToday, side.str() ); - if( pSide == NULL ) - { //error, skip this side - DEBUG_LOG(( "Unable to parse win/loss stats for %s in:\n%s\n", side.str(), szHTTPStats )); - continue; - } - - //Note: win% reported by GameSpy = team's wins / #games played by team - // we want win% = team's wins / total # games played by all teams - const char* pTotal = FindNextNumber(pSide); - const char* pWins = FindNextNumber(pTotal); - float percent = atof(pWins) / max(1,atof(pTotal)); //max prevents divide by zero - s_totalWinPercent += percent; - - s_winStats.insert(std::make_pair( side, percent )); -//x DEBUG_LOG(("Added win percent: %s, %d\n", side.str(), percent)); - } //for i -} //HandleOverallStats - - -//called only from WOLWelcomeMenuInit to set %win stats -static void updateOverallStats(void) -{ - UnicodeString percStr; - AsciiString wndName; - GameWindow* pWin; - - if( s_totalWinPercent <= 0 ) - s_totalWinPercent = 1; //prevent divide by zero - - std::map::iterator it; - for( it = s_winStats.begin(); it != s_winStats.end(); ++it ) - { - int percent = REAL_TO_INT(100.0f * (it->second / s_totalWinPercent)); - percStr.format( TheGameText->fetch("GUI:WinPercent"), percent ); - wndName.format( "WOLWelcomeMenu.wnd:Percent%s", it->first.str() ); - pWin = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY(wndName) ); - GadgetCheckBoxSetText( pWin, percStr ); -//x DEBUG_LOG(("Initialized win percent: %s -> %s %f=%s\n", wndName.str(), it->first.str(), it->second, percStr.str() )); - } //for -} //updateOverallStats - - -//------------------------------------------------------------------------------------------------- -/** Handle player stats */ -//------------------------------------------------------------------------------------------------- - -void UpdateLocalPlayerStats(void) -{ - - GameWindow *welcomeParent = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:WOLWelcomeMenuParent") ); - - if (welcomeParent) - { - PopulatePlayerInfoWindows( "WOLWelcomeMenu.wnd" ); - } - else - { - PopulatePlayerInfoWindows( "WOLQuickMatchMenu.wnd" ); - } - - return; -} - -static Bool raiseMessageBoxes = FALSE; -//------------------------------------------------------------------------------------------------- -/** Initialize the WOL Welcome Menu */ -//------------------------------------------------------------------------------------------------- -void WOLWelcomeMenuInit( WindowLayout *layout, void *userData ) -{ - nextScreen = NULL; - buttonPushed = FALSE; - isShuttingDown = FALSE; - - welcomeLayout = layout; - - //TheWOL->reset(); - - parentWOLWelcomeID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:WOLWelcomeMenuParent" ) ); - buttonBackID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonBack" ) ); - parentWOLWelcome = TheWindowManager->winGetWindowFromId( NULL, parentWOLWelcomeID ); - buttonBack = TheWindowManager->winGetWindowFromId( NULL, buttonBackID); - buttonOptionsID = TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:ButtonOptions" ); - buttonbuttonOptions = TheWindowManager->winGetWindowFromId( NULL, buttonOptionsID); - listboxInfoID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:InfoListbox" ) ); - - listboxInfo = TheWindowManager->winGetWindowFromId( NULL, listboxInfoID); - - staticTextServerName = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextServerName" )); - staticTextLastUpdated = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLastUpdated" )); - - staticTextLadderWins = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLadderWins" )); - staticTextLadderLosses = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLadderLosses" )); - staticTextLadderPoints = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLadderPoints" )); - staticTextLadderRank = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLadderRank" )); - staticTextLadderDisconnects = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextDisconnects" )); - - staticTextHighscoreWins = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextHighscoreWins" )); - staticTextHighscoreLosses = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextHighscoreLosses" )); - staticTextHighscorePoints = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextHighscorePoints" )); - staticTextHighscoreRank = TheWindowManager->winGetWindowFromId( parentWOLWelcome, - TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextHighscoreRank" )); - - if (staticTextServerName) - { - GadgetStaticTextSetText(staticTextServerName, gServerName); - } - - GameWindow *staticTextTitle = TheWindowManager->winGetWindowFromId(parentWOLWelcome, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextTitle")); - if (staticTextTitle && TheGameSpyInfo) - { - UnicodeString title; - title.format(TheGameText->fetch("GUI:WOLWelcome"), TheGameSpyInfo->getLocalBaseName().str()); - GadgetStaticTextSetText(staticTextTitle, title); - } - - // Clear some defaults - /* - UnicodeString questionMark = UnicodeString(L"?"); - GadgetStaticTextSetText(staticTextLastUpdated, questionMark); - GadgetStaticTextSetText(staticTextLadderWins, questionMark); - GadgetStaticTextSetText(staticTextLadderLosses, questionMark); - GadgetStaticTextSetText(staticTextLadderPoints, questionMark); - GadgetStaticTextSetText(staticTextLadderRank, questionMark); - GadgetStaticTextSetText(staticTextLadderDisconnects, questionMark); - GadgetStaticTextSetText(staticTextHighscoreWins, questionMark); - GadgetStaticTextSetText(staticTextHighscoreLosses, questionMark); - GadgetStaticTextSetText(staticTextHighscorePoints, questionMark); - GadgetStaticTextSetText(staticTextHighscoreRank, questionMark); - */ - - //DEBUG_ASSERTCRASH(listboxInfo, ("No control found!")); - - buttonQuickMatchID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonQuickMatch" ) ); - buttonQuickMatch = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonQuickMatchID ); - - buttonLobbyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonCustomMatch" ) ); - buttonLobby = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonLobbyID ); - - buttonBuddiesID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonBuddies" ) ); - buttonBuddies = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonBuddiesID ); - - buttonMyInfoID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonMyInfo" ) ); - buttonMyInfo = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonMyInfoID ); - - buttonLadderID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonLadder" ) ); - buttonLadder = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonLadderID ); - - if (TheFirewallHelper == NULL) { - TheFirewallHelper = createFirewallHelper(); - } - if (TheFirewallHelper->detectFirewall() == TRUE) { - // don't need to detect firewall, already been done. - delete TheFirewallHelper; - TheFirewallHelper = NULL; - } - /* - - if (TheGameSpyChat && TheGameSpyChat->isConnected()) - { - const char *keys[3] = { "locale", "wins", "losses" }; - char valueStrings[3][20]; - char *values[3] = { valueStrings[0], valueStrings[1], valueStrings[2] }; - _snprintf(values[0], 20, "%s", TheGameSpyPlayerInfo->getLocale().str()); - _snprintf(values[1], 20, "%d", TheGameSpyPlayerInfo->getWins()); - _snprintf(values[2], 20, "%d", TheGameSpyPlayerInfo->getLosses()); - peerSetGlobalKeys(TheGameSpyChat->getPeer(), 3, (const char **)keys, (const char **)values); - peerSetGlobalWatchKeys(TheGameSpyChat->getPeer(), GroupRoom, 3, keys, PEERFalse); - peerSetGlobalWatchKeys(TheGameSpyChat->getPeer(), StagingRoom, 3, keys, PEERFalse); - } - */ - -// // animate controls -// TheShell->registerWithAnimateManager(buttonQuickMatch, WIN_ANIMATION_SLIDE_LEFT, TRUE, 800); -// TheShell->registerWithAnimateManager(buttonLobby, WIN_ANIMATION_SLIDE_LEFT, TRUE, 600); -// //TheShell->registerWithAnimateManager(NULL, WIN_ANIMATION_SLIDE_LEFT, TRUE, 400); -// TheShell->registerWithAnimateManager(buttonBuddies, WIN_ANIMATION_SLIDE_LEFT, TRUE, 200); -// //TheShell->registerWithAnimateManager(NULL, WIN_ANIMATION_SLIDE_LEFT, TRUE, 1); -// TheShell->registerWithAnimateManager(buttonBack, WIN_ANIMATION_SLIDE_BOTTOM, TRUE, 1); - - // Show Menu - layout->hide( FALSE ); - - // Set Keyboard to Main Parent - TheWindowManager->winSetFocus( parentWOLWelcome ); - - enableControls( TheGameSpyInfo->gotGroupRoomList() ); - TheShell->showShellMap(TRUE); - - updateNumPlayersOnline(); - updateOverallStats(); - - UpdateLocalPlayerStats(); - - GameSpyMiscPreferences cPref; - if (cPref.getLocale() < LOC_MIN || cPref.getLocale() > LOC_MAX) - { - GameSpyOpenOverlay(GSOVERLAY_LOCALESELECT); - } - - raiseMessageBoxes = TRUE; - TheTransitionHandler->setGroup("WOLWelcomeMenuFade"); - -} // WOLWelcomeMenuInit - -//------------------------------------------------------------------------------------------------- -/** WOL Welcome Menu shutdown method */ -//------------------------------------------------------------------------------------------------- -void WOLWelcomeMenuShutdown( WindowLayout *layout, void *userData ) -{ - listboxInfo = NULL; - - if (TheFirewallHelper != NULL) { - delete TheFirewallHelper; - TheFirewallHelper = NULL; - } - - isShuttingDown = TRUE; - - // if we are shutting down for an immediate pop, skip the animations - Bool popImmediate = *(Bool *)userData; - if( popImmediate ) - { - - shutdownComplete( layout ); - return; - - } //end if - - TheShell->reverseAnimatewindow(); - TheTransitionHandler->reverse("WOLWelcomeMenuFade"); - - - RaiseGSMessageBox(); -} // WOLWelcomeMenuShutdown - - -//------------------------------------------------------------------------------------------------- -/** WOL Welcome Menu update method */ -//------------------------------------------------------------------------------------------------- -void WOLWelcomeMenuUpdate( WindowLayout * layout, void *userData) -{ - // We'll only be successful if we've requested to - if(isShuttingDown && TheShell->isAnimFinished() && TheTransitionHandler->isFinished()) - shutdownComplete(layout); - - if (raiseMessageBoxes) - { - RaiseGSMessageBox(); - raiseMessageBoxes = FALSE; - } - - if (TheFirewallHelper != NULL) - { - if (TheFirewallHelper->behaviorDetectionUpdate()) - { - TheWritableGlobalData->m_firewallBehavior = TheFirewallHelper->getFirewallBehavior(); - - TheFirewallHelper->writeFirewallBehavior(); - - TheFirewallHelper->flagNeedToRefresh(FALSE); // 2/19/03 BGC, we're done, so we don't need to refresh the NAT anymore. - - // we are now done with the firewall helper - delete TheFirewallHelper; - TheFirewallHelper = NULL; - } - } - - if (TheShell->isAnimFinished() && !buttonPushed && TheGameSpyPeerMessageQueue) - { - HandleBuddyResponses(); - HandlePersistentStorageResponses(); - - Int allowedMessages = TheGameSpyInfo->getMaxMessagesPerUpdate(); - Bool sawImportantMessage = FALSE; - PeerResponse resp; - while (allowedMessages-- && !sawImportantMessage && TheGameSpyPeerMessageQueue->getResponse( resp )) - { - switch (resp.peerResponseType) - { - case PeerResponse::PEERRESPONSE_GROUPROOM: - { - GameSpyGroupRoom room; - room.m_groupID = resp.groupRoom.id; - room.m_maxWaiting = resp.groupRoom.maxWaiting; - room.m_name = resp.groupRoomName.c_str(); - room.m_translatedName = UnicodeString(L"TEST"); - room.m_numGames = resp.groupRoom.numGames; - room.m_numPlaying = resp.groupRoom.numPlaying; - room.m_numWaiting = resp.groupRoom.numWaiting; - TheGameSpyInfo->addGroupRoom( room ); - if (room.m_groupID == 0) - { - enableControls( TRUE ); - } - } - break; - case PeerResponse::PEERRESPONSE_JOINGROUPROOM: - { - sawImportantMessage = TRUE; - enableControls( TRUE ); - if (resp.joinGroupRoom.ok) - { - //buttonPushed = TRUE; - TheGameSpyInfo->setCurrentGroupRoom(resp.joinGroupRoom.id); - //GSMessageBoxOk( TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSGroupRoomJoinOK") ); - - buttonPushed = TRUE; - nextScreen = "Menus/WOLCustomLobby.wnd"; - TheShell->pop(); - //TheShell->push( "Menus/WOLCustomLobby.wnd" ); - } - else - { - GSMessageBoxOk( TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSGroupRoomJoinFail") ); - } - } - break; - case PeerResponse::PEERRESPONSE_DISCONNECT: - { - sawImportantMessage = TRUE; - UnicodeString title, body; - AsciiString disconMunkee; - disconMunkee.format("GUI:GSDisconReason%d", resp.discon.reason); - title = TheGameText->fetch( "GUI:GSErrorTitle" ); - body = TheGameText->fetch( disconMunkee ); - GameSpyCloseAllOverlays(); - GSMessageBoxOk( title, body ); - TheShell->pop(); - } - break; - } - } - } - -}// WOLWelcomeMenuUpdate - -//------------------------------------------------------------------------------------------------- -/** WOL Welcome Menu input callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLWelcomeMenuInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - switch( msg ) - { - - // -------------------------------------------------------------------------------------------- - case GWM_CHAR: - { - UnsignedByte key = mData1; - UnsignedByte state = mData2; - if (buttonPushed) - break; - - switch( key ) - { - - // ---------------------------------------------------------------------------------------- - case KEY_ESC: - { - - // - // send a simulated selected event to the parent window of the - // back/exit button - // - if( BitTest( state, KEY_STATE_UP ) ) - { - TheWindowManager->winSendSystemMsg( window, GBM_SELECTED, - (WindowMsgData)buttonBack, buttonBackID ); - - } // end if - - // don't let key fall through anywhere else - return MSG_HANDLED; - - } // end escape - - } // end switch( key ) - - } // end char - - } // end switch( msg ) - - return MSG_IGNORED; -}// WOLWelcomeMenuInput - -//------------------------------------------------------------------------------------------------- -/** WOL Welcome Menu window system callback */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType WOLWelcomeMenuSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - UnicodeString txtInput; - - switch( msg ) - { - - - case GWM_CREATE: - { - - break; - } // case GWM_DESTROY: - - case GWM_DESTROY: - { - break; - } // case GWM_DESTROY: - - case GWM_INPUT_FOCUS: - { - // if we're givin the opportunity to take the keyboard focus we must say we want it - if( mData1 == TRUE ) - *(Bool *)mData2 = TRUE; - - return MSG_HANDLED; - }//case GWM_INPUT_FOCUS: - - case GBM_SELECTED: - { - if (buttonPushed) - break; - - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - - if ( controlID == buttonBackID ) - { - //DEBUG_ASSERTCRASH(TheGameSpyChat->getPeer(), ("No GameSpy Peer object!")); - //TheGameSpyChat->disconnectFromChat(); - - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_LOGOUT; - TheGameSpyPeerMessageQueue->addRequest( req ); - BuddyRequest breq; - breq.buddyRequestType = BuddyRequest::BUDDYREQUEST_LOGOUT; - TheGameSpyBuddyMessageQueue->addRequest( breq ); - - DEBUG_LOG(("Tearing down GameSpy from WOLWelcomeMenuSystem(GBM_SELECTED)\n")); - TearDownGameSpy(); - - /* - if (TheGameSpyChat->getPeer()) - { - peerDisconnect(TheGameSpyChat->getPeer()); - } - */ - - buttonPushed = TRUE; - - TheShell->pop(); - - /// @todo: log out instead of disconnecting - //TheWOL->addCommand( WOL::WOLCOMMAND_LOGOUT ); - /** - closeAllOverlays(); - TheShell->pop(); - delete TheWOL; - TheWOL = NULL; - delete TheWOLGame; - TheWOLGame = NULL; - **/ - - } //if ( controlID == buttonBack ) - else if (controlID == buttonOptionsID) - { - GameSpyOpenOverlay( GSOVERLAY_OPTIONS ); - } - else if (controlID == buttonQuickMatchID) - { - GameSpyMiscPreferences mPref; - if ((TheDisplay->getWidth() != 800 || TheDisplay->getHeight() != 600) && mPref.getQuickMatchResLocked()) - { - GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:QuickMatch800x600")); - } - else - { - buttonPushed = TRUE; - nextScreen = "Menus/WOLQuickMatchMenu.wnd"; - TheShell->pop(); - } - }// else if - else if (controlID == buttonMyInfoID ) - { - SetLookAtPlayer(TheGameSpyInfo->getLocalProfileID(), TheGameSpyInfo->getLocalName()); - GameSpyToggleOverlay(GSOVERLAY_PLAYERINFO); - } - else if (controlID == buttonLobbyID) - { - //TheGameSpyChat->clearGroupRoomList(); - //peerListGroupRooms(TheGameSpyChat->getPeer(), ListGroupRoomsCallback, NULL, PEERTrue); - TheGameSpyInfo->joinBestGroupRoom(); - enableControls( FALSE ); - - - /* - TheWOL->setScreen(WOL::WOLAPI_MENU_CUSTOMLOBBY); - TheWOL->setGameMode(WOL::WOLTYPE_CUSTOM); - TheWOL->setState( WOL::WOLAPI_LOBBY ); - TheWOL->addCommand( WOL::WOLCOMMAND_REFRESH_CHANNELS ); - */ - }// else if - else if (controlID == buttonBuddiesID) - { - GameSpyToggleOverlay( GSOVERLAY_BUDDY ); - /* - Bool joinedRoom = FALSE; - ClearGroupRoomList(); - peerJoinTitleRoom(TheGameSpyChat->getPeer(), JoinRoomCallback, &joinedRoom, PEERTrue); - if (joinedRoom) - { - GameSpyUsingGroupRooms = FALSE; - GameSpyCurrentGroupRoomID = 0; - TheShell->pop(); - TheShell->push("Menus/WOLCustomLobby.wnd"); - } - else - { - GameSpyCurrentGroupRoomID = 0; - GSMessageBoxOk(UnicodeString(L"Oops"), UnicodeString(L"Unable to join title room"), NULL); - } - */ - } - else if (controlID == buttonLadderID) - { - TheShell->push(AsciiString("Menus/WOLLadderScreen.wnd")); - } - break; - }// case GBM_SELECTED: - - case GEM_EDIT_DONE: - { - break; - } - default: - return MSG_IGNORED; - - }//Switch - - return MSG_HANDLED; -}// WOLWelcomeMenuSystem diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp index f57d2599c1e..0116fa2acaa 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp @@ -81,7 +81,6 @@ #include "GameClient/ChallengeGenerals.h" #include "GameLogic/FPUControl.h" #include "GameLogic/GameLogic.h" -#include "GameNetwork/GameSpy/PeerDefs.h" #include "GameNetwork/GameSpy/PersistentStorageThread.h" #include "GameNetwork/NetworkInterface.h" #include "GameNetwork/RankPointValue.h" diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp index 6b0fcc69344..f5b6a9df554 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp @@ -83,7 +83,6 @@ #include "GameNetwork/NetworkInterface.h" #include "GameNetwork/GameInfo.h" -#include "GameNetwork/GameSpyOverlay.h" #include "GameNetwork/GameSpy/BuddyThread.h" #ifdef _INTERNAL diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp index 44a3263f52d..16449fb5570 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp @@ -59,7 +59,6 @@ #include "Common/Xfer.h" #include "Common/XferCRC.h" #include "Common/XferDeepCRC.h" -#include "Common/GameSpyMiscPreferences.h" #include "GameClient/ControlBar.h" #include "GameClient/Drawable.h" @@ -103,12 +102,8 @@ #include "Common/DataChunk.h" #include "GameLogic/Scripts.h" -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/ThreadUtils.h" #include "GameNetwork/LANAPICallbacks.h" #include "GameNetwork/NetworkInterface.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" DECLARE_PERF_TIMER(SleepyMaintenance) diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Chat.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Chat.cpp deleted file mode 100644 index 3cc5c3ca6ae..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Chat.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: Chat.cpp ////////////////////////////////////////////////////// -// Generals GameSpy chat-related code -// Author: Matthew D. Campbell, July 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/AudioEventRTS.h" -#include "Common/INI.h" -#include "GameClient/GameText.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/LanguageFilter.h" -#include "GameClient/GameWindowManager.h" -#include "GameNetwork/GameSpy/PeerDefsImplementation.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameClient/InGameUI.h" -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -#define OFFSET(x) (sizeof(Int) * (x)) -static const FieldParse GameSpyColorFieldParse[] = -{ - - { "Default", INI::parseColorInt, NULL, OFFSET(GSCOLOR_DEFAULT) }, - { "CurrentRoom", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CURRENTROOM) }, - { "ChatRoom", INI::parseColorInt, NULL, OFFSET(GSCOLOR_ROOM) }, - { "Game", INI::parseColorInt, NULL, OFFSET(GSCOLOR_GAME) }, - { "GameFull", INI::parseColorInt, NULL, OFFSET(GSCOLOR_GAME_FULL) }, - { "GameCRCMismatch", INI::parseColorInt, NULL, OFFSET(GSCOLOR_GAME_CRCMISMATCH) }, - { "PlayerNormal", INI::parseColorInt, NULL, OFFSET(GSCOLOR_PLAYER_NORMAL) }, - { "PlayerOwner", INI::parseColorInt, NULL, OFFSET(GSCOLOR_PLAYER_OWNER) }, - { "PlayerBuddy", INI::parseColorInt, NULL, OFFSET(GSCOLOR_PLAYER_BUDDY) }, - { "PlayerSelf", INI::parseColorInt, NULL, OFFSET(GSCOLOR_PLAYER_SELF) }, - { "PlayerIgnored", INI::parseColorInt, NULL, OFFSET(GSCOLOR_PLAYER_IGNORED) }, - { "ChatNormal", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_NORMAL) }, - { "ChatEmote", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_EMOTE) }, - { "ChatOwner", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_OWNER) }, - { "ChatOwnerEmote", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_OWNER_EMOTE) }, - { "ChatPriv", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_PRIVATE) }, - { "ChatPrivEmote", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_PRIVATE_EMOTE) }, - { "ChatPrivOwner", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_PRIVATE_OWNER) }, - { "ChatPrivOwnerEmote", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_PRIVATE_OWNER_EMOTE) }, - { "ChatBuddy", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_BUDDY) }, - { "ChatSelf", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_SELF) }, - { "AcceptTrue", INI::parseColorInt, NULL, OFFSET(GSCOLOR_ACCEPT_TRUE) }, - { "AcceptFalse", INI::parseColorInt, NULL, OFFSET(GSCOLOR_ACCEPT_FALSE) }, - { "MapSelected", INI::parseColorInt, NULL, OFFSET(GSCOLOR_MAP_SELECTED) }, - { "MapUnselected", INI::parseColorInt, NULL, OFFSET(GSCOLOR_MAP_UNSELECTED) }, - { "MOTD", INI::parseColorInt, NULL, OFFSET(GSCOLOR_MOTD) }, - { "MOTDHeading", INI::parseColorInt, NULL, OFFSET(GSCOLOR_MOTD_HEADING) }, - - { NULL, NULL, NULL, 0 } // keep this last - -}; - -void INI::parseOnlineChatColorDefinition( INI* ini ) -{ - // parse the ini definition - ini->initFromINI( GameSpyColor, GameSpyColorFieldParse ); -} - - -Color GameSpyColor[GSCOLOR_MAX] = -{ - GameMakeColor(255,255,255,255), // GSCOLOR_DEFAULT - GameMakeColor(255,255, 0,255), // GSCOLOR_CURRENTROOM - GameMakeColor(255,255,255,255), // GSCOLOR_ROOM - GameMakeColor(128,128,0,255), // GSCOLOR_GAME - GameMakeColor(128,128,128,255), // GSCOLOR_GAME_FULL - GameMakeColor(128,128,128,255), // GSCOLOR_GAME_CRCMISMATCH - GameMakeColor(255,255,255,255), // GSCOLOR_PLAYER_NORMAL - GameMakeColor(255, 0,255,255), // GSCOLOR_PLAYER_OWNER - GameMakeColor(255, 0,128,255), // GSCOLOR_PLAYER_BUDDY - GameMakeColor(255, 0, 0,255), // GSCOLOR_PLAYER_SELF - GameMakeColor(128,128,128,255), // GSCOLOR_PLAYER_IGNORED - GameMakeColor(255,255,255,255), // GSCOLOR_CHAT_NORMAL - GameMakeColor(255,128,0,255), // GSCOLOR_CHAT_EMOTE, - GameMakeColor(255,255,0,255), // GSCOLOR_CHAT_OWNER, - GameMakeColor(128,255,0,255), // GSCOLOR_CHAT_OWNER_EMOTE, - GameMakeColor(0,0,255,255), // GSCOLOR_CHAT_PRIVATE, - GameMakeColor(0,255,255,255), // GSCOLOR_CHAT_PRIVATE_EMOTE, - GameMakeColor(255,0,255,255), // GSCOLOR_CHAT_PRIVATE_OWNER, - GameMakeColor(255,128,255,255), // GSCOLOR_CHAT_PRIVATE_OWNER_EMOTE, - GameMakeColor(255, 0,255,255), // GSCOLOR_CHAT_BUDDY, - GameMakeColor(255, 0,128,255), // GSCOLOR_CHAT_SELF, - GameMakeColor( 0,255, 0,255), // GSCOLOR_ACCEPT_TRUE, - GameMakeColor(255, 0, 0,255), // GSCOLOR_ACCEPT_FALSE, - GameMakeColor(255,255, 0,255), // GSCOLOR_MAP_SELECTED, - GameMakeColor(255,255,255,255), // GSCOLOR_MAP_UNSELECTED, - GameMakeColor(255,255,255,255), // GSCOLOR_MOTD, - GameMakeColor(255,255, 0,255), // GSCOLOR_MOTD_HEADING, -}; - -Bool GameSpyInfo::sendChat( UnicodeString message, Bool isAction, GameWindow *playerListbox ) -{ - static UnicodeString s_prevMsg = UnicodeString::TheEmptyString; //stop spam before it happens - - RoomType roomType = StagingRoom; - if (getCurrentGroupRoom()) - roomType = GroupRoom; - - PeerRequest req; - req.text = message.str(); - - message.trim(); - // Echo the user's input to the chat window - if (!message.isEmpty()) - { - if (!playerListbox) - { // Public message - if( isAction || message.compare(s_prevMsg) != 0 ) //don't send duplicate messages - { - req.message.isAction = isAction; - req.peerRequestType = PeerRequest::PEERREQUEST_MESSAGEROOM; - TheGameSpyPeerMessageQueue->addRequest(req); - s_prevMsg = message; - } - return false; - } - - // Get the selections (is this a private message?) - Int maxSel = GadgetListBoxGetListLength(playerListbox); - Int *selections; - GadgetListBoxGetSelected(playerListbox, (Int *)&selections); - - if (selections[0] == -1) - { // Public message - if( isAction || message.compare(s_prevMsg) != 0 ) //don't send duplicate messages - { - req.message.isAction = isAction; - req.peerRequestType = PeerRequest::PEERREQUEST_MESSAGEROOM; - TheGameSpyPeerMessageQueue->addRequest(req); - s_prevMsg = message; - } - return false; - } - else - { - // Private message - - // Construct a list - AsciiString names = AsciiString::TheEmptyString; - AsciiString tmp = AsciiString::TheEmptyString; - AsciiString aStr; // AsciiString buf for translating Unicode entries - names.format("%s", TheGameSpyInfo->getLocalName().str()); - for (int i=0; igetLocalName())) - { - tmp.format(",%s", aStr.str()); - names.concat(tmp); - } - } - else - { - break; - } - } - - if (!names.isEmpty()) - { - req.nick = names.str(); - req.message.isAction = isAction; - req.peerRequestType = PeerRequest::PEERREQUEST_MESSAGEPLAYER; - TheGameSpyPeerMessageQueue->addRequest(req); - } - s_prevMsg = message; - return true; - } - } - s_prevMsg = message; - return false; -} - -void GameSpyInfo::addChat( AsciiString nick, Int profileID, UnicodeString msg, Bool isPublic, Bool isAction, GameWindow *win ) -{ - PlayerInfoMap::iterator it = getPlayerInfoMap()->find(nick); - if (it != getPlayerInfoMap()->end()) - { - addChat( it->second, msg, isPublic, isAction, win ); - } - else - { - } -} - -void GameSpyInfo::addChat( PlayerInfo p, UnicodeString msg, Bool isPublic, Bool isAction, GameWindow *win ) -{ - Int style; - if(isSavedIgnored(p.m_profileID) || isIgnored(p.m_name)) - return; - - Bool isOwner = p.m_flags & PEER_FLAG_OP; - Bool isBuddy = getBuddyMap()->find(p.m_profileID) != getBuddyMap()->end(); - - Bool isMe = p.m_name.compare(TheGameSpyInfo->getLocalName()) == 0; - - if(!isMe) - { - if(m_disallowAsainText) - { - const WideChar *buff = msg.str(); - Int length = msg.getLength(); - for(Int i = 0; i < length; ++i) - { - if(buff[i] >= 256) - return; - } - } - else if(m_disallowNonAsianText) - { - const WideChar *buff = msg.str(); - Int length = msg.getLength(); - Bool hasUnicode = FALSE; - for(Int i = 0; i < length; ++i) - { - if(buff[i] >= 256) - { - hasUnicode = TRUE; - break; - } - } - if(!hasUnicode) - return; - } - - if (!isPublic) - { - AudioEventRTS privMsgAudio("GUIMessageReceived"); - - if( TheAudio ) - { - TheAudio->addAudioEvent( &privMsgAudio ); - } // end if - } - } - - - if (isBuddy) - { - style = GSCOLOR_CHAT_BUDDY; - } - else if (isPublic && isAction) - { - style = (isOwner)?GSCOLOR_CHAT_OWNER_EMOTE:GSCOLOR_CHAT_EMOTE; - } - else if (isPublic) - { - style = (isOwner)?GSCOLOR_CHAT_OWNER:GSCOLOR_CHAT_NORMAL; - } - else if (isAction) - { - style = (isOwner)?GSCOLOR_CHAT_PRIVATE_OWNER_EMOTE:GSCOLOR_CHAT_PRIVATE_EMOTE; - } - else - { - style = (isOwner)?GSCOLOR_CHAT_PRIVATE_OWNER:GSCOLOR_CHAT_PRIVATE; - } - - UnicodeString name; - name.translate(p.m_name); - - // filters language -// if( TheGlobalData->m_languageFilterPref ) -// { - TheLanguageFilter->filterLine(msg); -// } - - UnicodeString fullMsg; - if (isAction) - { - fullMsg.format( L"%ls %ls", name.str(), msg.str() ); - } - else - { - fullMsg.format( L"[%ls] %ls", name.str(), msg.str() ); - } - - Int index = addText(fullMsg, GameSpyColor[style], win); - if (index >= 0) - { - GadgetListBoxSetItemData(win, (void *)p.m_profileID, index); - } -} - -Int GameSpyInfo::addText( UnicodeString message, Color c, GameWindow *win ) -{ - if (TheGameSpyGame && TheGameSpyGame->isInGame() && TheGameSpyGame->isGameInProgress()) - { - static AudioEventRTS messageFromChatSound("GUIMessageReceived"); - TheAudio->addAudioEvent(&messageFromChatSound); - - TheInGameUI->message(message); - } - - if (!win) - { - // try to pick up a registered text window - if (m_textWindows.empty()) - return -1; - - win = *(m_textWindows.begin()); - } - Int index = GadgetListBoxAddEntryText(win, message, c, -1, -1); - GadgetListBoxSetItemData(win, (void *)-1, index); - - return index; -} - -void GameSpyInfo::registerTextWindow( GameWindow *win ) -{ - m_textWindows.insert(win); -} - -void GameSpyInfo::unregisterTextWindow( GameWindow *win ) -{ - m_textWindows.erase(win); -} - diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/GSConfig.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/GSConfig.cpp deleted file mode 100644 index 0bb8649f5f6..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/GSConfig.cpp +++ /dev/null @@ -1,479 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: GSConfig.cpp -// Author: Matthew D. Campbell, Sept 2002 -// Description: GameSpy online config -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameState.h" -#include "GameClient/MapUtil.h" -#include "GameNetwork/GameSpy/GSConfig.h" -#include "GameNetwork/RankPointValue.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -/////////////////////////////////////////////////////////////////////////////////////// - -GameSpyConfigInterface *TheGameSpyConfig = NULL; - -class GameSpyConfig : public GameSpyConfigInterface -{ -public: - GameSpyConfig( AsciiString config ); - ~GameSpyConfig() {} - - // Pings - std::list getPingServers(void) { return m_pingServers; } - Int getNumPingRepetitions(void) { return m_pingReps; } - Int getPingTimeoutInMs(void) { return m_pingTimeout; } - virtual Int getPingCutoffGood( void ) { return m_pingCutoffGood; } - virtual Int getPingCutoffBad( void ) { return m_pingCutoffBad; } - - // QM - std::list getQMMaps(void) { return m_qmMaps; } - Int getQMBotID(void) { return m_qmBotID; } - Int getQMChannel(void) { return m_qmChannel; } - void setQMChannel(Int channel) { m_qmChannel = channel; } - - // Player Info - Int getPointsForRank(Int rank); - virtual Bool isPlayerVIP(Int id); - - virtual Bool getManglerLocation(Int index, AsciiString& host, UnsignedShort& port); - - // Ladder / Any other external parsing - AsciiString getLeftoverConfig(void) { return m_leftoverConfig; } - - // NAT Timeouts - virtual Int getTimeBetweenRetries() { return m_natRetryInterval; } - virtual Int getMaxManglerRetries() { return m_natMaxManglerRetries; } - virtual time_t getRetryInterval() { return m_natManglerRetryInterval; } - virtual time_t getKeepaliveInterval() { return m_natKeepaliveInterval; } - virtual time_t getPortTimeout() { return m_natPortTimeout; } - virtual time_t getRoundTimeout() { return m_natRoundTimeout; } - - // Custom match - virtual Bool restrictGamesToLobby() { return m_restrictGamesToLobby; } - -protected: - std::list m_pingServers; - Int m_pingReps; - Int m_pingTimeout; - Int m_pingCutoffGood; - Int m_pingCutoffBad; - - Int m_natRetryInterval; - Int m_natMaxManglerRetries; - time_t m_natManglerRetryInterval; - time_t m_natKeepaliveInterval; - time_t m_natPortTimeout; - time_t m_natRoundTimeout; - - std::vector m_manglerHosts; - std::vector m_manglerPorts; - - std::list m_qmMaps; - Int m_qmBotID; - Int m_qmChannel; - - Bool m_restrictGamesToLobby; - - std::set m_vip; // VIP people - - Int m_rankPoints[MAX_RANKS]; - - AsciiString m_leftoverConfig; -}; - -/////////////////////////////////////////////////////////////////////////////////////// - -GameSpyConfigInterface* GameSpyConfigInterface::create(AsciiString config) -{ - return NEW GameSpyConfig(config); -} - -/////////////////////////////////////////////////////////////////////////////////////// - -class SectionChecker -{ -public: - typedef std::list SectionList; - void addVar(const Bool *var) { m_bools.push_back(var); } - Bool isInSection(); -protected: - SectionList m_bools; -}; -Bool SectionChecker::isInSection() { - Bool ret = FALSE; - for (SectionList::const_iterator it = m_bools.begin(); it != m_bools.end(); ++it) - { - ret = ret || **it; - } - return ret; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -GameSpyConfig::GameSpyConfig( AsciiString config ) : -m_natRetryInterval(1000), -m_natMaxManglerRetries(25), -m_natManglerRetryInterval(300), -m_natKeepaliveInterval(15000), -m_natPortTimeout(10000), -m_natRoundTimeout(10000), -m_pingReps(1), -m_pingTimeout(1000), -m_pingCutoffGood(300), -m_pingCutoffBad(600), -m_restrictGamesToLobby(FALSE), -m_qmBotID(0), -m_qmChannel(0) -{ - m_rankPoints[0] = 0; - m_rankPoints[1] = 5; - m_rankPoints[2] = 10; - m_rankPoints[3] = 20; - m_rankPoints[4] = 50; - m_rankPoints[5] = 100; - m_rankPoints[6] = 200; - m_rankPoints[7] = 500; - m_rankPoints[8] = 1000; - m_rankPoints[9] = 2000; - - AsciiString line; - Bool inPingServers = FALSE; - Bool inPingDuration = FALSE; - Bool inQMMaps = FALSE; - Bool inQMBot = FALSE; - Bool inManglers = FALSE; - Bool inVIP = FALSE; - Bool inNAT = FALSE; - Bool inCustom = FALSE; - - SectionChecker sections; - sections.addVar(&inPingServers); - sections.addVar(&inPingDuration); - sections.addVar(&inQMMaps); - sections.addVar(&inQMBot); - sections.addVar(&inManglers); - sections.addVar(&inVIP); - sections.addVar(&inNAT); - sections.addVar(&inCustom); - - while (config.nextToken(&line, "\n")) - { - if (line.getCharAt(line.getLength()-1) == '\r') - line.removeLastChar(); // there is a trailing '\r' - - line.trim(); - - if (line.isEmpty()) - continue; - - if (!sections.isInSection() && line.compare("") == 0) - { - inPingServers = TRUE; - } - else if (inPingServers && line.compare("") == 0) - { - inPingServers = FALSE; - } - else if (!sections.isInSection() && line.compare("") == 0) - { - inPingDuration = TRUE; - } - else if (inPingDuration && line.compare("") == 0) - { - inPingDuration = FALSE; - } - else if (!sections.isInSection() && line.compare("") == 0) - { - inQMMaps = TRUE; - } - else if (inQMMaps && line.compare("") == 0) - { - inQMMaps = FALSE; - } - else if (!sections.isInSection() && line.compare("") == 0) - { - inManglers = TRUE; - } - else if (inManglers && line.compare("") == 0) - { - inManglers = FALSE; - } - else if (!sections.isInSection() && line.compare("") == 0) - { - inQMBot = TRUE; - } - else if (inQMBot && line.compare("") == 0) - { - inQMBot = FALSE; - } - else if (!sections.isInSection() && line.compare("") == 0) - { - inVIP = TRUE; - } - else if (inVIP && line.compare("") == 0) - { - inVIP = FALSE; - } - else if (!sections.isInSection() && line.compare("") == 0) - { - inNAT = TRUE; - } - else if (inNAT && line.compare("") == 0) - { - inNAT = FALSE; - } - else if (!sections.isInSection() && line.compare("") == 0) - { - inCustom = TRUE; - } - else if (inCustom && line.compare("") == 0) - { - inCustom = FALSE; - } - else if (inVIP) - { - line.toLower(); - if (line.getLength()) - { - Int val = atoi(line.str()); - if (val > 0) - m_vip.insert(val); - } - } - else if (inPingServers) - { - line.toLower(); - m_pingServers.push_back(line); - } - else if (inPingDuration) - { - line.toLower(); - AsciiString key, val; - if (line.nextToken(&key, " =")) - { - if (key == "reps") - { - if (line.nextToken(&val, " =")) - { - m_pingReps = atoi(val.str()); - } - } - else if (key == "timeout") - { - if (line.nextToken(&val, " =")) - { - m_pingTimeout = atoi(val.str()); - } - } - else if (key == "low") - { - if (line.nextToken(&val, " =")) - { - m_pingCutoffGood = atoi(val.str()); - } - } - else if (key == "med") - { - if (line.nextToken(&val, " =")) - { - m_pingCutoffBad = atoi(val.str()); - } - } - } - } - else if (inManglers) - { - line.trim(); - line.toLower(); - AsciiString hostStr; - AsciiString portStr; - line.nextToken(&hostStr, ":"); - line.nextToken(&portStr, ":\n\r"); - if (hostStr.isNotEmpty() && portStr.isNotEmpty()) - { - m_manglerHosts.push_back(hostStr); - m_manglerPorts.push_back(atoi(portStr.str())); - } - } - else if (inQMMaps) - { - line.toLower(); - AsciiString mapName; - mapName.format("%s\\%s\\%s.map", TheMapCache->getMapDir().str(), line.str(), line.str()); - mapName = TheGameState->portableMapPathToRealMapPath(TheGameState->realMapPathToPortableMapPath(mapName)); - mapName.toLower(); - - const MapMetaData *md = TheMapCache->findMap(mapName); - if (md) - { - m_qmMaps.push_back(mapName); - } - } - else if (inQMBot) - { - line.toLower(); - AsciiString key, val; - if (line.nextToken(&key, " =")) - { - if (key == "id") - { - if (line.nextToken(&val, " =")) - { - m_qmBotID = atoi(val.str()); - } - } - } - } - else if (inNAT) - { - line.toLower(); - AsciiString key, val; - if (line.nextToken(&key, " =")) - { - if (key == "retryinterval") - { - if (line.nextToken(&val, " =")) - { - m_natRetryInterval = atoi(val.str()); - } - } - else if (key == "manglerretries") - { - if (line.nextToken(&val, " =")) - { - m_natMaxManglerRetries = atoi(val.str()); - } - } - else if (key == "manglerinterval") - { - if (line.nextToken(&val, " =")) - { - m_natManglerRetryInterval = atoi(val.str()); - } - } - else if (key == "keepaliveinterval") - { - if (line.nextToken(&val, " =")) - { - m_natKeepaliveInterval = atoi(val.str()); - } - } - else if (key == "porttimeout") - { - if (line.nextToken(&val, " =")) - { - m_natPortTimeout = atoi(val.str()); - } - } - else if (key == "roundtimeout") - { - if (line.nextToken(&val, " =")) - { - m_natRoundTimeout = atoi(val.str()); - } - } - else - { - DEBUG_LOG(("Unknown key '%s' = '%s' in NAT block of GameSpy Config\n", key.str(), val.str())); - } - } - else - { - DEBUG_LOG(("Key '%s' missing val in NAT block of GameSpy Config\n", key.str())); - } - } - else if (inCustom) - { - line.toLower(); - AsciiString key, val; - if (line.nextToken(&key, " =") && line.nextToken(&val, " =")) - { - if (key == "restricted") - { - m_restrictGamesToLobby = atoi(val.str()); - } - else - { - DEBUG_LOG(("Unknown key '%s' = '%s' in Custom block of GameSpy Config\n", key.str(), val.str())); - } - } - else - { - DEBUG_LOG(("Key '%s' missing val in Custom block of GameSpy Config\n", key.str())); - } - } - else - { - m_leftoverConfig.concat(line); - m_leftoverConfig.concat('\n'); - } - } - -} - -/////////////////////////////////////////////////////////////////////////////////////// - -Int GameSpyConfig::getPointsForRank(Int rank) -{ - if (rank >= MAX_RANKS) rank = MAX_RANKS-1; - if (rank < 0) rank = 0; - return m_rankPoints[rank]; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -Bool GameSpyConfig::getManglerLocation(Int index, AsciiString& host, UnsignedShort& port) -{ - if (index < 0 || index >= m_manglerHosts.size()) - { - return FALSE; - } - - host = m_manglerHosts[index]; - port = m_manglerPorts[index]; - return TRUE; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -Bool GameSpyConfig::isPlayerVIP(Int id) -{ - std::set::const_iterator it = std::find(m_vip.begin(), m_vip.end(), id); - return it != m_vip.end(); -} - -/////////////////////////////////////////////////////////////////////////////////////// diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp deleted file mode 100644 index 518fc5289fe..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp +++ /dev/null @@ -1,535 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: LadderDefs.cpp ////////////////////////////////////////////////////// -// Generals ladder code -// Author: Matthew D. Campbell, August 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "GameNetwork/GameSpy/ThreadUtils.h" -#include "GameNetwork/GameSpy/LadderDefs.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/GSConfig.h" -#include "Common/GameState.h" -#include "Common/File.h" -#include "Common/FileSystem.h" -#include "Common/PlayerTemplate.h" -#include "GameClient/GameText.h" -#include "GameClient/MapUtil.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -LadderList *TheLadderList = NULL; - -LadderInfo::LadderInfo() -{ - playersPerTeam = 1; - minWins = 0; - maxWins = 0; - randomMaps = TRUE; - randomFactions = TRUE; - validQM = TRUE; - validCustom = FALSE; - port = 0; - submitReplay = FALSE; - index = -1; -} - -static LadderInfo *parseLadder(AsciiString raw) -{ - DEBUG_LOG(("Looking at ladder:\n%s\n", raw.str())); - LadderInfo *lad = NULL; - AsciiString line; - while (raw.nextToken(&line, "\n")) - { - if (line.getCharAt(line.getLength()-1) == '\r') - line.removeLastChar(); // there is a trailing '\r' - - line.trim(); - - if (line.isEmpty()) - continue; - - // woohoo! got a line! - line.trim(); - if ( !lad && line.startsWith("' - line = line.str() + 7; // the "name = MultiByteToWideCharSingleLine(tokenName.str()).c_str(); - while (lad->name.getLength() > 20) - lad->name.removeLastChar(); // Per Harvard's request, ladder names are limited to 20 chars - lad->address = tokenAddr; - lad->port = atoi(tokenPort.str()); - lad->homepageURL = tokenHomepage; - } - else if ( lad && line.startsWith("Name ") ) - { - lad->name = MultiByteToWideCharSingleLine(line.str() + 5).c_str(); - } - else if ( lad && line.startsWith("Desc ") ) - { - lad->description = MultiByteToWideCharSingleLine(line.str() + 5).c_str(); - } - else if ( lad && line.startsWith("Loc ") ) - { - lad->location = MultiByteToWideCharSingleLine(line.str() + 4).c_str(); - } - else if ( lad && line.startsWith("TeamSize ") ) - { - lad->playersPerTeam = atoi(line.str() + 9); - } - else if ( lad && line.startsWith("RandomMaps ") ) - { - lad->randomMaps = atoi(line.str() + 11); - } - else if ( lad && line.startsWith("RandomFactions ") ) - { - lad->randomFactions = atoi(line.str() + 15); - } - else if ( lad && line.startsWith("Faction ") ) - { - AsciiString faction = line.str() + 8; - AsciiStringList outStringList; - ThePlayerTemplateStore->getAllSideStrings(&outStringList); - - AsciiStringList::iterator aIt = std::find(outStringList.begin(), outStringList.end(), faction); - if (aIt != outStringList.end()) - { - // valid faction - now check for dupes - aIt = std::find(lad->validFactions.begin(), lad->validFactions.end(), faction); - if (aIt == lad->validFactions.end()) - { - lad->validFactions.push_back(faction); - } - } - } - /* - else if ( lad && line.startsWith("QM ") ) - { - lad->validQM = atoi(line.str() + 3); - } - else if ( lad && line.startsWith("Custom ") ) - { - lad->validCustom = atoi(line.str() + 7); - } - */ - else if ( lad && line.startsWith("MinWins ") ) - { - lad->minWins = atoi(line.str() + 8); - } - else if ( lad && line.startsWith("MaxWins ") ) - { - lad->maxWins = atoi(line.str() + 8); - } - else if ( lad && line.startsWith("CryptedPass ") ) - { - lad->cryptedPassword = line.str() + 12; - } - else if ( lad && line.compare("") == 0 ) - { - DEBUG_LOG(("Saw a ladder: name=%ls, addr=%s:%d, players=%dv%d, pass=%s, replay=%d, homepage=%s\n", - lad->name.str(), lad->address.str(), lad->port, lad->playersPerTeam, lad->playersPerTeam, lad->cryptedPassword.str(), - lad->submitReplay, lad->homepageURL.str())); - // end of a ladder - if (lad->playersPerTeam >= 1 && lad->playersPerTeam <= MAX_SLOTS/2) - { - if (lad->validFactions.size() == 0) - { - DEBUG_LOG(("No factions specified. Using all.\n")); - lad->validFactions.clear(); - Int numTemplates = ThePlayerTemplateStore->getPlayerTemplateCount(); - for ( Int i = 0; i < numTemplates; ++i ) - { - const PlayerTemplate *pt = ThePlayerTemplateStore->getNthPlayerTemplate(i); - if (!pt) - continue; - - if (pt->isPlayableSide() && pt->getSide().compare("Boss") != 0 ) - lad->validFactions.push_back(pt->getSide()); - } - } - else - { - AsciiStringList validFactions = lad->validFactions; - for (AsciiStringListIterator it = validFactions.begin(); it != validFactions.end(); ++it) - { - AsciiString faction = *it; - AsciiString marker; - marker.format("INI:Faction%s", faction.str()); - DEBUG_LOG(("Faction %s has marker %s corresponding to str %ls\n", faction.str(), marker.str(), TheGameText->fetch(marker).str())); - } - } - - if (lad->validMaps.size() == 0) - { - DEBUG_LOG(("No maps specified. Using all.\n")); - std::list qmMaps = TheGameSpyConfig->getQMMaps(); - for (std::list::const_iterator it = qmMaps.begin(); it != qmMaps.end(); ++it) - { - AsciiString mapName = *it; - - // check sizes on the maps before allowing them - const MapMetaData *md = TheMapCache->findMap(mapName); - if (md && md->m_numPlayers >= lad->playersPerTeam*2) - { - lad->validMaps.push_back(mapName); - } - } - } - return lad; - } - else - { - // no maps? don't play on it! - delete lad; - lad = NULL; - return NULL; - } - } - else if ( lad && line.startsWith("Map ") ) - { - // valid map - AsciiString mapName = line.str() + 4; - mapName.trim(); - if (mapName.isNotEmpty()) - { - mapName.format("%s\\%s\\%s.map", TheMapCache->getMapDir().str(), mapName.str(), mapName.str()); - mapName = TheGameState->portableMapPathToRealMapPath(TheGameState->realMapPathToPortableMapPath(mapName)); - mapName.toLower(); - std::list qmMaps = TheGameSpyConfig->getQMMaps(); - if (std::find(qmMaps.begin(), qmMaps.end(), mapName) != qmMaps.end()) - { - // check sizes on the maps before allowing them - const MapMetaData *md = TheMapCache->findMap(mapName); - if (md && md->m_numPlayers >= lad->playersPerTeam*2) - lad->validMaps.push_back(mapName); - } - } - } - else - { - // bad ladder - kill it - delete lad; - lad = NULL; - } - } - - if (lad) - { - delete lad; - lad = NULL; - } - return NULL; -} - -LadderList::LadderList() -{ - //Int profile = TheGameSpyInfo->getLocalProfileID(); - - AsciiString rawMotd = TheGameSpyConfig->getLeftoverConfig(); - AsciiString line; - Bool inLadders = FALSE; - Bool inSpecialLadders = FALSE; - Bool inLadder = FALSE; - LadderInfo *lad = NULL; - Int index = 1; - AsciiString rawLadder; - - while (rawMotd.nextToken(&line, "\n")) - { - if (line.getCharAt(line.getLength()-1) == '\r') - line.removeLastChar(); // there is a trailing '\r' - - line.trim(); - - if (line.isEmpty()) - continue; - - if (!inLadders && line.compare("") == 0) - { - inLadders = TRUE; - rawLadder.clear(); - } - else if (inLadders && line.compare("") == 0) - { - inLadders = FALSE; - } - else if (!inSpecialLadders && line.compare("") == 0) - { - inSpecialLadders = TRUE; - rawLadder.clear(); - } - else if (inSpecialLadders && line.compare("") == 0) - { - inSpecialLadders = FALSE; - } - else if (inLadders || inSpecialLadders) - { - if (line.startsWith("") == 0 && inLadder) - { - inLadder = FALSE; - rawLadder.concat(line); - rawLadder.concat('\n'); - if ((lad = parseLadder(rawLadder)) != NULL) - { - lad->index = index++; - if (inLadders) - { - DEBUG_LOG(("Adding to standard ladders\n")); - m_standardLadders.push_back(lad); - } - else - { - DEBUG_LOG(("Adding to special ladders\n")); - m_specialLadders.push_back(lad); - } - } - rawLadder.clear(); - } - else if (inLadder) - { - rawLadder.concat(line); - rawLadder.concat('\n'); - } - } - } - - // look for local ladders - loadLocalLadders(); - - DEBUG_LOG(("After looking for ladders, we have %d local, %d special && %d normal\n", m_localLadders.size(), m_specialLadders.size(), m_standardLadders.size())); -} - -LadderList::~LadderList() -{ - LadderInfoList::iterator it; - for (it = m_specialLadders.begin(); it != m_specialLadders.end(); it = m_specialLadders.begin()) - { - delete *it; - m_specialLadders.pop_front(); - } - for (it = m_standardLadders.begin(); it != m_standardLadders.end(); it = m_standardLadders.begin()) - { - delete *it; - m_standardLadders.pop_front(); - } - for (it = m_localLadders.begin(); it != m_localLadders.end(); it = m_localLadders.begin()) - { - delete *it; - m_localLadders.pop_front(); - } -} - -const LadderInfo* LadderList::findLadder( const AsciiString& addr, UnsignedShort port ) -{ - LadderInfoList::const_iterator cit; - - for (cit = m_specialLadders.begin(); cit != m_specialLadders.end(); ++cit) - { - const LadderInfo *li = *cit; - if (li->address == addr && li->port == port) - { - return li; - } - } - - for (cit = m_standardLadders.begin(); cit != m_standardLadders.end(); ++cit) - { - const LadderInfo *li = *cit; - if (li->address == addr && li->port == port) - { - return li; - } - } - - for (cit = m_localLadders.begin(); cit != m_localLadders.end(); ++cit) - { - const LadderInfo *li = *cit; - if (li->address == addr && li->port == port) - { - return li; - } - } - - return NULL; -} - -const LadderInfo* LadderList::findLadderByIndex( Int index ) -{ - if (index == 0) - return NULL; - - LadderInfoList::const_iterator cit; - - for (cit = m_specialLadders.begin(); cit != m_specialLadders.end(); ++cit) - { - const LadderInfo *li = *cit; - if (li->index == index) - { - return li; - } - } - - for (cit = m_standardLadders.begin(); cit != m_standardLadders.end(); ++cit) - { - const LadderInfo *li = *cit; - if (li->index == index) - { - return li; - } - } - - for (cit = m_localLadders.begin(); cit != m_localLadders.end(); ++cit) - { - const LadderInfo *li = *cit; - if (li->index == index) - { - return li; - } - } - - return NULL; -} - -const LadderInfoList* LadderList::getSpecialLadders( void ) -{ - return &m_specialLadders; -} - -const LadderInfoList* LadderList::getStandardLadders( void ) -{ - return &m_standardLadders; -} - -const LadderInfoList* LadderList::getLocalLadders( void ) -{ - return &m_localLadders; -} - -void LadderList::loadLocalLadders( void ) -{ - AsciiString dirname; - dirname.format("%sGeneralsOnline\\Ladders\\", TheGlobalData->getPath_UserData().str()); - FilenameList filenameList; - TheFileSystem->getFileListInDirectory(dirname, AsciiString("*.ini"), filenameList, TRUE); - - Int index = -1; - - FilenameList::iterator it = filenameList.begin(); - while (it != filenameList.end()) - { - AsciiString filename = *it; - DEBUG_LOG(("Looking at possible ladder info file '%s'\n", filename.str())); - filename.toLower(); - checkLadder( filename, index-- ); - ++it; - } -} - -void LadderList::checkLadder( AsciiString fname, Int index ) -{ - File *fp = TheFileSystem->openFile(fname.str(), File::READ | File::TEXT); - char buf[1024]; - AsciiString rawData; - if (fp) - { - Int len; - while (!fp->eof()) - { - len = fp->read(buf, 1023); - buf[len] = 0; - buf[1023] = 0; - rawData.concat(buf); - } - fp->close(); - fp = NULL; - } - - DEBUG_LOG(("Read %d bytes from '%s'\n", rawData.getLength(), fname.str())); - if (rawData.isEmpty()) - return; - - LadderInfo *li = parseLadder(rawData); - if (!li) - { - return; - } - - // sanity check - if (li->address.isEmpty()) - { - DEBUG_LOG(("Bailing because of li->address.isEmpty()\n")); - delete li; - return; - } - - if (!li->port) - { - DEBUG_LOG(("Bailing because of !li->port\n")); - delete li; - return; - } - - if (li->validMaps.size() == 0) - { - DEBUG_LOG(("Bailing because of li->validMaps.size() == 0\n")); - delete li; - return; - } - - li->index = index; - - // ladders are QM-only at this point, which kinda invalidates the whole concept of local ladders. Oh well. - li->validQM = FALSE; // no local ladders in QM - li->validCustom = FALSE; - - //for (Int i=0; i<4; ++i) - // fname.removeLastChar(); // remove .lad - //li->name = UnicodeString(MultiByteToWideCharSingleLine(fname.reverseFind('\\')+1).c_str()); - - DEBUG_LOG(("Adding local ladder %ls\n", li->name.str())); - m_localLadders.push_back(li); -} diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/LobbyUtils.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/LobbyUtils.cpp deleted file mode 100644 index bcba368a0b4..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/LobbyUtils.cpp +++ /dev/null @@ -1,938 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: LobbyUtils.cpp -// Author: Matthew D. Campbell, Sept 2002 -// Description: GameSpy lobby utils -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "Common/MultiplayerSettings.h" -#include "Common/PlayerTemplate.h" -#include "Common/Version.h" -#include "GameClient/AnimateWindowManager.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/Image.h" -#include "GameClient/Shell.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetComboBox.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/GameText.h" -#include "GameClient/MapUtil.h" -#include "GameClient/MessageBox.h" -#include "GameClient/Mouse.h" -#include "GameNetwork/GameSpyOverlay.h" - -#include "GameClient/LanguageFilter.h" -#include "GameNetwork/GameSpy/BuddyDefs.h" -#include "GameNetwork/GameSpy/LadderDefs.h" -#include "GameNetwork/GameSpy/LobbyUtils.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PersistentStorageDefs.h" -#include "GameNetwork/GameSpy/GSConfig.h" - -#include "Common/STLTypedefs.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -// Note: if you add more columns, you must modify the .wnd files and change the listbox properties (yuck!) -static enum { - COLUMN_NAME = 0, - COLUMN_MAP, - COLUMN_LADDER, - COLUMN_NUMPLAYERS, - COLUMN_PASSWORD, - COLUMN_OBSERVER, - COLUMN_USE_STATS, - COLUMN_PING, -}; - -static NameKeyType buttonSortAlphaID = NAMEKEY_INVALID; -static NameKeyType buttonSortPingID = NAMEKEY_INVALID; -static NameKeyType buttonSortBuddiesID = NAMEKEY_INVALID; -static NameKeyType windowSortAlphaID = NAMEKEY_INVALID; -static NameKeyType windowSortPingID = NAMEKEY_INVALID; -static NameKeyType windowSortBuddiesID = NAMEKEY_INVALID; - -static GameWindow *buttonSortAlpha = NULL; -static GameWindow *buttonSortPing = NULL; -static GameWindow *buttonSortBuddies = NULL; -static GameWindow *windowSortAlpha = NULL; -static GameWindow *windowSortPing = NULL; -static GameWindow *windowSortBuddies = NULL; - -static GameSortType theGameSortType = GAMESORT_ALPHA_ASCENDING; -static Bool sortBuddies = TRUE; -static void showSortIcons(void) -{ - if (windowSortAlpha && windowSortPing) - { - switch(theGameSortType) - { - case GAMESORT_ALPHA_ASCENDING: - windowSortAlpha->winHide(FALSE); - windowSortAlpha->winEnable(TRUE); - windowSortPing->winHide(TRUE); - break; - case GAMESORT_ALPHA_DESCENDING: - windowSortAlpha->winHide(FALSE); - windowSortAlpha->winEnable(FALSE); - windowSortPing->winHide(TRUE); - break; - case GAMESORT_PING_ASCENDING: - windowSortPing->winHide(FALSE); - windowSortPing->winEnable(TRUE); - windowSortAlpha->winHide(TRUE); - break; - case GAMESORT_PING_DESCENDING: - windowSortPing->winHide(FALSE); - windowSortPing->winEnable(FALSE); - windowSortAlpha->winHide(TRUE); - break; - } - } - - if (sortBuddies) - { - if (windowSortBuddies) - { - windowSortBuddies->winHide(FALSE); - } - } - else - { - if (windowSortBuddies) - { - windowSortBuddies->winHide(TRUE); - } - } -} -void setSortMode( GameSortType sortType ) { theGameSortType = sortType; showSortIcons(); RefreshGameListBoxes(); } -void sortByBuddies( Bool doSort ) { sortBuddies = doSort; showSortIcons(); RefreshGameListBoxes(); } - -Bool HandleSortButton( NameKeyType sortButton ) -{ - if (sortButton == buttonSortBuddiesID) - { - sortByBuddies( !sortBuddies ); - return TRUE; - } - else if (sortButton == buttonSortAlphaID) - { - if (theGameSortType == GAMESORT_ALPHA_ASCENDING) - { - setSortMode(GAMESORT_ALPHA_DESCENDING); - } - else - { - setSortMode(GAMESORT_ALPHA_ASCENDING); - } - return TRUE; - } - else if (sortButton == buttonSortPingID) - { - if (theGameSortType == GAMESORT_PING_ASCENDING) - { - setSortMode(GAMESORT_PING_DESCENDING); - } - else - { - setSortMode(GAMESORT_PING_ASCENDING); - } - return TRUE; - } - return FALSE; -} - -// window ids ------------------------------------------------------------------------------ -static NameKeyType parentID = NAMEKEY_INVALID; -//static NameKeyType parentGameListSmallID = NAMEKEY_INVALID; -static NameKeyType parentGameListLargeID = NAMEKEY_INVALID; -static NameKeyType listboxLobbyGamesSmallID = NAMEKEY_INVALID; -static NameKeyType listboxLobbyGamesLargeID = NAMEKEY_INVALID; -//static NameKeyType listboxLobbyGameInfoID = NAMEKEY_INVALID; - -// Window Pointers ------------------------------------------------------------------------ -static GameWindow *parent = NULL; -//static GameWindow *parentGameListSmall = NULL; -static GameWindow *parentGameListLarge = NULL; - //GameWindow *listboxLobbyGamesSmall = NULL; - GameWindow *listboxLobbyGamesLarge = NULL; - //GameWindow *listboxLobbyGameInfo = NULL; - -static const Image *pingImages[3] = { NULL, NULL, NULL }; - -static void gameTooltip(GameWindow *window, - WinInstanceData *instData, - UnsignedInt mouse) -{ - Int x, y, row, col; - x = LOLONGTOSHORT(mouse); - y = HILONGTOSHORT(mouse); - - GadgetListBoxGetEntryBasedOnXY(window, x, y, row, col); - - if (row == -1 || col == -1) - { - TheMouse->setCursorTooltip( UnicodeString::TheEmptyString);//TheGameText->fetch("TOOLTIP:GamesBeingFormed") ); - return; - } - - Int gameID = (Int)GadgetListBoxGetItemData(window, row, 0); - GameSpyStagingRoom *room = TheGameSpyInfo->findStagingRoomByID(gameID); - if (!room) - { - TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:UnknownGame") ); - return; - } - - if (col == COLUMN_PING) - { -#if 0 //def DEBUG_LOGGING - UnicodeString s; - s.format(L"Ping is %d ms (cutoffs are %d ms and %d ms\n%hs local pings\n%hs remote pings", - room->getPingAsInt(), TheGameSpyConfig->getPingCutoffGood(), TheGameSpyConfig->getPingCutoffBad(), - TheGameSpyInfo->getPingString().str(), room->getPingString().str() - ); - TheMouse->setCursorTooltip( s, 10, NULL, 2.0f ); // the text and width are the only params used. the others are the default values. -#else - TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:PingInfo"), 10, NULL, 2.0f ); // the text and width are the only params used. the others are the default values. -#endif - return; - } - if (col == COLUMN_NUMPLAYERS) - { - TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:NumberOfPlayers"), 10, NULL, 2.0f ); // the text and width are the only params used. the others are the default values. - return; - } - if (col == COLUMN_PASSWORD) - { - if (room->getHasPassword()) - { - UnicodeString checkTooltip =TheGameText->fetch("TOOTIP:Password"); - if(!checkTooltip.compare(L"Password required to joing game")) - checkTooltip.set(L"Password required to join game"); - TheMouse->setCursorTooltip( checkTooltip, 10, NULL, 2.0f ); // the text and width are the only params used. the others are the default values. - } - else - TheMouse->setCursorTooltip( UnicodeString::TheEmptyString ); - return; - } - if (col == COLUMN_USE_STATS) - { - if ( room->getUseStats() ) - { - TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:UseStatsOn") ); - } - else - { - TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:UseStatsOff") ); - } - return; - } - - UnicodeString tooltip; - - UnicodeString mapName; - const MapMetaData *md = TheMapCache->findMap(room->getMap()); - if (md) - { - mapName = md->m_displayName; - } - else - { - const char *start = room->getMap().reverseFind('\\'); - if (start) - { - ++start; - } - else - { - start = room->getMap().str(); - } - mapName.translate( start ); - } - UnicodeString tmp; - tooltip.format(TheGameText->fetch("TOOLTIP:GameInfoGameName"), room->getGameName().str()); - if (room->getLadderPort() != 0) - { - const LadderInfo *linfo = TheLadderList->findLadder(room->getLadderIP(), room->getLadderPort()); - if (linfo) - { - tmp.format(TheGameText->fetch("TOOLTIP:GameInfoLadderName"), linfo->name.str()); - tooltip.concat(tmp); - } - } - if (room->getExeCRC() != TheGlobalData->m_exeCRC || room->getIniCRC() != TheGlobalData->m_iniCRC) - { - tmp.format(TheGameText->fetch("TOOLTIP:InvalidGameVersion"), mapName.str()); - tooltip.concat(tmp); - } - tmp.format(TheGameText->fetch("TOOLTIP:GameInfoMap"), mapName.str()); - tooltip.concat(tmp); - - AsciiString aPlayer; - UnicodeString player; - Int numPlayers = 0; - for (Int i=0; igetGameSpySlot(i); - if (i == 0 && (!slot || !slot->isHuman())) - { - DEBUG_CRASH(("About to tooltip a non-hosted game!\n")); - } - if (slot && slot->isHuman()) - { - tmp.format(TheGameText->fetch("TOOLTIP:GameInfoPlayer"), slot->getName().str(), slot->getWins(), slot->getLosses()); - tooltip.concat(tmp); - ++numPlayers; - } - else if (slot && slot->isAI()) - { - ++numPlayers; - switch(slot->getState()) - { - case SLOT_EASY_AI: - tooltip.concat(L'\n'); - tooltip.concat(TheGameText->fetch("GUI:EasyAI")); - break; - case SLOT_MED_AI: - tooltip.concat(L'\n'); - tooltip.concat(TheGameText->fetch("GUI:MediumAI")); - break; - case SLOT_BRUTAL_AI: - tooltip.concat(L'\n'); - tooltip.concat(TheGameText->fetch("GUI:HardAI")); - break; - } - } - } - DEBUG_ASSERTCRASH(numPlayers, ("Tooltipping a 0-player game!\n")); - - TheMouse->setCursorTooltip( tooltip, 10, NULL, 2.0f ); // the text and width are the only params used. the others are the default values. -} - -static Bool isSmall = TRUE; - -GameWindow *GetGameListBox( void ) -{ - return listboxLobbyGamesLarge; -} - -GameWindow *GetGameInfoListBox( void ) -{ - return NULL; -} - -NameKeyType GetGameListBoxID( void ) -{ - return listboxLobbyGamesLargeID; -} - -NameKeyType GetGameInfoListBoxID( void ) -{ - return NAMEKEY_INVALID; -} - -void GrabWindowInfo( void ) -{ - isSmall = TRUE; - parentID = NAMEKEY( "WOLCustomLobby.wnd:WOLLobbyMenuParent" ); - parent = TheWindowManager->winGetWindowFromId(NULL, parentID); - - pingImages[0] = TheMappedImageCollection->findImageByName("Ping03"); - pingImages[1] = TheMappedImageCollection->findImageByName("Ping02"); - pingImages[2] = TheMappedImageCollection->findImageByName("Ping01"); - DEBUG_ASSERTCRASH(pingImages[0], ("Can't find ping image!")); - DEBUG_ASSERTCRASH(pingImages[1], ("Can't find ping image!")); - DEBUG_ASSERTCRASH(pingImages[2], ("Can't find ping image!")); - -// parentGameListSmallID = NAMEKEY( "WOLCustomLobby.wnd:ParentGameListSmall" ); -// parentGameListSmall = TheWindowManager->winGetWindowFromId(NULL, parentGameListSmallID); - - parentGameListLargeID = NAMEKEY( "WOLCustomLobby.wnd:ParentGameListLarge" ); - parentGameListLarge = TheWindowManager->winGetWindowFromId(NULL, parentGameListLargeID); - - listboxLobbyGamesSmallID = NAMEKEY( "WOLCustomLobby.wnd:ListboxGames" ); -// listboxLobbyGamesSmall = TheWindowManager->winGetWindowFromId(NULL, listboxLobbyGamesSmallID); -// listboxLobbyGamesSmall->winSetTooltipFunc(gameTooltip); - - listboxLobbyGamesLargeID = NAMEKEY( "WOLCustomLobby.wnd:ListboxGamesLarge" ); - listboxLobbyGamesLarge = TheWindowManager->winGetWindowFromId(NULL, listboxLobbyGamesLargeID); - listboxLobbyGamesLarge->winSetTooltipFunc(gameTooltip); -// -// listboxLobbyGameInfoID = NAMEKEY( "WOLCustomLobby.wnd:ListboxGameInfo" ); -// listboxLobbyGameInfo = TheWindowManager->winGetWindowFromId(NULL, listboxLobbyGameInfoID); - - buttonSortAlphaID = NAMEKEY("WOLCustomLobby.wnd:ButtonSortAlpha"); - buttonSortPingID = NAMEKEY("WOLCustomLobby.wnd:ButtonSortPing"); - buttonSortBuddiesID = NAMEKEY("WOLCustomLobby.wnd:ButtonSortBuddies"); - windowSortAlphaID = NAMEKEY("WOLCustomLobby.wnd:WindowSortAlpha"); - windowSortPingID = NAMEKEY("WOLCustomLobby.wnd:WindowSortPing"); - windowSortBuddiesID = NAMEKEY("WOLCustomLobby.wnd:WindowSortBuddies"); - - buttonSortAlpha = TheWindowManager->winGetWindowFromId(parent, buttonSortAlphaID); - buttonSortPing = TheWindowManager->winGetWindowFromId(parent, buttonSortPingID); - buttonSortBuddies = TheWindowManager->winGetWindowFromId(parent, buttonSortBuddiesID); - windowSortAlpha = TheWindowManager->winGetWindowFromId(parent, windowSortAlphaID); - windowSortPing = TheWindowManager->winGetWindowFromId(parent, windowSortPingID); - windowSortBuddies = TheWindowManager->winGetWindowFromId(parent, windowSortBuddiesID); - - showSortIcons(); -} - -void ReleaseWindowInfo( void ) -{ - isSmall = TRUE; - parent = NULL; -// parentGameListSmall = NULL; - parentGameListLarge = NULL; -// listboxLobbyGamesSmall = NULL; - listboxLobbyGamesLarge = NULL; -// listboxLobbyGameInfo = NULL; - - buttonSortAlpha = NULL; - buttonSortPing = NULL; - buttonSortBuddies = NULL; - windowSortAlpha = NULL; - windowSortPing = NULL; - windowSortBuddies = NULL; -} - -typedef std::set BuddyGameSet; -static BuddyGameSet *theBuddyGames = NULL; -static void populateBuddyGames(void) -{ - BuddyInfoMap *m = TheGameSpyInfo->getBuddyMap(); - theBuddyGames = NEW BuddyGameSet; - if (!m) - { - return; - } - for (BuddyInfoMap::const_iterator bit = m->begin(); bit != m->end(); ++bit) - { - BuddyInfo info = bit->second; - if (info.m_status == GP_STAGING) - { - StagingRoomMap *srm = TheGameSpyInfo->getStagingRoomList(); - for (StagingRoomMap::iterator srmIt = srm->begin(); srmIt != srm->end(); ++srmIt) - { - GameSpyStagingRoom *game = srmIt->second; - game->cleanUpSlotPointers(); - const GameSpyGameSlot *slot = game->getGameSpySlot(0); - if (slot && slot->getName() == info.m_locationString) - { - theBuddyGames->insert(game); - break; - } - } - } - } -} - -static void clearBuddyGames(void) -{ - if (theBuddyGames) - delete theBuddyGames; - theBuddyGames = NULL; -} - -struct GameSortStruct -{ - bool operator()(GameSpyStagingRoom *g1, GameSpyStagingRoom *g2) - { - // sort CRC mismatches to the bottom - Bool g1Good = (g1->getExeCRC() != TheGlobalData->m_exeCRC || g1->getIniCRC() != TheGlobalData->m_iniCRC); - Bool g2Good = (g1->getExeCRC() != TheGlobalData->m_exeCRC || g1->getIniCRC() != TheGlobalData->m_iniCRC); - if ( g1Good ^ g2Good ) - { - return g1Good; - } - - // sort games with private ladders to the bottom - Bool g1UnknownLadder = (g1->getLadderPort() && TheLadderList->findLadder(g1->getLadderIP(), g1->getLadderPort()) == NULL); - Bool g2UnknownLadder = (g2->getLadderPort() && TheLadderList->findLadder(g2->getLadderIP(), g2->getLadderPort()) == NULL); - if ( g1UnknownLadder ^ g2UnknownLadder ) - { - return g2UnknownLadder; - } - - // sort full games to the bottom - Bool g1Full = (g1->getNumNonObserverPlayers() == g1->getMaxPlayers() || g1->getNumPlayers() == MAX_SLOTS); - Bool g2Full = (g2->getNumNonObserverPlayers() == g2->getMaxPlayers() || g2->getNumPlayers() == MAX_SLOTS); - if ( g1Full ^ g2Full ) - { - return g2Full; - } - - if (sortBuddies) - { - Bool g1HasBuddies = (theBuddyGames->find(g1) != theBuddyGames->end()); - Bool g2HasBuddies = (theBuddyGames->find(g2) != theBuddyGames->end()); - if ( g1HasBuddies ^ g2HasBuddies ) - { - return g1HasBuddies; - } - } - - switch(theGameSortType) - { - case GAMESORT_ALPHA_ASCENDING: - return wcsicmp(g1->getGameName().str(), g2->getGameName().str()) < 0; - break; - case GAMESORT_ALPHA_DESCENDING: - return wcsicmp(g1->getGameName().str(),g2->getGameName().str()) > 0; - break; - case GAMESORT_PING_ASCENDING: - return g1->getPingAsInt() < g2->getPingAsInt(); - break; - case GAMESORT_PING_DESCENDING: - return g1->getPingAsInt() > g2->getPingAsInt(); - break; - } - return false; - } -}; - -static Int insertGame( GameWindow *win, GameSpyStagingRoom *game, Bool showMap ) -{ - game->cleanUpSlotPointers(); - Color gameColor = GameSpyColor[GSCOLOR_GAME]; - if (game->getNumNonObserverPlayers() == game->getMaxPlayers() || game->getNumPlayers() == MAX_SLOTS) - { - gameColor = GameSpyColor[GSCOLOR_GAME_FULL]; - } - if (game->getExeCRC() != TheGlobalData->m_exeCRC || game->getIniCRC() != TheGlobalData->m_iniCRC) - { - gameColor = GameSpyColor[GSCOLOR_GAME_CRCMISMATCH]; - } - UnicodeString gameName = game->getGameName(); - - if(TheGameSpyInfo->getDisallowAsianText()) - { - const WideChar *buff = gameName.str(); - Int length = gameName.getLength(); - for(Int i = 0; i < length; ++i) - { - if(buff[i] >= 256) - return -1; - } - } - else if(TheGameSpyInfo->getDisallowNonAsianText()) - { - const WideChar *buff = gameName.str(); - Int length = gameName.getLength(); - Bool hasUnicode = FALSE; - for(Int i = 0; i < length; ++i) - { - if(buff[i] >= 256) - { - hasUnicode = TRUE; - break; - } - } - if(!hasUnicode) - return -1; - } - - - - Int index = GadgetListBoxAddEntryText(win, game->getGameName(), gameColor, -1, COLUMN_NAME); - GadgetListBoxSetItemData(win, (void *)game->getID(), index); - - UnicodeString s; - - if (showMap) - { - UnicodeString mapName; - const MapMetaData *md = TheMapCache->findMap(game->getMap()); - if (md) - { - mapName = md->m_displayName; - } - else - { - const char *start = game->getMap().reverseFind('\\'); - if (start) - { - ++start; - } - else - { - start = game->getMap().str(); - } - mapName.translate( start ); - } - GadgetListBoxAddEntryText(win, mapName, gameColor, index, COLUMN_MAP); - - const LadderInfo * li = TheLadderList->findLadder(game->getLadderIP(), game->getLadderPort()); - if (li) - { - GadgetListBoxAddEntryText(win, li->name, gameColor, index, COLUMN_LADDER); - } - else if (game->getLadderPort()) - { - GadgetListBoxAddEntryText(win, TheGameText->fetch("GUI:UnknownLadder"), gameColor, index, COLUMN_LADDER); - } - else - { - GadgetListBoxAddEntryText(win, TheGameText->fetch("GUI:NoLadder"), gameColor, index, COLUMN_LADDER); - } - } - else - { - GadgetListBoxAddEntryText(win, UnicodeString(L" "), gameColor, index, COLUMN_MAP); - GadgetListBoxAddEntryText(win, UnicodeString(L" "), gameColor, index, COLUMN_LADDER); - } - - s.format(L"%d/%d", game->getReportedNumPlayers(), game->getReportedMaxPlayers()); - GadgetListBoxAddEntryText(win, s, gameColor, index, COLUMN_NUMPLAYERS); - - if (game->getHasPassword()) - { - const Image *img = TheMappedImageCollection->findImageByName("Password"); - Int width = 10, height = 10; - if (img) - { - width = img->getImageWidth(); - height = img->getImageHeight(); - } - GadgetListBoxAddEntryImage(win, img, index, COLUMN_PASSWORD, width, height); - } - else - { - GadgetListBoxAddEntryText(win, UnicodeString(L" "), gameColor, index, COLUMN_PASSWORD); - } - - if (game->getAllowObservers()) - { - const Image *img = TheMappedImageCollection->findImageByName("Observer"); - GadgetListBoxAddEntryImage(win, img, index, COLUMN_OBSERVER); - } - else - { - GadgetListBoxAddEntryText(win, UnicodeString(L" "), gameColor, index, COLUMN_OBSERVER); - } - - { - if (game->getUseStats()) - { - const Image *img = TheMappedImageCollection->findImageByName("GoodStatsIcon"); - GadgetListBoxAddEntryImage(win, img, index, COLUMN_USE_STATS, img->getImageHeight(), img->getImageWidth()); - } - - } - - s.format(L"%d", game->getPingAsInt()); - GadgetListBoxAddEntryText(win, s, gameColor, index, COLUMN_PING); - Int ping = game->getPingAsInt(); - Int width = 10, height = 10; - if (pingImages[0]) - { - width = pingImages[0]->getImageWidth(); - height = pingImages[0]->getImageHeight(); - } - // CLH picking an arbitrary number for our ping display - if (ping < TheGameSpyConfig->getPingCutoffGood()) - { - GadgetListBoxAddEntryImage(win, pingImages[0], index, COLUMN_PING, width, height); - } - else if (ping < TheGameSpyConfig->getPingCutoffBad()) - { - GadgetListBoxAddEntryImage(win, pingImages[1], index, COLUMN_PING, width, height); - } - else - { - GadgetListBoxAddEntryImage(win, pingImages[2], index, COLUMN_PING, width, height); - } - - return index; -} - -void RefreshGameListBox( GameWindow *win, Bool showMap ) -{ - if (!win) - return; - - // save off selection - Int selectedIndex = -1; - Int indexToSelect = -1; - Int selectedID = 0; - GadgetListBoxGetSelected(win, &selectedIndex); - if (selectedIndex != -1 ) - { - selectedID = (Int)GadgetListBoxGetItemData(win, selectedIndex); - } - int prevPos = GadgetListBoxGetTopVisibleEntry( win ); - - // empty listbox - GadgetListBoxReset(win); - - // sort our games - typedef std::multiset SortedGameList; - SortedGameList sgl; - StagingRoomMap *srm = TheGameSpyInfo->getStagingRoomList(); - populateBuddyGames(); - for (StagingRoomMap::iterator srmIt = srm->begin(); srmIt != srm->end(); ++srmIt) - { - sgl.insert(srmIt->second); - } - - // populate listbox - for (SortedGameList::iterator sglIt = sgl.begin(); sglIt != sgl.end(); ++sglIt) - { - GameSpyStagingRoom *game = *sglIt; - if (game) - { - Int index = insertGame(win, game, showMap); - if (game->getID() == selectedID) - { - indexToSelect = index; - } - } - } - - clearBuddyGames(); - - // restore selection - GadgetListBoxSetSelected(win, indexToSelect); // even for -1, so we can disable the 'Join Game' button -// if(prevPos > 10) - GadgetListBoxSetTopVisibleEntry( win, prevPos );//+ 1 - - if (indexToSelect < 0 && selectedID) - { - TheWindowManager->winSetLoneWindow(NULL); - } -} - -void RefreshGameInfoListBox( GameWindow *mainWin, GameWindow *win ) -{ -// if (!mainWin || !win) -// return; -// -// GadgetListBoxReset(win); -// -// Int selected = -1; -// GadgetListBoxGetSelected(mainWin, &selected); -// if (selected < 0) -// { -// return; -// } -// -// Int selectedID = (Int)GadgetListBoxGetItemData(mainWin, selected); -// if (selectedID < 0) -// { -// return; -// } -// -// StagingRoomMap *srm = TheGameSpyInfo->getStagingRoomList(); -// StagingRoomMap::iterator srmIt = srm->find(selectedID); -// if (srmIt != srm->end()) -// { -// GameSpyStagingRoom *theRoom = srmIt->second; -// theRoom->cleanUpSlotPointers(); -// -// // game name -//// GadgetListBoxAddEntryText(listboxLobbyGameInfo, theRoom->getGameName(), GameSpyColor[GSCOLOR_DEFAULT], -1); -// -// const LadderInfo * li = TheLadderList->findLadder(theRoom->getLadderIP(), theRoom->getLadderPort()); -// if (li) -// { -// UnicodeString tmp; -// tmp.format(TheGameText->fetch("TOOLTIP:LadderName"), li->name.str()); -// GadgetListBoxAddEntryText(listboxLobbyGameInfo, tmp, GameSpyColor[GSCOLOR_DEFAULT], -1); -// } -// else if (theRoom->getLadderPort()) -// { -// GadgetListBoxAddEntryText(listboxLobbyGameInfo, TheGameText->fetch("TOOLTIP:UnknownLadder"), GameSpyColor[GSCOLOR_DEFAULT], -1); -// } -// else -// { -// GadgetListBoxAddEntryText(listboxLobbyGameInfo, TheGameText->fetch("TOOLTIP:NoLadder"), GameSpyColor[GSCOLOR_DEFAULT], -1); -// } -// -// if (theRoom->getExeCRC() != TheGlobalData->m_exeCRC || theRoom->getIniCRC() != TheGlobalData->m_iniCRC) -// { -// GadgetListBoxAddEntryText(listboxLobbyGameInfo, TheGameText->fetch("TOOLTIP:InvalidGameVersionSingleLine"), GameSpyColor[GSCOLOR_DEFAULT], -1); -// } -// -// // map name -// UnicodeString mapName; -// const MapMetaData *md = TheMapCache->findMap(theRoom->getMap()); -// if (md) -// { -// mapName = md->m_displayName; -// } -// else -// { -// const char *start = theRoom->getMap().reverseFind('\\'); -// if (start) -// { -// ++start; -// } -// else -// { -// start = theRoom->getMap().str(); -// } -// mapName.translate( start ); -// } -// -// GadgetListBoxAddEntryText(listboxLobbyGameInfo, mapName, GameSpyColor[GSCOLOR_DEFAULT], -1); -// -// // player list (rank, win/loss, side) -// for (Int i=0; igetGameSpySlot(i); -// if (slot && slot->isHuman()) -// { -// UnicodeString theName, theRating, thePlayerTemplate; -// Int colorIdx = slot->getColor(); -// theName = slot->getName(); -// theRating.format(L" (%d-%d)", slot->getWins(), slot->getLosses()); -// const PlayerTemplate * pt = ThePlayerTemplateStore->getNthPlayerTemplate(slot->getPlayerTemplate()); -// if (pt) -// { -// thePlayerTemplate = pt->getDisplayName(); -// } -// else -// { -// thePlayerTemplate = TheGameText->fetch("GUI:Random"); -// } -// -// UnicodeString theText; -// theText.format(L"%ls - %ls - %ls", theName.str(), thePlayerTemplate.str(), theRating.str()); -// -// Int theColor = GameSpyColor[GSCOLOR_DEFAULT]; -// const MultiplayerColorDefinition *mcd = TheMultiplayerSettings->getColor(colorIdx); -// if (mcd) -// { -// theColor = mcd->getColor(); -// } -// -// GadgetListBoxAddEntryText(listboxLobbyGameInfo, theText, theColor, -1); -// } -// } -// } - -} - -void RefreshGameListBoxes( void ) -{ - GameWindow *main = GetGameListBox(); - GameWindow *info = GetGameInfoListBox(); - - RefreshGameListBox( main, (info == NULL) ); - - if (info) - { - RefreshGameInfoListBox( main, info ); - } -} - -void ToggleGameListType( void ) -{ - isSmall = !isSmall; - if(isSmall) - { - parentGameListLarge->winHide(TRUE); -// parentGameListSmall->winHide(FALSE); - } - else - { - parentGameListLarge->winHide(FALSE); -// parentGameListSmall->winHide(TRUE); - } - - RefreshGameListBoxes(); -} - -// for use by GameWindow::winSetTooltipFunc -// displays the Army Tooltip for the player templates -void playerTemplateComboBoxTooltip(GameWindow *wndComboBox, WinInstanceData *instData, UnsignedInt mouse) -{ - Int index = 0; - GadgetComboBoxGetSelectedPos(wndComboBox, &index); - Int templateNum = (Int)GadgetComboBoxGetItemData(wndComboBox, index); - UnicodeString ustringTooltip; - if (templateNum == -1) - { - // the "Random" template is always first - ustringTooltip = TheGameText->fetch("TOOLTIP:BioStrategyLong_Random"); - } - else - { - const PlayerTemplate *playerTemplate = ThePlayerTemplateStore->getNthPlayerTemplate(templateNum); - if (playerTemplate) - { - ustringTooltip = TheGameText->fetch(playerTemplate->getTooltip()); - } - } - TheMouse->setCursorTooltip(ustringTooltip); -} - -// ----------------------------------------------------------------------------- - -// for use by GameWindow::winSetTooltipFunc -// displays the Army Tooltip for the player templates -void playerTemplateListBoxTooltip(GameWindow *wndListBox, WinInstanceData *instData, UnsignedInt mouse) -{ - Int x, y, row, col; - x = LOLONGTOSHORT(mouse); - y = HILONGTOSHORT(mouse); - GadgetListBoxGetEntryBasedOnXY(wndListBox, x, y, row, col); - if (row == -1 || col == -1) - return; - - Int templateNum = (Int)GadgetListBoxGetItemData(wndListBox, row, col); - UnicodeString ustringTooltip; - if (templateNum == -1) - { - // the "Random" template is always first - ustringTooltip = TheGameText->fetch("TOOLTIP:BioStrategyLong_Random"); - } - else - { - const PlayerTemplate *playerTemplate = ThePlayerTemplateStore->getNthPlayerTemplate(templateNum); - if (playerTemplate) - { - ustringTooltip = TheGameText->fetch(playerTemplate->getTooltip()); - } - } - - // use no tooltip delay here - TheMouse->setCursorTooltip(ustringTooltip, 0); -} diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/MainMenuUtils.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/MainMenuUtils.cpp deleted file mode 100644 index 17e6aa75e99..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/MainMenuUtils.cpp +++ /dev/null @@ -1,827 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////// -// FILE: MainMenuUtils.cpp -// Author: Matthew D. Campbell, Sept 2002 -// Description: GameSpy version check, patch download, etc utils -/////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include - -//#include "Common/Registry.h" -#include "Common/UserPreferences.h" -#include "Common/Version.h" -#include "GameClient/GameText.h" -#include "GameClient/MessageBox.h" -#include "GameClient/Shell.h" -#include "GameLogic/ScriptEngine.h" - -#include "GameClient/ShellHooks.h" - -#include "GameSpy/ghttp/ghttp.h" - -#include "GameNetwork/DownloadManager.h" -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/MainMenuUtils.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" - -#include "WWDownload/Registry.h" -#include "WWDownload/URLBuilder.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -/////////////////////////////////////////////////////////////////////////////////////// - -static Bool checkingForPatchBeforeGameSpy = FALSE; -static Int checksLeftBeforeOnline = 0; -static Int timeThroughOnline = 0; // used to avoid having old callbacks cause problems -static Bool mustDownloadPatch = FALSE; -static Bool cantConnectBeforeOnline = FALSE; -static std::list queuedDownloads; - -static char *MOTDBuffer = NULL; -static char *configBuffer = NULL; -GameWindow *onlineCancelWindow = NULL; - -static Bool s_asyncDNSThreadDone = TRUE; -static Bool s_asyncDNSThreadSucceeded = FALSE; -static Bool s_asyncDNSLookupInProgress = FALSE; -static HANDLE s_asyncDNSThreadHandle = NULL; -enum { - LOOKUP_INPROGRESS, - LOOKUP_FAILED, - LOOKUP_SUCCEEDED, -}; - -/////////////////////////////////////////////////////////////////////////////////////// - -static void startOnline( void ); -static void reallyStartPatchCheck( void ); - -/////////////////////////////////////////////////////////////////////////////////////// - -// someone has hit a button allowing downloads to start -void StartDownloadingPatches( void ) -{ - if (queuedDownloads.empty()) - { - HandleCanceledDownload(); - return; - } - - WindowLayout *layout; - layout = TheWindowManager->winCreateLayout( AsciiString( "Menus/DownloadMenu.wnd" ) ); - layout->runInit(); - layout->hide( FALSE ); - layout->bringForward(); - HandleCanceledDownload(FALSE); - DEBUG_ASSERTCRASH(TheDownloadManager, ("No download manager!")); - if (TheDownloadManager) - { - std::list::iterator it = queuedDownloads.begin(); - while (it != queuedDownloads.end()) - { - QueuedDownload q = *it; - TheDownloadManager->queueFileForDownload(q.server, q.userName, q.password, - q.file, q.localFile, q.regKey, q.tryResume); - queuedDownloads.pop_front(); - it = queuedDownloads.begin(); - } - TheDownloadManager->downloadNextQueuedFile(); - } -} - -/////////////////////////////////////////////////////////////////////////////////////// - -// user agrees to patch before going online -static void patchBeforeOnlineCallback( void ) -{ - StartDownloadingPatches(); -} - -// user doesn't want to patch before going online -static void noPatchBeforeOnlineCallback( void ) -{ - queuedDownloads.clear(); - if (mustDownloadPatch || cantConnectBeforeOnline) - { - // go back to normal - HandleCanceledDownload(); - } - else - { - // clear out unneeded downloads and go on - startOnline(); - } -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static Bool hasWriteAccess() -{ - const char* filename = "PatchAccessTest.txt"; - - remove(filename); - - int handle = _open( filename, _O_CREAT | _O_RDWR, _S_IREAD | _S_IWRITE); - if (handle == -1) - { - return false; - } - - _close(handle); - remove(filename); - - unsigned int val; - if (!GetUnsignedIntFromRegistry("", "Version", val)) - { - return false; - } - - if (!SetUnsignedIntInRegistry("", "Version", val)) - { - return false; - } - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static void startOnline( void ) -{ - checkingForPatchBeforeGameSpy = FALSE; - - DEBUG_ASSERTCRASH(checksLeftBeforeOnline==0, ("starting online with pending callbacks")); - if (onlineCancelWindow) - { - TheWindowManager->winDestroy(onlineCancelWindow); - onlineCancelWindow = NULL; - } - - if (cantConnectBeforeOnline) - { - MessageBoxOk(TheGameText->fetch("GUI:CannotConnectToServservTitle"), - TheGameText->fetch("GUI:CannotConnectToServserv"), - noPatchBeforeOnlineCallback); - return; - } - if (queuedDownloads.size()) - { - if (!hasWriteAccess()) - { - MessageBoxOk(TheGameText->fetch("GUI:Error"), - TheGameText->fetch("GUI:MustHaveAdminRights"), - noPatchBeforeOnlineCallback); - } - else if (mustDownloadPatch) - { - MessageBoxOkCancel(TheGameText->fetch("GUI:PatchAvailable"), - TheGameText->fetch("GUI:MustPatchForOnline"), - patchBeforeOnlineCallback, noPatchBeforeOnlineCallback); - } - else - { - MessageBoxYesNo(TheGameText->fetch("GUI:PatchAvailable"), - TheGameText->fetch("GUI:CanPatchForOnline"), - patchBeforeOnlineCallback, noPatchBeforeOnlineCallback); - } - return; - } - - TheScriptEngine->signalUIInteract(TheShellHookNames[SHELL_SCRIPT_HOOK_MAIN_MENU_ONLINE_SELECTED]); - - DEBUG_ASSERTCRASH( !TheGameSpyBuddyMessageQueue, ("TheGameSpyBuddyMessageQueue exists!") ); - DEBUG_ASSERTCRASH( !TheGameSpyPeerMessageQueue, ("TheGameSpyPeerMessageQueue exists!") ); - DEBUG_ASSERTCRASH( !TheGameSpyInfo, ("TheGameSpyInfo exists!") ); - SetUpGameSpy(MOTDBuffer, configBuffer); - if (MOTDBuffer) - { - delete[] MOTDBuffer; - MOTDBuffer = NULL; - } - if (configBuffer) - { - delete[] configBuffer; - configBuffer = NULL; - } - -#ifdef ALLOW_NON_PROFILED_LOGIN - UserPreferences pref; - pref.load("GameSpyLogin.ini"); - UserPreferences::const_iterator it = pref.find("useProfiles"); - if (it != pref.end() && it->second.compareNoCase("yes") == 0) -#endif ALLOW_NON_PROFILED_LOGIN - TheShell->push( AsciiString("Menus/GameSpyLoginProfile.wnd") ); -#ifdef ALLOW_NON_PROFILED_LOGIN - else - TheShell->push( AsciiString("Menus/GameSpyLoginQuick.wnd") ); -#endif ALLOW_NON_PROFILED_LOGIN -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static void queuePatch(Bool mandatory, AsciiString downloadURL) -{ - QueuedDownload q; - Bool success = TRUE; - - AsciiString connectionType; - success &= downloadURL.nextToken(&connectionType, ":"); - - AsciiString server; - success &= downloadURL.nextToken(&server, ":/"); - - AsciiString user; - success &= downloadURL.nextToken(&user, ":@"); - - AsciiString pass; - success &= downloadURL.nextToken(&pass, "@/"); - - AsciiString filePath; - success &= downloadURL.nextToken(&filePath, ""); - - if (!success && user.isNotEmpty()) - { - // no user/pass combo - move the file into it's proper place - filePath = user; - user = ""; // LFeenanEA - Credentials removed as per Security requirements - pass = ""; - success = TRUE; - } - - AsciiString fileStr = filePath; - const char *s = filePath.reverseFind('/'); - if (s) - fileStr = s+1; - AsciiString fileName = "patches\\"; - fileName.concat(fileStr); - - DEBUG_LOG(("download URL split: %d [%s] [%s] [%s] [%s] [%s] [%s]\n", - success, connectionType.str(), server.str(), user.str(), pass.str(), - filePath.str(), fileName.str())); - - if (!success) - return; - - q.file = filePath; - q.localFile = fileName; - q.password = pass; - q.regKey = ""; - q.server = server; - q.tryResume = TRUE; - q.userName = user; - - std::list::iterator it = queuedDownloads.begin(); - while (it != queuedDownloads.end()) - { - if (it->localFile == q.localFile) - return; // don't add it if it exists already (because we can check multiple times) - ++it; - } - - queuedDownloads.push_back(q); -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static GHTTPBool motdCallback( GHTTPRequest request, GHTTPResult result, - char * buffer, GHTTPByteCount bufferLen, void * param ) -{ - Int run = (Int)param; - if (run != timeThroughOnline) - { - DEBUG_CRASH(("Old callback being called!")); - return GHTTPTrue; - } - - if (MOTDBuffer) - { - delete[] MOTDBuffer; - MOTDBuffer = NULL; - } - - MOTDBuffer = NEW char[bufferLen]; - memcpy(MOTDBuffer, buffer, bufferLen); - MOTDBuffer[bufferLen-1] = 0; - - --checksLeftBeforeOnline; - DEBUG_ASSERTCRASH(checksLeftBeforeOnline>=0, ("Too many callbacks")); - if (onlineCancelWindow && !checksLeftBeforeOnline) - { - TheWindowManager->winDestroy(onlineCancelWindow); - onlineCancelWindow = NULL; - } - - DEBUG_LOG(("------- Got MOTD before going online -------\n")); - DEBUG_LOG(("%s\n", (MOTDBuffer)?MOTDBuffer:"")); - DEBUG_LOG(("--------------------------------------------\n")); - - if (!checksLeftBeforeOnline) - startOnline(); - - return GHTTPTrue; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static GHTTPBool configCallback( GHTTPRequest request, GHTTPResult result, - char * buffer, GHTTPByteCount bufferLen, void * param ) -{ - Int run = (Int)param; - if (run != timeThroughOnline) - { - DEBUG_CRASH(("Old callback being called!")); - return GHTTPTrue; - } - - if (configBuffer) - { - delete[] configBuffer; - configBuffer = NULL; - } - - if (result != GHTTPSuccess || bufferLen < 100) - { - if (!checkingForPatchBeforeGameSpy) - return GHTTPTrue; - --checksLeftBeforeOnline; - if (onlineCancelWindow && !checksLeftBeforeOnline) - { - TheWindowManager->winDestroy(onlineCancelWindow); - onlineCancelWindow = NULL; - } - cantConnectBeforeOnline = TRUE; - if (!checksLeftBeforeOnline) - { - startOnline(); - } - return GHTTPTrue; - } - - configBuffer = NEW char[bufferLen]; - memcpy(configBuffer, buffer, bufferLen); - configBuffer[bufferLen-1] = 0; - - AsciiString fname; - fname.format("%sGeneralsOnline\\Config.txt", TheGlobalData->getPath_UserData().str()); - FILE *fp = fopen(fname.str(), "wb"); - if (fp) - { - fwrite(configBuffer, bufferLen, 1, fp); - fclose(fp); - } - - --checksLeftBeforeOnline; - DEBUG_ASSERTCRASH(checksLeftBeforeOnline>=0, ("Too many callbacks")); - if (onlineCancelWindow && !checksLeftBeforeOnline) - { - TheWindowManager->winDestroy(onlineCancelWindow); - onlineCancelWindow = NULL; - } - - DEBUG_LOG(("Got Config before going online\n")); - - if (!checksLeftBeforeOnline) - startOnline(); - - return GHTTPTrue; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static GHTTPBool configHeadCallback( GHTTPRequest request, GHTTPResult result, - char * buffer, GHTTPByteCount bufferLen, void * param ) -{ - Int run = (Int)param; - if (run != timeThroughOnline) - { - DEBUG_CRASH(("Old callback being called!")); - return GHTTPTrue; - } - - DEBUG_LOG(("HTTP head resp: res=%d, len=%d, buf=[%s]\n", result, bufferLen, buffer)); - - if (result == GHTTPSuccess) - { - DEBUG_LOG(("Headers are [%s]\n", ghttpGetHeaders( request ))); - - AsciiString headers(ghttpGetHeaders( request )); - AsciiString line; - while (headers.nextToken(&line, "\n\r")) - { - AsciiString key, val; - line.nextToken(&key, ": "); - line.nextToken(&val, ": \r\n"); - - if (key.compare("Content-Length") == 0 && val.isNotEmpty()) - { - Int serverLen = atoi(val.str()); - Int fileLen = 0; - AsciiString fname; - fname.format("%sGeneralsOnline\\Config.txt", TheGlobalData->getPath_UserData().str()); - FILE *fp = fopen(fname.str(), "rb"); - if (fp) - { - fseek(fp, 0, SEEK_END); - fileLen = ftell(fp); - fclose(fp); - } - - if (serverLen == fileLen) - { - // we don't need to download the MOTD again - --checksLeftBeforeOnline; - DEBUG_ASSERTCRASH(checksLeftBeforeOnline>=0, ("Too many callbacks")); - if (onlineCancelWindow && !checksLeftBeforeOnline) - { - TheWindowManager->winDestroy(onlineCancelWindow); - onlineCancelWindow = NULL; - } - - if (configBuffer) - { - delete[] configBuffer; - configBuffer = NULL; - } - - AsciiString fname; - fname.format("%sGeneralsOnline\\Config.txt", TheGlobalData->getPath_UserData().str()); - FILE *fp = fopen(fname.str(), "rb"); - if (fp) - { - configBuffer = NEW char[fileLen]; - fread(configBuffer, fileLen, 1, fp); - configBuffer[fileLen-1] = 0; - fclose(fp); - - DEBUG_LOG(("Got Config before going online\n")); - - if (!checksLeftBeforeOnline) - startOnline(); - - return GHTTPTrue; - } - } - } - } - } - - // we need to download the MOTD again - std::string gameURL, mapURL; - std::string configURL, motdURL; - FormatURLFromRegistry(gameURL, mapURL, configURL, motdURL); - ghttpGet( configURL.c_str(), GHTTPFalse, configCallback, param ); - - return GHTTPTrue; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static GHTTPBool gamePatchCheckCallback( GHTTPRequest request, GHTTPResult result, char * buffer, GHTTPByteCount bufferLen, void * param ) -{ - Int run = (Int)param; - if (run != timeThroughOnline) - { - DEBUG_CRASH(("Old callback being called!")); - return GHTTPTrue; - } - - --checksLeftBeforeOnline; - DEBUG_ASSERTCRASH(checksLeftBeforeOnline>=0, ("Too many callbacks")); - - DEBUG_LOG(("Result=%d, buffer=[%s], len=%d\n", result, buffer, bufferLen)); - if (result != GHTTPSuccess) - { - if (!checkingForPatchBeforeGameSpy) - return GHTTPTrue; - cantConnectBeforeOnline = TRUE; - if (!checksLeftBeforeOnline) - { - startOnline(); - } - return GHTTPTrue; - } - - AsciiString message = buffer; - AsciiString line; - while (message.nextToken(&line, "\r\n")) - { - AsciiString type, req, url; - Bool ok = TRUE; - ok &= line.nextToken(&type, " "); - ok &= line.nextToken(&req, " "); - ok &= line.nextToken(&url, " "); - if (ok && type == "patch") - { - DEBUG_LOG(("Saw a patch: %d/[%s]\n", atoi(req.str()), url.str())); - queuePatch( atoi(req.str()), url ); - if (atoi(req.str())) - { - mustDownloadPatch = TRUE; - } - } - else if (ok && type == "server") - { - } - } - - if (!checksLeftBeforeOnline) - { - startOnline(); - } - - return GHTTPTrue; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -void CancelPatchCheckCallbackAndReopenDropdown( void ) -{ - HandleCanceledDownload(); - CancelPatchCheckCallback(); -} - -void CancelPatchCheckCallback( void ) -{ - s_asyncDNSLookupInProgress = FALSE; - HandleCanceledDownload(FALSE); // don't dropdown - checkingForPatchBeforeGameSpy = FALSE; - checksLeftBeforeOnline = 0; - if (onlineCancelWindow) - { - TheWindowManager->winDestroy(onlineCancelWindow); - onlineCancelWindow = NULL; - } - queuedDownloads.clear(); - if (MOTDBuffer) - { - delete[] MOTDBuffer; - MOTDBuffer = NULL; - } - if (configBuffer) - { - delete[] configBuffer; - configBuffer = NULL; - } -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static GHTTPBool overallStatsCallback( GHTTPRequest request, GHTTPResult result, char * buffer, GHTTPByteCount bufferLen, void * param ) -{ - DEBUG_LOG(("overallStatsCallback() - Result=%d, len=%d\n", result, bufferLen)); - if (result != GHTTPSuccess) - { - return GHTTPTrue; - } - - HandleOverallStats( buffer, bufferLen ); - return GHTTPTrue; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static GHTTPBool numPlayersOnlineCallback( GHTTPRequest request, GHTTPResult result, char * buffer, GHTTPByteCount bufferLen, void * param ) -{ - DEBUG_LOG(("numPlayersOnlineCallback() - Result=%d, buffer=[%s], len=%d\n", result, buffer, bufferLen)); - if (result != GHTTPSuccess) - { - return GHTTPTrue; - } - - AsciiString message = buffer; - message.trim(); - const char *s = message.reverseFind('\\'); - if (!s) - { - return GHTTPTrue; - } - - if (*s == '\\') - ++s; - - DEBUG_LOG(("Message was '%s', trimmed to '%s'=%d\n", buffer, s, atoi(s))); - HandleNumPlayersOnline(atoi(s)); - - return GHTTPTrue; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -void CheckOverallStats( void ) -{ - ghttpGet("http://gamestats.gamespy.com/ccgenzh/display.html", - GHTTPFalse, overallStatsCallback, NULL); -} - -/////////////////////////////////////////////////////////////////////////////////////// - -void CheckNumPlayersOnline( void ) -{ - ghttpGet("http://launch.gamespyarcade.com/software/launch/arcadecount2.dll?svcname=ccgenzh", - GHTTPFalse, numPlayersOnlineCallback, NULL); -} - -/////////////////////////////////////////////////////////////////////////////////////// - -DWORD WINAPI asyncGethostbynameThreadFunc( void * szName ) -{ - HOSTENT *he = gethostbyname( (const char *)szName ); - - if (he) - { - s_asyncDNSThreadSucceeded = TRUE; - } - else - { - s_asyncDNSThreadSucceeded = FALSE; - } - - s_asyncDNSThreadDone = TRUE; - return 0; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -int asyncGethostbyname(char * szName) -{ - static int stat = 0; - static unsigned long threadid; - - if( stat == 0 ) - { - /* Kick off gethostname thread */ - s_asyncDNSThreadDone = FALSE; - s_asyncDNSThreadHandle = CreateThread( NULL, 0, asyncGethostbynameThreadFunc, szName, 0, &threadid ); - - if( s_asyncDNSThreadHandle == NULL ) - { - return( LOOKUP_FAILED ); - } - stat = 1; - } - if( stat == 1 ) - { - if( s_asyncDNSThreadDone ) - { - /* Thread finished */ - stat = 0; - s_asyncDNSLookupInProgress = FALSE; - s_asyncDNSThreadHandle = NULL; - return( (s_asyncDNSThreadSucceeded)?LOOKUP_SUCCEEDED:LOOKUP_FAILED ); - } - } - - return( LOOKUP_INPROGRESS ); -} - -/////////////////////////////////////////////////////////////////////////////////////// - -// GameSpy's HTTP SDK has had at least 1 crash bug, so we're going to just bail and -// never try again if they crash us. We won't be able to get back online again (we'll -// time out) but at least we'll live. -static Bool isHttpOk = TRUE; - -void HTTPThinkWrapper( void ) -{ - if (s_asyncDNSLookupInProgress) - { - Int ret = asyncGethostbyname("servserv.generals.ea.com"); - switch(ret) - { - case LOOKUP_FAILED: - cantConnectBeforeOnline = TRUE; - startOnline(); - break; - case LOOKUP_SUCCEEDED: - reallyStartPatchCheck(); - break; - } - } - - if (isHttpOk) - { - try - { - ghttpThink(); - } - catch (...) - { - isHttpOk = FALSE; // we can't abort the login, since we might be done with the - // required checks and are fetching extras. If it is a required - // check, we'll time out normally. - } - } -} - -/////////////////////////////////////////////////////////////////////////////////////// - -void StopAsyncDNSCheck( void ) -{ - if (s_asyncDNSThreadHandle) - { -#ifdef DEBUG_CRASHING - Int res = -#endif - TerminateThread(s_asyncDNSThreadHandle,0); - DEBUG_ASSERTCRASH(res, ("Could not terminate the Async DNS Lookup thread!")); // Thread still not killed! - } - s_asyncDNSThreadHandle = NULL; - s_asyncDNSLookupInProgress = FALSE; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -void StartPatchCheck( void ) -{ - checkingForPatchBeforeGameSpy = TRUE; - cantConnectBeforeOnline = FALSE; - timeThroughOnline++; - checksLeftBeforeOnline = 0; - - onlineCancelWindow = MessageBoxCancel(TheGameText->fetch("GUI:CheckingForPatches"), - TheGameText->fetch("GUI:CheckingForPatches"), CancelPatchCheckCallbackAndReopenDropdown); - - s_asyncDNSLookupInProgress = TRUE; - Int ret = asyncGethostbyname("servserv.generals.ea.com"); - switch(ret) - { - case LOOKUP_FAILED: - cantConnectBeforeOnline = TRUE; - startOnline(); - break; - case LOOKUP_SUCCEEDED: - reallyStartPatchCheck(); - break; - } -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static void reallyStartPatchCheck( void ) -{ - checksLeftBeforeOnline = 4; - - std::string gameURL, mapURL; - std::string configURL, motdURL; - - FormatURLFromRegistry(gameURL, mapURL, configURL, motdURL); - - std::string proxy; - if (GetStringFromRegistry("", "Proxy", proxy)) - { - if (!proxy.empty()) - { - ghttpSetProxy(proxy.c_str()); - } - } - - // check for a patch first - DEBUG_LOG(("Game patch check: [%s]\n", gameURL.c_str())); - DEBUG_LOG(("Map patch check: [%s]\n", mapURL.c_str())); - DEBUG_LOG(("Config: [%s]\n", configURL.c_str())); - DEBUG_LOG(("MOTD: [%s]\n", motdURL.c_str())); - ghttpGet(gameURL.c_str(), GHTTPFalse, gamePatchCheckCallback, (void *)timeThroughOnline); - ghttpGet(mapURL.c_str(), GHTTPFalse, gamePatchCheckCallback, (void *)timeThroughOnline); - ghttpHead(configURL.c_str(), GHTTPFalse, configHeadCallback, (void *)timeThroughOnline); - ghttpGet(motdURL.c_str(), GHTTPFalse, motdCallback, (void *)timeThroughOnline); - - // check total game stats - CheckOverallStats(); - - // check the users online - CheckNumPlayersOnline(); -} - -/////////////////////////////////////////////////////////////////////////////////////// diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/PeerDefs.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/PeerDefs.cpp deleted file mode 100644 index c4a94f92fc6..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/PeerDefs.cpp +++ /dev/null @@ -1,945 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -// FILE: PeerDefs.cpp ////////////////////////////////////////////////////// -// Generals GameSpy Peer (chat) definitions -// Author: Matthew D. Campbell, June 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine -#include - -#include "Common/GameState.h" -#include "Common/RandomValue.h" -#include "Common/IgnorePreferences.h" -#include "Common/CustomMatchPreferences.h" -#include "Common/GameSpyMiscPreferences.h" -#include "Common/Recorder.h" -#include "Common/Player.h" -#include "Common/PlayerList.h" -#include "Common/PlayerTemplate.h" -#include "GameClient/MapUtil.h" -#include "GameClient/ShellHooks.h" -#include "GameClient/GameText.h" -#include "GameNetwork/GameSpy/LadderDefs.h" -#include "GameNetwork/GameSpy/PeerDefsImplementation.h" -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PingThread.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpy/GSConfig.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameNetwork/RankPointValue.h" -#include "GameLogic/GameLogic.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -GameSpyInfoInterface *TheGameSpyInfo = NULL; -extern GameSpyStagingRoom *TheGameSpyGame = NULL; -void deleteNotificationBox( void ); - -bool AsciiComparator::operator()(AsciiString s1, AsciiString s2) const -{ - return stricmp(s1.str(), s2.str()) < 0; -} - -GameSpyInfo::GameSpyInfo() -{ - reset(); - TheGameSpyGame = &m_localStagingRoom; - m_isDisconAfterGameStart = FALSE; -} - -GameSpyInfo::~GameSpyInfo() -{ - TheGameSpyGame = NULL; - reset(); -} - -void GameSpyInfo::reset( void ) -{ - m_sawFullGameList = FALSE; - m_isDisconAfterGameStart = FALSE; - m_currentGroupRoomID = 0; - clearGroupRoomList(); - clearStagingRoomList(); - m_localStagingRoomID = 0; - m_buddyRequestMap.clear(); - m_buddyMap.clear(); - m_buddyMessages.clear(); - m_joinedStagingRoom = 0; - m_isHosting = false; - m_localStagingRoomID = 0; - m_localStagingRoom.reset(); - m_gotGroupRoomList = false; - m_localName = ""; - m_localProfileID = 0; - m_maxMessagesPerUpdate = 100; - - // Added By Sadullah Nader - // Initialization missing and needed - m_disallowAsainText = FALSE; - m_disallowNonAsianText = FALSE; - m_disconReason = 0; - m_localBaseName.clear(); - m_localEmail.clear(); - m_localPasswd.clear(); - m_pingString.clear(); - m_rawConfig.clear(); - m_rawMotd.clear(); - // - - m_internalIP = m_externalIP = 0; - - m_savedIgnoreMap.clear(); - m_preorderPlayers.clear(); - - m_cachedLocalPlayerStats.reset(); - - m_additionalDisconnects = -1; -} - -Bool GameSpyInfo::didPlayerPreorder( Int profileID ) const -{ - std::set::const_iterator it = m_preorderPlayers.find(profileID); - return (it != m_preorderPlayers.end()); -} - -void GameSpyInfo::markPlayerAsPreorder( Int profileID ) -{ - m_preorderPlayers.insert(profileID); -} - -void GameSpyInfo::setLocalIPs(UnsignedInt internalIP, UnsignedInt externalIP) -{ - m_internalIP = internalIP; - m_externalIP = externalIP; -} - -void GameSpyInfo::readAdditionalDisconnects( void ) -{ - m_additionalDisconnects = GetAdditionalDisconnectsFromUserFile(m_localProfileID); - DEBUG_LOG(("GameSpyInfo::readAdditionalDisconnects() found %d disconnects.\n", m_additionalDisconnects)); -} - -Int GameSpyInfo::getAdditionalDisconnects( void ) -{ - DEBUG_LOG(("GameSpyInfo::getAdditionalDisconnects() would have returned %d. Returning 0 instead.\n", m_additionalDisconnects)); - return 0; -} - -void GameSpyInfo::clearAdditionalDisconnects( void ) -{ - m_additionalDisconnects = 0; -} - -GameSpyInfoInterface* GameSpyInfoInterface::createNewGameSpyInfoInterface( void ) -{ - return NEW GameSpyInfo; -} - -Bool GameSpyInfo::amIHost( void ) -{ - return m_isHosting; -} - -GameSpyStagingRoom* GameSpyInfo::getCurrentStagingRoom( void ) -{ - if (m_isHosting || m_joinedStagingRoom) - return &m_localStagingRoom; - - StagingRoomMap::iterator it = m_stagingRooms.find(m_joinedStagingRoom); - if (it != m_stagingRooms.end()) - return it->second; - - return NULL; -} - -void GameSpyInfo::setGameOptions( void ) -{ - if (!m_isHosting) - return; - - // set options for game lists, and UTM players in-game - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_SETGAMEOPTIONS; - req.options = GameInfoToAsciiString(&m_localStagingRoom).str(); - - Int i; - AsciiString mapName = TheGameState->realMapPathToPortableMapPath(m_localStagingRoom.getMap()); - AsciiString newMapName; - for (i=0; igetGameSpySlot(i); - req.gameOptsPlayerNames[i] = ""; - if (!slot->isOccupied()) - { - if (slot->isOpen()) - ++numOpenSlots; - } - else - { - AsciiString playerName; - if (slot->isHuman()) - { - playerName.translate(slot->getName()); - req.gameOptsPlayerNames[i] = playerName.str(); - PlayerInfoMap::iterator it = m_playerInfoMap.find(playerName); - if (it != m_playerInfoMap.end()) - { - wins = it->second.m_wins; - losses = it->second.m_losses; - profileID = it->second.m_profileID; - } - req.gameOptions.wins[req.gameOptions.numObservers+req.gameOptions.numPlayers] = wins; - req.gameOptions.losses[req.gameOptions.numObservers+req.gameOptions.numPlayers] = losses; - req.gameOptions.profileID[req.gameOptions.numObservers+req.gameOptions.numPlayers] = profileID; - req.gameOptions.faction[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getPlayerTemplate(); - req.gameOptions.color[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getColor(); - if (slot->getPlayerTemplate() == PLAYERTEMPLATE_OBSERVER) - { - ++req.gameOptions.numObservers; - } - else - { - ++req.gameOptions.numPlayers; - } - } - else if (slot->isAI()) - { - // add in AI players - switch (slot->getState()) - { - case SLOT_EASY_AI: - playerName = "CE"; - break; - case SLOT_MED_AI: - playerName = "CM"; - break; - case SLOT_BRUTAL_AI: - playerName = "CH"; - break; - } - req.gameOptsPlayerNames[i] = playerName.str(); // name is unused - we go off of the profileID - req.gameOptions.wins[req.gameOptions.numObservers+req.gameOptions.numPlayers] = 0; - req.gameOptions.losses[req.gameOptions.numObservers+req.gameOptions.numPlayers] = 0; - req.gameOptions.profileID[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getState(); - req.gameOptions.faction[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getPlayerTemplate(); - req.gameOptions.color[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getColor(); - ++req.gameOptions.numPlayers; - } - } - } - req.gameOptions.maxPlayers = numOpenSlots + req.gameOptions.numPlayers + req.gameOptions.numObservers; - TheGameSpyPeerMessageQueue->addRequest(req); - - req.peerRequestType = PeerRequest::PEERREQUEST_UTMROOM; - req.UTM.isStagingRoom = TRUE; - req.id = "Pings/"; - AsciiString pings; - for (i=0; igetGameSpySlot(i); - if (slot && slot->isHuman()) - { - pings.concat(slot->getPingString()); - } - else - { - pings.concat("0"); - } - } - req.options = pings.str(); - TheGameSpyPeerMessageQueue->addRequest(req); -} - -Bool GameSpyInfo::isBuddy( Int id ) -{ - return m_buddyMap.find(id) != m_buddyMap.end(); -} - -void GameSpyInfo::addGroupRoom( GameSpyGroupRoom room ) -{ - if (room.m_groupID == 0) - { - m_gotGroupRoomList = TRUE; - - GroupRoomMap::iterator iter; - - // figure out how many good strings we've got - std::vector names; - Int numRooms = 0; - for (iter = getGroupRoomList()->begin(); iter != getGroupRoomList()->end(); ++iter) - { - GameSpyGroupRoom room = iter->second; - if (room.m_groupID != TheGameSpyConfig->getQMChannel()) - { - ++numRooms; - - AsciiString groupLabel; - groupLabel.format("GUI:%s", room.m_name.str()); - - Bool exists = FALSE; - UnicodeString groupName = TheGameText->fetch(groupLabel, &exists); - if (exists) - { - names.push_back(groupName); - } - } - } - - if (!names.empty() && names.size() != numRooms) - { - // didn't get all names. fix up - Int nameIndex = 0; - Int timesThrough = 1; // start with USA Lobby 1 - for (iter = TheGameSpyInfo->getGroupRoomList()->begin(); iter != TheGameSpyInfo->getGroupRoomList()->end(); ++iter) - { - GameSpyGroupRoom room = iter->second; - if (room.m_groupID != TheGameSpyConfig->getQMChannel()) - { - room.m_translatedName.format(L"%ls %d", names[nameIndex].str(), timesThrough); - nameIndex = (nameIndex+1)%names.size(); - m_groupRooms[room.m_groupID] = room; - if (!nameIndex) - { - // we've looped through the name list already. increment the timesThrough counter - ++timesThrough; - } - } - } - } - } - else - { - DEBUG_LOG(("Adding group room %d (%s)\n", room.m_groupID, room.m_name.str())); - AsciiString groupLabel; - groupLabel.format("GUI:%s", room.m_name.str()); - room.m_translatedName = TheGameText->fetch(groupLabel); - m_groupRooms[room.m_groupID] = room; - if ( !stricmp("quickmatch", room.m_name.str()) ) - { - DEBUG_LOG(("Group room %d (%s) is the QuickMatch room\n", room.m_groupID, room.m_name.str())); - TheGameSpyConfig->setQMChannel(room.m_groupID); - } - } -} - -void GameSpyInfo::joinGroupRoom( Int groupID ) -{ - if (groupID > 0) - { - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_JOINGROUPROOM; - req.groupRoom.id = groupID; - TheGameSpyPeerMessageQueue->addRequest(req); - m_playerInfoMap.clear(); - } -} - -void GameSpyInfo::leaveGroupRoom( void ) -{ - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_LEAVEGROUPROOM; - TheGameSpyPeerMessageQueue->addRequest(req); - setCurrentGroupRoom(0); - m_playerInfoMap.clear(); -} - -void GameSpyInfo::joinBestGroupRoom( void ) -{ - if (m_currentGroupRoomID) - { - DEBUG_LOG(("Bailing from GameSpyInfo::joinBestGroupRoom() - we were already in a room\n")); - m_currentGroupRoomID = 0; - return; - } - - if (m_groupRooms.size()) - { - int minID = -1; - int minPlayers = 1000; - GroupRoomMap::iterator iter = m_groupRooms.begin(); - while (iter != m_groupRooms.end()) - { - GameSpyGroupRoom room = iter->second; - DEBUG_LOG(("Group room %d: %s (%d, %d, %d, %d)\n", room.m_groupID, room.m_name.str(), room.m_numWaiting, room.m_maxWaiting, - room.m_numGames, room.m_numPlaying)); - - if (TheGameSpyConfig->getQMChannel() != room.m_groupID && minPlayers > 25 && room.m_numWaiting < minPlayers) - { - minID = room.m_groupID; - minPlayers = room.m_numWaiting; - } - - ++iter; - } - - if (minID > 0) - { - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_JOINGROUPROOM; - req.groupRoom.id = minID; - TheGameSpyPeerMessageQueue->addRequest(req); - m_playerInfoMap.clear(); - } - else - { - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSGroupRoomJoinFail"), NULL); - } - } - else - { - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSGroupRoomJoinFail"), NULL); - } -} - -void GameSpyInfo::updatePlayerInfo( PlayerInfo pi, AsciiString oldNick ) -{ - if (!oldNick.isEmpty()) - playerLeftGroupRoom(oldNick); - - m_playerInfoMap[pi.m_name] = pi; - - if (pi.m_preorder != 0) - markPlayerAsPreorder(pi.m_profileID); -} - -void GameSpyInfo::playerLeftGroupRoom( AsciiString nick ) -{ - PlayerInfoMap::iterator it = m_playerInfoMap.find(nick); - if (it != m_playerInfoMap.end()) - { - m_playerInfoMap.erase(it); - } -} - -void GameSpyInfo::clearStagingRoomList( void ) -{ - Int numRoomsRemoved = 0; - m_sawFullGameList = FALSE; - m_stagingRoomsDirty = FALSE; - - StagingRoomMap::iterator it = m_stagingRooms.begin(); - while (it != m_stagingRooms.end()) - { - ++numRoomsRemoved; - - delete it->second; - m_stagingRooms.erase(it); - it = m_stagingRooms.begin(); - } - if (numRoomsRemoved > 0) - { - //m_stagingRoomsDirty = true; // only consider ourselves dirty if we actually removed some games. - } -} - -void GameSpyInfo::addStagingRoom( GameSpyStagingRoom room ) -{ - removeStagingRoom(room); - GameSpyStagingRoom *newRoom = NEW GameSpyStagingRoom; - *newRoom = room; - newRoom->cleanUpSlotPointers(); - m_stagingRooms[room.getID()] = newRoom; - m_stagingRoomsDirty = m_sawFullGameList; -} - -void GameSpyInfo::updateStagingRoom( GameSpyStagingRoom room ) -{ - addStagingRoom(room); -} - -void GameSpyInfo::removeStagingRoom( GameSpyStagingRoom room ) -{ - StagingRoomMap::iterator it = m_stagingRooms.find(room.getID()); - if (it != m_stagingRooms.end()) - { - delete it->second; - m_stagingRooms.erase(it); - - m_stagingRoomsDirty = m_sawFullGameList; - } -} - -Bool GameSpyInfo::hasStagingRoomListChanged( void ) -{ - Bool val = m_stagingRoomsDirty; - m_stagingRoomsDirty = false; - return val; -} - -GameSpyStagingRoom* GameSpyInfo::findStagingRoomByID( Int id ) -{ - StagingRoomMap::iterator it = m_stagingRooms.find(id); - if (it != m_stagingRooms.end()) - return it->second; - - return NULL; -} - -void GameSpyInfo::leaveStagingRoom( void ) -{ - m_localStagingRoomID = 0; - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_LEAVESTAGINGROOM; - TheGameSpyPeerMessageQueue->addRequest(req); - m_playerInfoMap.clear(); - m_joinedStagingRoom = FALSE; - m_isHosting = FALSE; -} - -void GameSpyInfo::markAsStagingRoomHost( void ) -{ - m_localStagingRoomID = 0; - m_joinedStagingRoom = FALSE; m_isHosting = TRUE; - - // There are a few options we don't want to reset when we are hosting (they carry over - // from the the create game dialog). - // Interesting fact: oldFactionsOnly will be carried over correctly if I remove these - // lines. UseStats won't be. I have no idea why. - Int useStats = m_localStagingRoom.getUseStats(); - Bool oldFactionsOnly = m_localStagingRoom.oldFactionsOnly(); - - m_localStagingRoom.reset(); - m_localStagingRoom.enterGame(); - m_localStagingRoom.setSeed(GetTickCount()); - - m_localStagingRoom.setUseStats( useStats ); - m_localStagingRoom.setOldFactionsOnly( oldFactionsOnly ); - - GameSlot newSlot; - UnicodeString uName; - uName.translate(m_localName); - newSlot.setState(SLOT_PLAYER, uName); - - m_localStagingRoom.setLocalIP(m_externalIP); - newSlot.setIP(m_externalIP); - - m_localStagingRoom.setSlot(0,newSlot); - m_localStagingRoom.setLocalName(m_localName); - - TheMapCache->updateCache(); - m_localStagingRoom.setMap(getDefaultMap(TRUE)); - m_localStagingRoom.adjustSlotsForMap(); // close slots that the map can't hold. BGC -} - -void GameSpyInfo::markAsStagingRoomJoiner( Int game ) -{ - m_localStagingRoomID = game; - m_joinedStagingRoom = TRUE; m_isHosting = FALSE; - m_localStagingRoom.reset(); - m_localStagingRoom.enterGame(); - StagingRoomMap::iterator it = m_stagingRooms.find(game); - if (it != m_stagingRooms.end()) - { - GameSpyStagingRoom *info = it->second; - info->cleanUpSlotPointers(); - AsciiString options = GameInfoToAsciiString(info); -#ifdef DEBUG_CRASHING - Bool res = -#endif - ParseAsciiStringToGameInfo(&m_localStagingRoom, options); - DEBUG_ASSERTCRASH(res, ("Could not parse game info \"%s\"", options.str())); - m_localStagingRoom.setInGame(); - m_localStagingRoom.setLocalName(m_localName); - m_localStagingRoom.setExeCRC(info->getExeCRC()); - m_localStagingRoom.setIniCRC(info->getIniCRC()); - m_localStagingRoom.setAllowObservers(info->getAllowObservers()); - m_localStagingRoom.setHasPassword(info->getHasPassword()); - m_localStagingRoom.setGameName(info->getGameName()); - DEBUG_LOG(("Joining game: host is %ls\n", m_localStagingRoom.getConstSlot(0)->getName().str())); - } -} - -void GameSpyInfo::setMOTD( const AsciiString& motd ) -{ - m_rawMotd = motd; -} - -const AsciiString& GameSpyInfo::getMOTD( void ) -{ - return m_rawMotd; -} - -void GameSpyInfo::setConfig( const AsciiString& config ) -{ - m_rawConfig = config; -} - -const AsciiString& GameSpyInfo::getConfig( void ) -{ - return m_rawConfig; -} - -// -------------------------------------------------------------- -void SetUpGameSpy( const char *motdBuffer, const char *configBuffer ) -{ - if (!motdBuffer) - motdBuffer = ""; - if (!configBuffer) - configBuffer = ""; - TearDownGameSpy(); - - AsciiString dir = TheGlobalData->getPath_UserData(); - CreateDirectory(dir.str(), NULL); - dir.format("%sGeneralsOnline", TheGlobalData->getPath_UserData().str()); - CreateDirectory(dir.str(), NULL); - dir.format("%sGeneralsOnline\\Ladders", TheGlobalData->getPath_UserData().str()); - CreateDirectory(dir.str(), NULL); - - TheGameSpyBuddyMessageQueue = GameSpyBuddyMessageQueueInterface::createNewMessageQueue(); - TheGameSpyBuddyMessageQueue->startThread(); - - TheGameSpyPeerMessageQueue = GameSpyPeerMessageQueueInterface::createNewMessageQueue(); - TheGameSpyPeerMessageQueue->startThread(); - - TheGameSpyPSMessageQueue = GameSpyPSMessageQueueInterface::createNewMessageQueue(); - TheGameSpyPSMessageQueue->startThread(); - - /* - TheGameSpyGame = NEW GameSpyStagingRoom; - */ - - TheGameSpyInfo = GameSpyInfoInterface::createNewGameSpyInfoInterface(); - TheGameSpyInfo->setMOTD(motdBuffer); - TheGameSpyInfo->setConfig(configBuffer); - - CustomMatchPreferences pref; - TheGameSpyInfo->setDisallowAsianText(pref.getDisallowAsianText()); - TheGameSpyInfo->setDisallowNonAsianText( pref.getDisallowNonAsianText()); - - - TheGameSpyConfig = GameSpyConfigInterface::create(configBuffer); - - TheLadderList = NEW LadderList; - - ThePinger = PingerInterface::createNewPingerInterface(); - ThePinger->startThreads(); - - TheRankPointValues = NEW RankPoints; -} - -void TearDownGameSpy( void ) -{ - // save off cached stats - if (TheGameSpyInfo && TheGameSpyInfo->getLocalProfileID()) - { -// /* This was done on the score screen, so there is no need to do it now. -// * - PSPlayerStats localPSStats = TheGameSpyPSMessageQueue->findPlayerStatsByID(TheGameSpyInfo->getLocalProfileID()); - if (localPSStats.id != 0) - { - GameSpyMiscPreferences mPref; - mPref.setCachedStats(GameSpyPSMessageQueueInterface::formatPlayerKVPairs(localPSStats).c_str()); - mPref.write(); - } -// */ - } - - // End our threads before we kill off the singletons they reference. No crashy-crash for you! - if (TheGameSpyPSMessageQueue) - TheGameSpyPSMessageQueue->endThread(); - if (TheGameSpyBuddyMessageQueue) - TheGameSpyBuddyMessageQueue->endThread(); - if (TheGameSpyPeerMessageQueue) - TheGameSpyPeerMessageQueue->endThread(); - if (ThePinger) - ThePinger->endThreads(); - - if(TheRankPointValues) - { - delete TheRankPointValues; - TheRankPointValues = NULL; - } - if (TheGameSpyPSMessageQueue) - { - delete TheGameSpyPSMessageQueue; - TheGameSpyPSMessageQueue = NULL; - } - - if (TheGameSpyBuddyMessageQueue) - { - delete TheGameSpyBuddyMessageQueue; - TheGameSpyBuddyMessageQueue = NULL; - } - - if (TheGameSpyPeerMessageQueue) - { - delete TheGameSpyPeerMessageQueue; - TheGameSpyPeerMessageQueue = NULL; - } - - if (TheGameSpyInfo) - { - if (TheGameSpyInfo->getInternalIP()) - { - // we've logged in before. mark us as logging out. - SignalUIInteraction(SHELL_SCRIPT_HOOK_GENERALS_ONLINE_LOGOUT); - } - delete TheGameSpyInfo; - TheGameSpyInfo = NULL; - } - - if (ThePinger) - { - delete ThePinger; - ThePinger = NULL; - } - - if (TheLadderList) - { - delete TheLadderList; - TheLadderList = NULL; - } - - if (TheGameSpyConfig) - { - delete TheGameSpyConfig; - TheGameSpyConfig = NULL; - } - - // make sure the notification box doesn't exist - deleteNotificationBox(); -} - - -void GameSpyInfo::addToIgnoreList( AsciiString nick ) -{ - m_ignoreList.insert(nick); -} - -void GameSpyInfo::removeFromIgnoreList( AsciiString nick ) -{ - m_ignoreList.erase(nick); -} - -Bool GameSpyInfo::isIgnored( AsciiString nick ) -{ - return m_ignoreList.find(nick) != m_ignoreList.end(); -} - -IgnoreList GameSpyInfo::returnIgnoreList( void ) -{ - return m_ignoreList; -} - -void GameSpyInfo::addToSavedIgnoreList( Int profileID, AsciiString nick) -{ - m_savedIgnoreMap[profileID] = nick; - IgnorePreferences pref; - pref.setIgnore(nick, profileID, true); - pref.write(); -} - -void GameSpyInfo::removeFromSavedIgnoreList( Int profileID ) -{ - m_savedIgnoreMap.erase(profileID); - IgnorePreferences pref; - pref.setIgnore(AsciiString::TheEmptyString, profileID, false); - pref.write(); -} - -Bool GameSpyInfo::isSavedIgnored( Int profileID ) -{ - return m_savedIgnoreMap.find(profileID) != m_savedIgnoreMap.end(); -} - -SavedIgnoreMap GameSpyInfo::returnSavedIgnoreList( void ) -{ - return m_savedIgnoreMap; -} - -static Int grabHexInt(const char *s) -{ - char tmp[5] = "0xff"; - tmp[2] = s[0]; - tmp[3] = s[1]; - Int b = strtol(tmp, NULL, 16); - return b; -} - -Int GameSpyInfo::getPingValue( const AsciiString& otherPing ) -{ - if (m_pingString.getLength() != otherPing.getLength()) - { - return TheGameSpyConfig->getPingTimeoutInMs(); - } - - if (m_pingString.getLength() % 2 != 0) - { - return TheGameSpyConfig->getPingTimeoutInMs(); - } - - Int best = 255+255; - const char *myStr = m_pingString.str(); - const char *otherStr = otherPing.str(); - - while (*myStr) - { - Int myVal = grabHexInt(myStr); - Int otherVal = grabHexInt(otherStr); - Int val = myVal + otherVal; - best = (val < best) ? val : best; - myStr += 2; - otherStr += 2; - } - - return best * TheGameSpyConfig->getPingTimeoutInMs() / (255+255); -} - -Bool PlayerInfo::isIgnored( void ) -{ - return (m_profileID)?TheGameSpyInfo->isSavedIgnored(m_profileID):TheGameSpyInfo->isIgnored(m_name); -} - -void GameSpyInfo::loadSavedIgnoreList( void ) -{ - m_savedIgnoreMap.clear(); - IgnorePreferences prefs; - m_savedIgnoreMap = prefs.getIgnores(); -} - -void GameSpyInfo::setDisallowAsianText( Bool val ) -{ - m_disallowAsainText = val; -} - -void GameSpyInfo::setDisallowNonAsianText( Bool val ) -{ - m_disallowNonAsianText = val; -} - -Bool GameSpyInfo::getDisallowAsianText( void ) -{ - return m_disallowAsainText; -} -Bool GameSpyInfo::getDisallowNonAsianText(void ) -{ - return m_disallowNonAsianText; -} - -void GameSpyInfo::setMaxMessagesPerUpdate( Int num ) -{ - m_maxMessagesPerUpdate = num; -} - -Int GameSpyInfo::getMaxMessagesPerUpdate( void ) -{ - return m_maxMessagesPerUpdate; -} - -/**This function is used to force an update of player's gamespy stats with an additional -disconnection. This is used upon starting a new game so that if user disconnects prior -to finishing game, the disconnection stays on the server. If he completes the game, we -remove this extra disconnection inside of populatePlayerInfo() on the ScoreScreen. This -seems like the only secure way to handle this issue since users can abort the process -before we can detect/log disconnections.*/ -void GameSpyInfo::updateAdditionalGameSpyDisconnections(Int count) -{ - if (TheRecorder->isMultiplayer() && TheGameLogic->isInInternetGame() && TheGameSpyGame && TheGameSpyGame->getUseStats()) - { - Int localID = TheGameSpyInfo->getLocalProfileID(); - PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(localID); - - Player *player=ThePlayerList->getLocalPlayer(); - - Int ptIdx; - const PlayerTemplate *myTemplate = player->getPlayerTemplate(); - DEBUG_LOG(("myTemplate = %X(%s)\n", myTemplate, myTemplate->getName().str())); - for (ptIdx = 0; ptIdx < ThePlayerTemplateStore->getPlayerTemplateCount(); ++ptIdx) - { - const PlayerTemplate *nthTemplate = ThePlayerTemplateStore->getNthPlayerTemplate(ptIdx); - DEBUG_LOG(("nthTemplate = %X(%s)\n", nthTemplate, nthTemplate->getName().str())); - if (nthTemplate == myTemplate) - { - break; - } - } - - Bool anyAI = FALSE; - for (Int i=0; igetConstSlot(i); - - if (slot->isAI()) - { - anyAI = TRUE; - } - } - - //Check for cases where we're not tracking stats. - if (anyAI || stats.id == 0 || myTemplate->isObserver() || player->getPlayerType() != PLAYER_HUMAN || player->isPlayerObserver()) - return; - - Int disCons=stats.discons[ptIdx]; - disCons += count; - if (disCons < 0) - { DEBUG_LOG(("updateAdditionalGameSpyDisconnections() - disconnection count below zero\n")); - return; //something is wrong here - } - stats.discons[ptIdx] = disCons; //add an additional disconnection to their stats. - - //Add an additional disconnection to player stats. - PSRequest req; - - req.requestType = PSRequest::PSREQUEST_UPDATEPLAYERSTATS; - req.email = TheGameSpyInfo->getLocalEmail().str(); - req.nick = TheGameSpyInfo->getLocalBaseName().str(); - req.password = TheGameSpyInfo->getLocalPassword().str(); - req.player = stats; - req.addDesync = FALSE; - req.addDiscon = FALSE; - req.lastHouse = ptIdx; - - TheGameSpyPSMessageQueue->addRequest(req); - TheGameSpyPSMessageQueue->trackPlayerStats(stats); - - // force an update of our shtuff - PSResponse newResp; - newResp.responseType = PSResponse::PSRESPONSE_PLAYERSTATS; - newResp.player = stats; - TheGameSpyPSMessageQueue->addResponse(newResp); - - // cache our stuff for easy reading next time - GameSpyMiscPreferences mPref; - mPref.setCachedStats(GameSpyPSMessageQueueInterface::formatPlayerKVPairs(stats).c_str()); - mPref.write(); - } -} diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/StagingRoomGameInfo.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/StagingRoomGameInfo.cpp deleted file mode 100644 index df34ea870e4..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/StagingRoomGameInfo.cpp +++ /dev/null @@ -1,896 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: StagingRoomGameInfo.cpp ////////////////////////////////////////////////////// -// Generals GameSpy GameInfo-related code -// Author: Matthew D. Campbell, July 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameState.h" -#include "Common/Player.h" -#include "Common/PlayerList.h" -#include "Common/PlayerTemplate.h" -#include "Common/RandomValue.h" -#include "Common/ScoreKeeper.h" -#include "GameClient/GameText.h" -#include "GameClient/MapUtil.h" -#include "GameClient/Shell.h" -#include "GameLogic/GameLogic.h" -#include "GameLogic/VictoryConditions.h" -#include "GameNetwork/FileTransfer.h" -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpy/ThreadUtils.h" -#include "GameNetwork/GameSpyOverlay.h" -#include "GameNetwork/NAT.h" -#include "GameNetwork/NetworkInterface.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -// GameSpyGameSlot ------------------------------------------- - -GameSpyGameSlot::GameSpyGameSlot() -{ - GameSlot(); - m_gameSpyLogin.clear(); - m_gameSpyLocale.clear(); - m_profileID = 0; - m_wins = 0; - m_losses = 0; - m_rankPoints = 0; - m_favoriteSide = 0; - m_pingInt = 0; - // Added By Sadullah Nader - // Initializations missing and needed - m_profileID = 0; - m_pingStr.clear(); -} - -// Helper Functions ---------------------------------------- -/* -** Function definitions for the MIB-II entry points. -*/ - -BOOL (__stdcall *SnmpExtensionInitPtr)(IN DWORD dwUpTimeReference, OUT HANDLE *phSubagentTrapEvent, OUT AsnObjectIdentifier *pFirstSupportedRegion); -BOOL (__stdcall *SnmpExtensionQueryPtr)(IN BYTE bPduType, IN OUT RFC1157VarBindList *pVarBindList, OUT AsnInteger32 *pErrorStatus, OUT AsnInteger32 *pErrorIndex); -LPVOID (__stdcall *SnmpUtilMemAllocPtr)(IN DWORD bytes); -VOID (__stdcall *SnmpUtilMemFreePtr)(IN LPVOID pMem); - -typedef struct tConnInfoStruct { - unsigned int State; - unsigned long LocalIP; - unsigned short LocalPort; - unsigned long RemoteIP; - unsigned short RemotePort; -} ConnInfoStruct; - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) -#endif - -/*********************************************************************************************** - * Get_Local_Chat_Connection_Address -- Which address are we using to talk to the chat server? * - * * - * * - * * - * INPUT: Ptr to address to return local address * * - * * - * OUTPUT: True if success * - * * - * WARNINGS: None * - * * - * HISTORY: * - * 10/27/00 3:24PM ST : Created * - *=============================================================================================*/ -Bool GetLocalChatConnectionAddress(AsciiString serverName, UnsignedShort serverPort, UnsignedInt& localIP) -{ - //return false; - /* - ** Local defines. - */ - enum { - CLOSED = 1, - LISTENING, - SYN_SENT, - SEN_RECEIVED, - ESTABLISHED, - FIN_WAIT, - FIN_WAIT2, - CLOSE_WAIT, - LAST_ACK, - CLOSING, - TIME_WAIT, - DELETE_TCB - }; - - enum { - tcpConnState = 1, - tcpConnLocalAddress, - tcpConnLocalPort, - tcpConnRemAddress, - tcpConnRemPort - }; - - - /* - ** Locals. - */ - unsigned char serverAddress[4]; - unsigned char remoteAddress[4]; - HANDLE trap_handle; - AsnObjectIdentifier first_supported_region; - std::vector connectionVector; - int last_field; - int index; - AsnInteger error_status; - AsnInteger error_index; - int conn_entry_type_index; - int conn_entry_type; - Bool found; - - /* - ** Statics. - */ - static char _conn_state[][32] = { - "?", - "CLOSED", - "LISTENING", - "SYN_SENT", - "SEN_RECEIVED", - "ESTABLISHED", - "FIN_WAIT", - "FIN_WAIT2", - "CLOSE_WAIT", - "LAST_ACK", - "CLOSING", - "TIME_WAIT", - "DELETE_TCB" - }; - - DEBUG_LOG(("Finding local address used to talk to the chat server\n")); - DEBUG_LOG(("Current chat server name is %s\n", serverName.str())); - DEBUG_LOG(("Chat server port is %d\n", serverPort)); - - /* - ** Get the address of the chat server. - */ - DEBUG_LOG( ("About to call gethostbyname\n")); - struct hostent *host_info = gethostbyname(serverName.str()); - - if (!host_info) { - DEBUG_LOG( ("gethostbyname failed! Error code %d\n", WSAGetLastError())); - return(false); - } - - memcpy(serverAddress, &host_info->h_addr_list[0][0], 4); - unsigned long temp = *((unsigned long*)(&serverAddress[0])); - temp = ntohl(temp); - *((unsigned long*)(&serverAddress[0])) = temp; - - DEBUG_LOG(("Host address is %d.%d.%d.%d\n", serverAddress[3], serverAddress[2], serverAddress[1], serverAddress[0])); - - /* - ** Load the MIB-II SNMP DLL. - */ - DEBUG_LOG(("About to load INETMIB1.DLL\n")); - - HINSTANCE mib_ii_dll = LoadLibrary("inetmib1.dll"); - if (mib_ii_dll == NULL) { - DEBUG_LOG(("Failed to load INETMIB1.DLL\n")); - return(false); - } - - DEBUG_LOG(("About to load SNMPAPI.DLL\n")); - - HINSTANCE snmpapi_dll = LoadLibrary("snmpapi.dll"); - if (snmpapi_dll == NULL) { - DEBUG_LOG(("Failed to load SNMPAPI.DLL\n")); - FreeLibrary(mib_ii_dll); - return(false); - } - - /* - ** Get the function pointers into the .dll - */ - SnmpExtensionInitPtr = (int (__stdcall *)(unsigned long,void ** ,AsnObjectIdentifier *)) GetProcAddress(mib_ii_dll, "SnmpExtensionInit"); - SnmpExtensionQueryPtr = (int (__stdcall *)(unsigned char,SnmpVarBindList *,long *,long *)) GetProcAddress(mib_ii_dll, "SnmpExtensionQuery"); - SnmpUtilMemAllocPtr = (void *(__stdcall *)(unsigned long)) GetProcAddress(snmpapi_dll, "SnmpUtilMemAlloc"); - SnmpUtilMemFreePtr = (void (__stdcall *)(void *)) GetProcAddress(snmpapi_dll, "SnmpUtilMemFree"); - if (SnmpExtensionInitPtr == NULL || SnmpExtensionQueryPtr == NULL || SnmpUtilMemAllocPtr == NULL || SnmpUtilMemFreePtr == NULL) { - DEBUG_LOG(("Failed to get proc addresses for linked functions\n")); - FreeLibrary(snmpapi_dll); - FreeLibrary(mib_ii_dll); - return(false); - } - - - RFC1157VarBindList *bind_list_ptr = (RFC1157VarBindList *) SnmpUtilMemAllocPtr(sizeof(RFC1157VarBindList)); - RFC1157VarBind *bind_ptr = (RFC1157VarBind *) SnmpUtilMemAllocPtr(sizeof(RFC1157VarBind)); - - /* - ** OK, here we go. Try to initialise the .dll - */ - DEBUG_LOG(("About to init INETMIB1.DLL\n")); - int ok = SnmpExtensionInitPtr(GetCurrentTime(), &trap_handle, &first_supported_region); - - if (!ok) { - /* - ** Aw crap. - */ - DEBUG_LOG(("Failed to init the .dll\n")); - SnmpUtilMemFreePtr(bind_list_ptr); - SnmpUtilMemFreePtr(bind_ptr); - FreeLibrary(snmpapi_dll); - FreeLibrary(mib_ii_dll); - return(false); - } - - /* - ** Name of mib_ii object we want to query. See RFC 1213. - ** - ** iso.org.dod.internet.mgmt.mib-2.tcp.tcpConnTable.TcpConnEntry.tcpConnState - ** 1 3 6 1 2 1 6 13 1 1 - */ - unsigned int mib_ii_name[] = {1,3,6,1,2,1,6,13,1,1}; - unsigned int *mib_ii_name_ptr = (unsigned int *) SnmpUtilMemAllocPtr(sizeof(mib_ii_name)); - memcpy(mib_ii_name_ptr, mib_ii_name, sizeof(mib_ii_name)); - - /* - ** Get the index of the conn entry data. - */ - conn_entry_type_index = ARRAY_SIZE(mib_ii_name) - 1; - - /* - ** Set up the bind list. - */ - bind_ptr->name.idLength = ARRAY_SIZE(mib_ii_name); - bind_ptr->name.ids = mib_ii_name; - bind_list_ptr->list = bind_ptr; - bind_list_ptr->len = 1; - - - /* - ** We start with the tcpConnLocalAddress field. - */ - last_field = 1; - - /* - ** First connection. - */ - index = 0; - - /* - ** Suck out that tcp connection info.... - */ - while (true) { - - if (!SnmpExtensionQueryPtr(SNMP_PDU_GETNEXT, bind_list_ptr, &error_status, &error_index)) { - //if (!SnmpExtensionQueryPtr(ASN_RFC1157_GETNEXTREQUEST, bind_list_ptr, &error_status, &error_index)) { - DEBUG_LOG(("SnmpExtensionQuery returned false\n")); - SnmpUtilMemFreePtr(bind_list_ptr); - SnmpUtilMemFreePtr(bind_ptr); - FreeLibrary(snmpapi_dll); - FreeLibrary(mib_ii_dll); - return(false); - } - - /* - ** If this is something new we aren't looking for then we are done. - */ - if (bind_ptr->name.idLength < ARRAY_SIZE(mib_ii_name)) { - break; - } - - /* - ** Get the type of info we are looking at. See RFC1213. - ** - ** 1 = tcpConnState - ** 2 = tcpConnLocalAddress - ** 3 = tcpConnLocalPort - ** 4 = tcpConnRemAddress - ** 5 = tcpConnRemPort - ** - ** tcpConnState is one of the following... - ** - ** 1 closed - ** 2 listen - ** 3 synSent - ** 4 synReceived - ** 5 established - ** 6 finWait1 - ** 7 finWait2 - ** 8 closeWait - ** 9 lastAck - ** 10 closing - ** 11 timeWait - ** 12 deleteTCB - */ - conn_entry_type = bind_ptr->name.ids[conn_entry_type_index]; - - if (last_field != conn_entry_type) { - index = 0; - last_field = conn_entry_type; - } - - switch (conn_entry_type) { - - /* - ** 1. First field in the entry. Need to create a new connection info struct - ** here to store this connection in. - */ - case tcpConnState: - { - ConnInfoStruct new_conn; - new_conn.State = bind_ptr->value.asnValue.number; - connectionVector.push_back(new_conn); - break; - } - - /* - ** 2. Local address field. - */ - case tcpConnLocalAddress: - DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index")); - connectionVector[index].LocalIP = *((unsigned long*)bind_ptr->value.asnValue.address.stream); - index++; - break; - - /* - ** 3. Local port field. - */ - case tcpConnLocalPort: - DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index")); - connectionVector[index].LocalPort = bind_ptr->value.asnValue.number; - //connectionVector[index]->LocalPort = ntohs(connectionVector[index]->LocalPort); - index++; - break; - - /* - ** 4. Remote address field. - */ - case tcpConnRemAddress: - DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index")); - connectionVector[index].RemoteIP = *((unsigned long*)bind_ptr->value.asnValue.address.stream); - index++; - break; - - /* - ** 5. Remote port field. - */ - case tcpConnRemPort: - DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index")); - connectionVector[index].RemotePort = bind_ptr->value.asnValue.number; - //connectionVector[index]->RemotePort = ntohs(connectionVector[index]->RemotePort); - index++; - break; - } - } - - SnmpUtilMemFreePtr(bind_list_ptr); - SnmpUtilMemFreePtr(bind_ptr); - SnmpUtilMemFreePtr(mib_ii_name_ptr); - - DEBUG_LOG(("Got %d connections in list, parsing...\n", connectionVector.size())); - - /* - ** Right, we got the lot. Lets see if any of them have the same address as the chat - ** server we think we are talking to. - */ - found = false; - for (Int i=0; igetPingValue(pingStr); -} - -// GameSpyStagingRoom ---------------------------------------- - -GameSpyStagingRoom::GameSpyStagingRoom() -{ - cleanUpSlotPointers(); - - setLocalIP(0); - m_transport = NULL; - - m_localName = "localhost"; - - m_ladderIP.clear(); - m_ladderPort = 0; -} - -void GameSpyStagingRoom::cleanUpSlotPointers( void ) -{ - for (Int i = 0; i< MAX_SLOTS; ++i) - setSlotPointer(i, &m_GameSpySlot[i]); -} - -GameSpyGameSlot * GameSpyStagingRoom::getGameSpySlot( Int index ) -{ - GameSlot *slot = getSlot(index); - DEBUG_ASSERTCRASH(slot && (slot == &(m_GameSpySlot[index])), ("Bad game slot pointer\n")); - return (GameSpyGameSlot *)slot; -} - -void GameSpyStagingRoom::init( void ) -{ - GameInfo::init(); -} - -void GameSpyStagingRoom::setPingString( AsciiString pingStr ) -{ - m_pingStr = pingStr; - m_pingInt = TheGameSpyInfo->getPingValue(pingStr); -} - -Bool GameSpyStagingRoom::amIHost( void ) const -{ - DEBUG_ASSERTCRASH(m_inGame, ("Looking for game slot while not in game")); - if (!m_inGame) - return false; - - return getConstSlot(0)->isPlayer(m_localName); -} - -void GameSpyStagingRoom::resetAccepted( void ) -{ - GameInfo::resetAccepted(); - - if (amIHost()) - { - /* - peerStateChanged(TheGameSpyChat->getPeer()); - m_hasBeenQueried = false; - DEBUG_LOG(("resetAccepted() called peerStateChange()\n")); - */ - } -} - -Int GameSpyStagingRoom::getLocalSlotNum( void ) const -{ - DEBUG_ASSERTCRASH(m_inGame, ("Looking for local game slot while not in game")); - if (!m_inGame) - return -1; - - AsciiString localName = TheGameSpyInfo->getLocalName(); - - for (Int i=0; iisPlayer(localName)) - return i; - } - return -1; -} - -void GameSpyStagingRoom::startGame(Int gameID) -{ - DEBUG_ASSERTCRASH(m_inGame, ("Starting a game while not in game")); - DEBUG_LOG(("GameSpyStagingRoom::startGame - game id = %d\n", gameID)); - DEBUG_ASSERTCRASH(m_transport == NULL, ("m_transport is not NULL when it should be")); - DEBUG_ASSERTCRASH(TheNAT == NULL, ("TheNAT is not NULL when it should be")); - - UnsignedInt localIP = TheGameSpyInfo->getInternalIP(); - setLocalIP(localIP); - - if (TheNAT != NULL) { - delete TheNAT; - TheNAT = NULL; - } - - // fill in GS-specific info - Int numHumans = 0; - for (Int i=0; igetLocalProfileID()); // hehe - we know our own. the rest, they'll tell us. - } - else - { - PlayerInfoMap *pInfoMap = TheGameSpyInfo->getPlayerInfoMap(); - PlayerInfoMap::iterator it = pInfoMap->find(gsName); - if (it != pInfoMap->end()) - { - m_GameSpySlot[i].setProfileID(it->second.m_profileID); - m_GameSpySlot[i].setLocale(it->second.m_locale); - m_GameSpySlot[i].setSlotRankPoints(it->second.m_rankPoints); - m_GameSpySlot[i].setFavoriteSide(it->second.m_side); - } - else - { - DEBUG_CRASH(("No player info for %s", gsName.str())); - } - } - } - } - -//#if defined(_DEBUG) || defined(_INTERNAL) - if (numHumans < 2) - { - launchGame(); - if (TheGameSpyInfo) - TheGameSpyInfo->leaveStagingRoom(); - } - else -//#endif defined(_DEBUG) || defined(_INTERNAL) - { - TheNAT = NEW NAT(); - TheNAT->attachSlotList(m_slot, getLocalSlotNum(), m_localIP); - TheNAT->establishConnectionPaths(); - } -} - -AsciiString GameSpyStagingRoom::generateGameSpyGameResultsPacket( void ) -{ - Int i; - Int endFrame = TheVictoryConditions->getEndFrame(); - Int localSlotNum = getLocalSlotNum(); - Int winningTeam = -1; - Int numHumans = 0; - Int numPlayers = 0; - Int numAIs = 0; - Int numTeamsAtGameEnd = 0; - Int lastTeamAtGameEnd = -1; - for (i=0; ifindPlayerWithNameKey(NAMEKEY(playerName)); - if (p) - { - ++numHumans; - if (TheVictoryConditions->hasAchievedVictory(p)) - { - winningTeam = getSlot(i)->getTeamNumber(); - } - - // check if he lasted - GameSlot *slot = getSlot(i); - if (!slot->disconnected()) - { - if (slot->getTeamNumber() != lastTeamAtGameEnd || numTeamsAtGameEnd == 0) - { - lastTeamAtGameEnd = slot->getTeamNumber(); - ++numTeamsAtGameEnd; - } - } - } - else - { - if (m_GameSpySlot[i].isAI()) - ++numAIs; - } - } - numPlayers = numHumans + numAIs; - - AsciiString mapName; - for (i=0; ifindPlayerWithNameKey(NAMEKEY(playerName)); - if (p) - { - GameSpyGameSlot *slot = &(m_GameSpySlot[i]); - AsciiString playerName = (slot->isHuman())?slot->getLoginName():"AIPlayer"; - Int gsPlayerID = slot->getProfileID(); - Bool disconnected = slot->disconnected(); - - AsciiString result = "loss"; - if (disconnected) - result = "discon"; - else if (TheNetwork->sawCRCMismatch()) - result = "desync"; - else if (TheVictoryConditions->hasAchievedVictory(p)) - result = "win"; - - AsciiString side = p->getPlayerTemplate()->getSide(); - if (side == "America") - side = "USA"; //conform to GameSpy - - AsciiString playerStr; - playerStr.format("\\player_%d\\%s\\pid_%d\\%d\\team_%d\\%d\\result_%d\\%s\\side_%d\\%s", - playerID, playerName.str(), playerID, gsPlayerID, playerID, slot->getTeamNumber(), - playerID, result.str(), playerID, side.str()); - results.concat(playerStr); - - ++playerID; - } - } - - return results; -} - -AsciiString GameSpyStagingRoom::generateLadderGameResultsPacket( void ) -{ - Int i; - Int endFrame = TheVictoryConditions->getEndFrame(); - Int localSlotNum = getLocalSlotNum(); - Bool sawGameEnd = (endFrame > 0); - Int winningTeam = -1; - Int numPlayers = 0; - Int numTeamsAtGameEnd = 0; - Int lastTeamAtGameEnd = -1; - Player* p[MAX_SLOTS]; - for (i=0; ifindPlayerWithNameKey(NAMEKEY(playerName)); - if (p[i]) - { - ++numPlayers; - if (TheVictoryConditions->hasAchievedVictory(p[i])) - { - winningTeam = getSlot(i)->getTeamNumber(); - } - - // check if he lasted - GameSlot *slot = getSlot(i); - if (!slot->disconnected()) - { - if (slot->getTeamNumber() != lastTeamAtGameEnd || numTeamsAtGameEnd == 0) - { - lastTeamAtGameEnd = slot->getTeamNumber(); - ++numTeamsAtGameEnd; - } - } - } - } - - AsciiString results; - results.format("seed=%d,slotNum=%d,sawDesync=%d,sawGameEnd=%d,winningTeam=%d,disconEnd=%d,duration=%d,numPlayers=%d,isQM=%d,map=%s", - getSeed(), localSlotNum, TheNetwork->sawCRCMismatch(), sawGameEnd, winningTeam, (numTeamsAtGameEnd < 2), - endFrame, numPlayers, m_isQM, TheGameState->realMapPathToPortableMapPath(getMap()).str()); - - AsciiString tempStr; - tempStr.format("ladderIP=%s,ladderPort=%d", getLadderIP().str(), getLadderPort()); - results.concat(tempStr); - - Int playerID = 0; - for (i=0; igetScoreKeeper(); - AsciiString playerName = slot->getLoginName(); - Int gsPlayerID = slot->getProfileID(); - PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(gsPlayerID); - Int fps = TheNetwork->getAverageFPS(); - Int unitsKilled = keeper->getTotalUnitsDestroyed(); - Int unitsLost = keeper->getTotalUnitsLost(); - Int unitsBuilt = keeper->getTotalUnitsBuilt(); - Int buildingsKilled = keeper->getTotalBuildingsDestroyed(); - Int buildingsLost = keeper->getTotalBuildingsLost(); - Int buildingsBuilt = keeper->getTotalBuildingsBuilt(); - Int earnings = keeper->getTotalMoneyEarned(); - Int techCaptured = keeper->getTotalTechBuildingsCaptured(); - Bool disconnected = slot->disconnected(); - - AsciiString playerStr; - playerStr.format(",player%d=%s,playerID%d=%d,locale%d=%d", - playerID, playerName.str(), playerID, gsPlayerID, playerID, stats.locale); - results.concat(playerStr); - playerStr.format(",unitsKilled%d=%d,unitsLost%d=%d,unitsBuilt%d=%d", - playerID, unitsKilled, playerID, unitsLost, playerID, unitsBuilt); - results.concat(playerStr); - playerStr.format(",buildingsKilled%d=%d,buildingsLost%d=%d,buildingsBuilt%d=%d", - playerID, buildingsKilled, playerID, buildingsLost, playerID, buildingsBuilt); - results.concat(playerStr); - playerStr.format(",fps%d=%d,cash%d=%d,capturedTech%d=%d,discon%d=%d,side%d=%s", - playerID, fps, playerID, earnings, playerID, techCaptured, playerID, disconnected, playerID, p[i]->getPlayerTemplate()->getSide().str()); - results.concat(playerStr); - - ++playerID; - } - } - - // Add a trailing size value (so the server can ensure it got the entire packet) - results.concat(",size="); - int resultsLen = results.getLength()+10; - AsciiString tail; - tail.format("%10.10d", resultsLen); - results.concat(tail); - - return results; -} - -void GameSpyStagingRoom::launchGame( void ) -{ - setGameInProgress(TRUE); - - for (Int i=0; iisHuman()) - { - if (TheGameSpyInfo->didPlayerPreorder(slot->getProfileID())) - markPlayerAsPreorder(i); - } - } - - // Set up the game network - AsciiString user; - AsciiString userList; - DEBUG_ASSERTCRASH(TheNetwork == NULL, ("For some reason TheNetwork isn't NULL at the start of this game. Better look into that.")); - - if (TheNetwork != NULL) { - delete TheNetwork; - TheNetwork = NULL; - } - - // Time to initialize TheNetwork for this game. - TheNetwork = NetworkInterface::createNetwork(); - TheNetwork->init(); - - TheNetwork->setLocalAddress(getLocalIP(), (TheNAT)?TheNAT->getSlotPort(getLocalSlotNum()):8888); - if (TheNAT) - TheNetwork->attachTransport(TheNAT->getTransport()); - else - TheNetwork->initTransport(); - - TheNetwork->parseUserList(this); - - - if (TheGameLogic->isInGame()) { - TheGameLogic->clearGameData(); - } - - Bool filesOk = DoAnyMapTransfers(this); - - // see if we really have the map. if not, back out. - TheMapCache->updateCache(); - if (!filesOk || TheMapCache->findMap(getMap()) == NULL) - { - DEBUG_LOG(("After transfer, we didn't really have the map. Bailing...\n")); - if (TheNetwork != NULL) { - delete TheNetwork; - TheNetwork = NULL; - } - GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:CouldNotTransferMap")); - - void PopBackToLobby( void ); - PopBackToLobby(); - return; - } - - - // shutdown the top, but do not pop it off the stack -// TheShell->hideShell(); - // setup the Global Data with the Map and Seed - TheWritableGlobalData->m_pendingFile = TheGameSpyGame->getMap(); - - // send a message to the logic for a new game - GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_NEW_GAME ); - msg->appendIntegerArgument(GAME_INTERNET); - - TheWritableGlobalData->m_useFpsLimit = false; - - // Set the random seed - InitGameLogicRandom( getSeed() ); - DEBUG_LOG(("InitGameLogicRandom( %d )\n", getSeed())); - - // mark us as "Loading" in the buddy list - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_SETSTATUS; - req.arg.status.status = GP_PLAYING; - strcpy(req.arg.status.statusString, "Loading"); - sprintf(req.arg.status.locationString, "%s", WideCharStringToMultiByte(TheGameSpyGame->getGameName().str()).c_str()); - TheGameSpyBuddyMessageQueue->addRequest(req); - - if (TheNAT != NULL) { - delete TheNAT; - TheNAT = NULL; - } -} - -void GameSpyStagingRoom::reset(void) -{ -#ifdef DEBUG_LOGGING - if (this == TheGameSpyGame) - { - WindowLayout *theLayout = TheShell->findScreenByFilename("Menus/GameSpyGameOptionsMenu.wnd"); - if (theLayout) - { - DEBUG_LOG(("Resetting TheGameSpyGame on the game options menu!\n")); - } - } -#endif - GameInfo::reset(); -} diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/BuddyThread.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/BuddyThread.cpp deleted file mode 100644 index 3fbec0117c0..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/BuddyThread.cpp +++ /dev/null @@ -1,681 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: BuddyThread.cpp ////////////////////////////////////////////////////// -// GameSpy Presence & Messaging (Buddy) thread -// This thread communicates with GameSpy's buddy server -// and talks through a message queue with the rest of -// the game. -// Author: Matthew D. Campbell, June 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpy/ThreadUtils.h" - -#include "Common/StackDump.h" - -#include "mutex.h" -#include "thread.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -//------------------------------------------------------------------------- - -typedef std::queue RequestQueue; -typedef std::queue ResponseQueue; -class BuddyThreadClass; - -class GameSpyBuddyMessageQueue : public GameSpyBuddyMessageQueueInterface -{ -public: - virtual ~GameSpyBuddyMessageQueue(); - GameSpyBuddyMessageQueue(); - virtual void startThread( void ); - virtual void endThread( void ); - virtual Bool isThreadRunning( void ); - virtual Bool isConnected( void ); - virtual Bool isConnecting( void ); - - virtual void addRequest( const BuddyRequest& req ); - virtual Bool getRequest( BuddyRequest& req ); - - virtual void addResponse( const BuddyResponse& resp ); - virtual Bool getResponse( BuddyResponse& resp ); - - virtual GPProfile getLocalProfileID( void ); - - BuddyThreadClass* getThread( void ); - -private: - MutexClass m_requestMutex; - MutexClass m_responseMutex; - RequestQueue m_requests; - ResponseQueue m_responses; - BuddyThreadClass *m_thread; -}; - -GameSpyBuddyMessageQueueInterface* GameSpyBuddyMessageQueueInterface::createNewMessageQueue( void ) -{ - return NEW GameSpyBuddyMessageQueue; -} - -GameSpyBuddyMessageQueueInterface *TheGameSpyBuddyMessageQueue; -#define MESSAGE_QUEUE ((GameSpyBuddyMessageQueue *)TheGameSpyBuddyMessageQueue) - -//------------------------------------------------------------------------- - -class BuddyThreadClass : public ThreadClass -{ - -public: - BuddyThreadClass() : ThreadClass() { m_isNewAccount = m_isdeleting = m_isConnecting = m_isConnected = false; m_profileID = 0; m_lastErrorCode = 0; } - - void Thread_Function(); - - void errorCallback( GPConnection *con, GPErrorArg *arg ); - void messageCallback( GPConnection *con, GPRecvBuddyMessageArg *arg ); - void connectCallback( GPConnection *con, GPConnectResponseArg *arg ); - void requestCallback( GPConnection *con, GPRecvBuddyRequestArg *arg ); - void statusCallback( GPConnection *con, GPRecvBuddyStatusArg *arg ); - - Bool isConnecting( void ) { return m_isConnecting; } - Bool isConnected( void ) { return m_isConnected; } - - GPProfile getLocalProfileID( void ) { return m_profileID; } - -private: - Bool m_isNewAccount; - Bool m_isConnecting; - Bool m_isConnected; - GPProfile m_profileID; - Int m_lastErrorCode; - Bool m_isdeleting; - std::string m_nick, m_email, m_pass; -}; - -static enum CallbackType -{ - CALLBACK_CONNECT, - CALLBACK_ERROR, - CALLBACK_RECVMESSAGE, - CALLBACK_RECVREQUEST, - CALLBACK_RECVSTATUS, - CALLBACK_MAX -}; - -void callbackWrapper( GPConnection *con, void *arg, void *param ) -{ - CallbackType info = (CallbackType)(Int)param; - BuddyThreadClass *thread = MESSAGE_QUEUE->getThread() ? MESSAGE_QUEUE->getThread() : NULL /*(TheGameSpyBuddyMessageQueue)?TheGameSpyBuddyMessageQueue->getThread():NULL*/; - if (!thread) - return; - - switch (info) - { - case CALLBACK_CONNECT: - thread->connectCallback( con, (GPConnectResponseArg *)arg ); - break; - case CALLBACK_ERROR: - thread->errorCallback( con, (GPErrorArg *)arg ); - break; - case CALLBACK_RECVMESSAGE: - thread->messageCallback( con, (GPRecvBuddyMessageArg *)arg ); - break; - case CALLBACK_RECVREQUEST: - thread->requestCallback( con, (GPRecvBuddyRequestArg *)arg ); - break; - case CALLBACK_RECVSTATUS: - thread->statusCallback( con, (GPRecvBuddyStatusArg *)arg ); - break; - } -} - -//------------------------------------------------------------------------- - -GameSpyBuddyMessageQueue::GameSpyBuddyMessageQueue() -{ - m_thread = NULL; -} - -GameSpyBuddyMessageQueue::~GameSpyBuddyMessageQueue() -{ - endThread(); -} - -void GameSpyBuddyMessageQueue::startThread( void ) -{ - if (!m_thread) - { - m_thread = NEW BuddyThreadClass; - m_thread->Execute(); - } - else - { - if (!m_thread->Is_Running()) - { - m_thread->Execute(); - } - } -} - -void GameSpyBuddyMessageQueue::endThread( void ) -{ - if (m_thread) - delete m_thread; - m_thread = NULL; -} - -Bool GameSpyBuddyMessageQueue::isThreadRunning( void ) -{ - return (m_thread) ? m_thread->Is_Running() : false; -} - -Bool GameSpyBuddyMessageQueue::isConnected( void ) -{ - return (m_thread) ? m_thread->isConnected() : false; -} - -Bool GameSpyBuddyMessageQueue::isConnecting( void ) -{ - return (m_thread) ? m_thread->isConnecting() : false; -} - -void GameSpyBuddyMessageQueue::addRequest( const BuddyRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex); - if (m.Failed()) - return; - - m_requests.push(req); -} - -Bool GameSpyBuddyMessageQueue::getRequest( BuddyRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex, 0); - if (m.Failed()) - return false; - - if (m_requests.empty()) - return false; - req = m_requests.front(); - m_requests.pop(); - return true; -} - -void GameSpyBuddyMessageQueue::addResponse( const BuddyResponse& resp ) -{ - MutexClass::LockClass m(m_responseMutex); - if (m.Failed()) - return; - - m_responses.push(resp); -} - -Bool GameSpyBuddyMessageQueue::getResponse( BuddyResponse& resp ) -{ - MutexClass::LockClass m(m_responseMutex, 0); - if (m.Failed()) - return false; - - if (m_responses.empty()) - return false; - resp = m_responses.front(); - m_responses.pop(); - return true; -} - -BuddyThreadClass* GameSpyBuddyMessageQueue::getThread( void ) -{ - return m_thread; -} - -GPProfile GameSpyBuddyMessageQueue::getLocalProfileID( void ) -{ - return (m_thread) ? m_thread->getLocalProfileID() : 0; -} - -//------------------------------------------------------------------------- - -void BuddyThreadClass::Thread_Function() -{ - try { - _set_se_translator( DumpExceptionInfo ); // Hook that allows stack trace. - GPConnection gpCon; - GPConnection *con = &gpCon; - gpInitialize( con, 823, 0, GP_PARTNERID_GAMESPY ); - m_isConnected = m_isConnecting = false; - - gpSetCallback( con, GP_ERROR, callbackWrapper, (void *)CALLBACK_ERROR ); - gpSetCallback( con, GP_RECV_BUDDY_MESSAGE, callbackWrapper, (void *)CALLBACK_RECVMESSAGE ); - gpSetCallback( con, GP_RECV_BUDDY_REQUEST, callbackWrapper, (void *)CALLBACK_RECVREQUEST ); - gpSetCallback( con, GP_RECV_BUDDY_STATUS, callbackWrapper, (void *)CALLBACK_RECVSTATUS ); - - GPEnum lastStatus = GP_OFFLINE; - std::string lastStatusString; - - BuddyRequest incomingRequest; - while ( running ) - { - // deal with requests - if (TheGameSpyBuddyMessageQueue->getRequest(incomingRequest)) - { - switch (incomingRequest.buddyRequestType) - { - case BuddyRequest::BUDDYREQUEST_LOGIN: - m_isConnecting = true; - m_nick = incomingRequest.arg.login.nick; - m_email = incomingRequest.arg.login.email; - m_pass = incomingRequest.arg.login.password; - m_isConnected = (gpConnect( con, incomingRequest.arg.login.nick, incomingRequest.arg.login.email, - incomingRequest.arg.login.password, (incomingRequest.arg.login.hasFirewall)?GP_FIREWALL:GP_NO_FIREWALL, - GP_BLOCKING, callbackWrapper, (void *)CALLBACK_CONNECT ) == GP_NO_ERROR); - m_isConnecting = false; - break; - - case BuddyRequest::BUDDYREQUEST_RELOGIN: - m_isConnecting = true; - m_isConnected = (gpConnect( con, m_nick.c_str(), m_email.c_str(), m_pass.c_str(), GP_FIREWALL, - GP_BLOCKING, callbackWrapper, (void *)CALLBACK_CONNECT ) == GP_NO_ERROR); - m_isConnecting = false; - break; - case BuddyRequest::BUDDYREQUEST_DELETEACCT: - m_isdeleting = true; - // TheSuperHackers @tweak OmniBlade API was updated since Generals released to require a callback. Passing -1 will make our wrapper ignore this. - gpDeleteProfile( con, callbackWrapper, (void *)(-1) ); - break; - case BuddyRequest::BUDDYREQUEST_LOGOUT: - m_isConnecting = m_isConnected = false; - gpDisconnect( con ); - break; - case BuddyRequest::BUDDYREQUEST_MESSAGE: - { - std::string s = WideCharStringToMultiByte( incomingRequest.arg.message.text ); - DEBUG_LOG(("Sending a buddy message to %d [%s]\n", incomingRequest.arg.message.recipient, s.c_str())); - gpSendBuddyMessage( con, incomingRequest.arg.message.recipient, s.c_str() ); - } - break; - case BuddyRequest::BUDDYREQUEST_LOGINNEW: - { - m_isConnecting = true; - m_nick = incomingRequest.arg.login.nick; - m_email = incomingRequest.arg.login.email; - m_pass = incomingRequest.arg.login.password; - m_isNewAccount = TRUE; - // TheSuperHackers @tweak OmniBlade API was updated since Generals release to require uniquenick which is the same as nick and cdkey is an empty string here. - m_isConnected = (gpConnectNewUser( con, incomingRequest.arg.login.nick, incomingRequest.arg.login.nick, incomingRequest.arg.login.email, - incomingRequest.arg.login.password, "", (incomingRequest.arg.login.hasFirewall)?GP_FIREWALL:GP_NO_FIREWALL, - GP_BLOCKING, callbackWrapper, (void *)CALLBACK_CONNECT ) == GP_NO_ERROR); - if (m_isNewAccount) // if we didn't re-login - { - gpSetInfoMask( con, GP_MASK_NONE ); // don't share info - } - m_isConnecting = false; - } - break; - case BuddyRequest::BUDDYREQUEST_ADDBUDDY: - { - std::string s = WideCharStringToMultiByte( incomingRequest.arg.addbuddy.text ); - gpSendBuddyRequest( con, incomingRequest.arg.addbuddy.id, s.c_str() ); - } - break; - case BuddyRequest::BUDDYREQUEST_DELBUDDY: - { - gpDeleteBuddy( con, incomingRequest.arg.profile.id ); - } - break; - case BuddyRequest::BUDDYREQUEST_OKADD: - { - gpAuthBuddyRequest( con, incomingRequest.arg.profile.id ); - } - break; - case BuddyRequest::BUDDYREQUEST_DENYADD: - { - gpDenyBuddyRequest( con, incomingRequest.arg.profile.id ); - } - case BuddyRequest::BUDDYREQUEST_SETSTATUS: - { - //don't blast our 'Loading' status with 'Online'. - if (lastStatus == GP_PLAYING && lastStatusString == "Loading" && incomingRequest.arg.status.status == GP_ONLINE) - break; - - DEBUG_LOG(("BUDDYREQUEST_SETSTATUS: status is now %d:%s/%s\n", - incomingRequest.arg.status.status, incomingRequest.arg.status.statusString, incomingRequest.arg.status.locationString)); - gpSetStatus( con, incomingRequest.arg.status.status, incomingRequest.arg.status.statusString, - incomingRequest.arg.status.locationString ); - lastStatus = incomingRequest.arg.status.status; - lastStatusString = incomingRequest.arg.status.statusString; - } - break; - } - } - - // update the network - GPEnum isConnected = GP_CONNECTED; - GPResult res = GP_NO_ERROR; - res = gpIsConnected( con, &isConnected ); - if ( isConnected == GP_CONNECTED && res == GP_NO_ERROR ) - gpProcess( con ); - - // end our timeslice - Switch_Thread(); - } - - gpDestroy( con ); - } catch ( ... ) { - DEBUG_CRASH(("Exception in buddy thread!")); - } -} - -void BuddyThreadClass::errorCallback( GPConnection *con, GPErrorArg *arg ) -{ - // log the error - DEBUG_LOG(("GPErrorCallback\n")); - m_lastErrorCode = arg->errorCode; - - char errorCodeString[256]; - char resultString[256]; - - #define RESULT(x) case x: strcpy(resultString, #x); break; - switch(arg->result) - { - RESULT(GP_NO_ERROR) - RESULT(GP_MEMORY_ERROR) - RESULT(GP_PARAMETER_ERROR) - RESULT(GP_NETWORK_ERROR) - RESULT(GP_SERVER_ERROR) - default: - strcpy(resultString, "Unknown result!"); - } - #undef RESULT - - #define ERRORCODE(x) case x: strcpy(errorCodeString, #x); break; - switch(arg->errorCode) - { - ERRORCODE(GP_GENERAL) - ERRORCODE(GP_PARSE) - ERRORCODE(GP_NOT_LOGGED_IN) - ERRORCODE(GP_BAD_SESSKEY) - ERRORCODE(GP_DATABASE) - ERRORCODE(GP_NETWORK) - ERRORCODE(GP_FORCED_DISCONNECT) - ERRORCODE(GP_CONNECTION_CLOSED) - ERRORCODE(GP_LOGIN) - ERRORCODE(GP_LOGIN_TIMEOUT) - ERRORCODE(GP_LOGIN_BAD_NICK) - ERRORCODE(GP_LOGIN_BAD_EMAIL) - ERRORCODE(GP_LOGIN_BAD_PASSWORD) - ERRORCODE(GP_LOGIN_BAD_PROFILE) - ERRORCODE(GP_LOGIN_PROFILE_DELETED) - ERRORCODE(GP_LOGIN_CONNECTION_FAILED) - ERRORCODE(GP_LOGIN_SERVER_AUTH_FAILED) - ERRORCODE(GP_NEWUSER) - ERRORCODE(GP_NEWUSER_BAD_NICK) - ERRORCODE(GP_NEWUSER_BAD_PASSWORD) - ERRORCODE(GP_UPDATEUI) - ERRORCODE(GP_UPDATEUI_BAD_EMAIL) - ERRORCODE(GP_NEWPROFILE) - ERRORCODE(GP_NEWPROFILE_BAD_NICK) - ERRORCODE(GP_NEWPROFILE_BAD_OLD_NICK) - ERRORCODE(GP_UPDATEPRO) - ERRORCODE(GP_UPDATEPRO_BAD_NICK) - ERRORCODE(GP_ADDBUDDY) - ERRORCODE(GP_ADDBUDDY_BAD_FROM) - ERRORCODE(GP_ADDBUDDY_BAD_NEW) - ERRORCODE(GP_ADDBUDDY_ALREADY_BUDDY) - ERRORCODE(GP_AUTHADD) - ERRORCODE(GP_AUTHADD_BAD_FROM) - ERRORCODE(GP_AUTHADD_BAD_SIG) - ERRORCODE(GP_STATUS) - ERRORCODE(GP_BM) - ERRORCODE(GP_BM_NOT_BUDDY) - ERRORCODE(GP_GETPROFILE) - ERRORCODE(GP_GETPROFILE_BAD_PROFILE) - ERRORCODE(GP_DELBUDDY) - ERRORCODE(GP_DELBUDDY_NOT_BUDDY) - ERRORCODE(GP_DELPROFILE) - ERRORCODE(GP_DELPROFILE_LAST_PROFILE) - ERRORCODE(GP_SEARCH) - ERRORCODE(GP_SEARCH_CONNECTION_FAILED) - default: - strcpy(errorCodeString, "Unknown error code!"); - } - #undef ERRORCODE - - if(arg->fatal) - { - DEBUG_LOG(( "-----------\n")); - DEBUG_LOG(( "GP FATAL ERROR\n")); - DEBUG_LOG(( "-----------\n")); - } - else - { - DEBUG_LOG(( "-----\n")); - DEBUG_LOG(( "GP ERROR\n")); - DEBUG_LOG(( "-----\n")); - } - DEBUG_LOG(( "RESULT: %s (%d)\n", resultString, arg->result)); - DEBUG_LOG(( "ERROR CODE: %s (0x%X)\n", errorCodeString, arg->errorCode)); - DEBUG_LOG(( "ERROR STRING: %s\n", arg->errorString)); - - if (arg->fatal == GP_FATAL) - { - BuddyResponse errorResponse; - errorResponse.buddyResponseType = BuddyResponse::BUDDYRESPONSE_DISCONNECT; - errorResponse.result = arg->result; - errorResponse.arg.error.errorCode = arg->errorCode; - errorResponse.arg.error.fatal = arg->fatal; - strncpy(errorResponse.arg.error.errorString, arg->errorString, MAX_BUDDY_CHAT_LEN); - errorResponse.arg.error.errorString[MAX_BUDDY_CHAT_LEN-1] = 0; - m_isConnecting = m_isConnected = false; - TheGameSpyBuddyMessageQueue->addResponse( errorResponse ); - if (m_isdeleting) - { - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_LOGOUT; - TheGameSpyPeerMessageQueue->addRequest( req ); - m_isdeleting = false; - } - } -} - -static void getNickForMessage( GPConnection *con, GPGetInfoResponseArg *arg, void *param ) -{ - BuddyResponse *resp = (BuddyResponse *)param; - strcpy(resp->arg.message.nick, arg->nick); -} - -void BuddyThreadClass::messageCallback( GPConnection *con, GPRecvBuddyMessageArg *arg ) -{ - BuddyResponse messageResponse; - messageResponse.buddyResponseType = BuddyResponse::BUDDYRESPONSE_MESSAGE; - messageResponse.profile = arg->profile; - - // get info about the person asking to be our buddy - gpGetInfo( con, arg->profile, GP_CHECK_CACHE, GP_BLOCKING, (GPCallback)getNickForMessage, &messageResponse); - - std::wstring s = MultiByteToWideCharSingleLine( arg->message ); - wcsncpy(messageResponse.arg.message.text, s.c_str(), MAX_BUDDY_CHAT_LEN); - messageResponse.arg.message.text[MAX_BUDDY_CHAT_LEN-1] = 0; - messageResponse.arg.message.date = arg->date; - DEBUG_LOG(("Got a buddy message from %d [%ls]\n", arg->profile, s.c_str())); - TheGameSpyBuddyMessageQueue->addResponse( messageResponse ); -} - -void BuddyThreadClass::connectCallback( GPConnection *con, GPConnectResponseArg *arg ) -{ - BuddyResponse loginResponse; - if (arg->result == GP_NO_ERROR) - { - loginResponse.buddyResponseType = BuddyResponse::BUDDYRESPONSE_LOGIN; - loginResponse.result = arg->result; - loginResponse.profile = arg->profile; - TheGameSpyBuddyMessageQueue->addResponse( loginResponse ); - m_profileID = arg->profile; - - if (!TheGameSpyPeerMessageQueue->isConnected() && !TheGameSpyPeerMessageQueue->isConnecting()) - { - DEBUG_LOG(("Buddy connect: trying chat connect\n")); - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_LOGIN; - req.nick = m_nick.c_str(); - req.password = m_pass; - req.email = m_email; - req.login.profileID = arg->profile; - TheGameSpyPeerMessageQueue->addRequest(req); - } - } - else - { - if (!TheGameSpyPeerMessageQueue->isConnected() && !TheGameSpyPeerMessageQueue->isConnecting()) - { - if (m_lastErrorCode == GP_NEWUSER_BAD_NICK) - { - m_isNewAccount = FALSE; - // they just hit 'create account' instead of 'log in'. Fix them. - DEBUG_LOG(("User Error: Create Account instead of Login. Fixing them...\n")); - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_LOGIN; - strcpy(req.arg.login.nick, m_nick.c_str()); - strcpy(req.arg.login.email, m_email.c_str()); - strcpy(req.arg.login.password, m_pass.c_str()); - req.arg.login.hasFirewall = true; - TheGameSpyBuddyMessageQueue->addRequest( req ); - return; - } - DEBUG_LOG(("Buddy connect failed (%d/%d): posting a failed chat connect\n", arg->result, m_lastErrorCode)); - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT; - resp.discon.reason = DISCONNECT_COULDNOTCONNECT; - switch (m_lastErrorCode) - { - case GP_LOGIN_TIMEOUT: - resp.discon.reason = DISCONNECT_GP_LOGIN_TIMEOUT; - break; - case GP_LOGIN_BAD_NICK: - resp.discon.reason = DISCONNECT_GP_LOGIN_BAD_NICK; - break; - case GP_LOGIN_BAD_EMAIL: - resp.discon.reason = DISCONNECT_GP_LOGIN_BAD_EMAIL; - break; - case GP_LOGIN_BAD_PASSWORD: - resp.discon.reason = DISCONNECT_GP_LOGIN_BAD_PASSWORD; - break; - case GP_LOGIN_BAD_PROFILE: - resp.discon.reason = DISCONNECT_GP_LOGIN_BAD_PROFILE; - break; - case GP_LOGIN_PROFILE_DELETED: - resp.discon.reason = DISCONNECT_GP_LOGIN_PROFILE_DELETED; - break; - case GP_LOGIN_CONNECTION_FAILED: - resp.discon.reason = DISCONNECT_GP_LOGIN_CONNECTION_FAILED; - break; - case GP_LOGIN_SERVER_AUTH_FAILED: - resp.discon.reason = DISCONNECT_GP_LOGIN_SERVER_AUTH_FAILED; - break; - case GP_NEWUSER_BAD_NICK: - resp.discon.reason = DISCONNECT_GP_NEWUSER_BAD_NICK; - break; - case GP_NEWUSER_BAD_PASSWORD: - resp.discon.reason = DISCONNECT_GP_NEWUSER_BAD_PASSWORD; - break; - case GP_NEWPROFILE_BAD_NICK: - resp.discon.reason = DISCONNECT_GP_NEWPROFILE_BAD_NICK; - break; - case GP_NEWPROFILE_BAD_OLD_NICK: - resp.discon.reason = DISCONNECT_GP_NEWPROFILE_BAD_OLD_NICK; - break; - } - TheGameSpyPeerMessageQueue->addResponse(resp); - } - } -} - -// ----------------------- - -static void getInfoResponseForRequest( GPConnection *con, GPGetInfoResponseArg *arg, void *param ) -{ - BuddyResponse *resp = (BuddyResponse *)param; - resp->profile = arg->profile; - strcpy(resp->arg.request.nick, arg->nick); - strcpy(resp->arg.request.email, arg->email); - strcpy(resp->arg.request.countrycode, arg->countrycode); -} - -void BuddyThreadClass::requestCallback( GPConnection *con, GPRecvBuddyRequestArg *arg ) -{ - BuddyResponse response; - response.buddyResponseType = BuddyResponse::BUDDYRESPONSE_REQUEST; - response.profile = arg->profile; - - // get info about the person asking to be our buddy - gpGetInfo( con, arg->profile, GP_CHECK_CACHE, GP_BLOCKING, (GPCallback)getInfoResponseForRequest, &response); - - std::wstring s = MultiByteToWideCharSingleLine( arg->reason ); - wcsncpy(response.arg.request.text, s.c_str(), GP_REASON_LEN); - response.arg.request.text[GP_REASON_LEN-1] = 0; - - TheGameSpyBuddyMessageQueue->addResponse( response ); -} - -// ----------------------- - -static void getInfoResponseForStatus(GPConnection * connection, GPGetInfoResponseArg * arg, void * param) -{ - BuddyResponse *resp = (BuddyResponse *)param; - resp->profile = arg->profile; - strcpy(resp->arg.status.nick, arg->nick); - strcpy(resp->arg.status.email, arg->email); - strcpy(resp->arg.status.countrycode, arg->countrycode); -} - -void BuddyThreadClass::statusCallback( GPConnection *con, GPRecvBuddyStatusArg *arg ) -{ - BuddyResponse response; - - // get user's name - response.buddyResponseType = BuddyResponse::BUDDYRESPONSE_STATUS; - gpGetInfo( con, arg->profile, GP_CHECK_CACHE, GP_BLOCKING, (GPCallback)getInfoResponseForStatus, &response); - - // get user's status - GPBuddyStatus status; - gpGetBuddyStatus( con, arg->index, &status ); - strcpy(response.arg.status.location, status.locationString); - strcpy(response.arg.status.statusString, status.statusString); - response.arg.status.status = status.status; - DEBUG_LOG(("Got buddy status for %d(%s) - status %d\n", status.profile, response.arg.status.nick, status.status)); - - // relay to UI - TheGameSpyBuddyMessageQueue->addResponse( response ); -} - - -//------------------------------------------------------------------------- - diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/GameResultsThread.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/GameResultsThread.cpp deleted file mode 100644 index a08f9535ff5..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/GameResultsThread.cpp +++ /dev/null @@ -1,394 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PingThread.cpp ////////////////////////////////////////////////////// -// Ping thread -// Author: Matthew D. Campbell, August 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include // This one has to be here. Prevents collisions with winsock2.h - -#include "GameNetwork/GameSpy/GameResultsThread.h" -#include "mutex.h" -#include "thread.h" - -#include "Common/StackDump.h" -#include "Common/SubsystemInterface.h" - -//------------------------------------------------------------------------- - -static const Int NumWorkerThreads = 1; - -typedef std::queue RequestQueue; -typedef std::queue ResponseQueue; -class GameResultsThreadClass; - -class GameResultsQueue : public GameResultsInterface -{ -public: - virtual ~GameResultsQueue(); - GameResultsQueue(); - - virtual void init() {} - virtual void reset() {} - virtual void update() {} - - virtual void startThreads( void ); - virtual void endThreads( void ); - virtual Bool areThreadsRunning( void ); - - virtual void addRequest( const GameResultsRequest& req ); - virtual Bool getRequest( GameResultsRequest& resp ); - - virtual void addResponse( const GameResultsResponse& resp ); - virtual Bool getResponse( GameResultsResponse& resp ); - - virtual Bool areGameResultsBeingSent( void ); - -private: - MutexClass m_requestMutex; - MutexClass m_responseMutex; - RequestQueue m_requests; - ResponseQueue m_responses; - Int m_requestCount; - Int m_responseCount; - - GameResultsThreadClass *m_workerThreads[NumWorkerThreads]; -}; - -GameResultsInterface* GameResultsInterface::createNewGameResultsInterface( void ) -{ - return NEW GameResultsQueue; -} - -GameResultsInterface *TheGameResultsQueue; - -//------------------------------------------------------------------------- - -class GameResultsThreadClass : public ThreadClass -{ - -public: - GameResultsThreadClass() : ThreadClass() {} - - void Thread_Function(); - -private: - Int sendGameResults( UnsignedInt IP, UnsignedShort port, const std::string& results ); -}; - - -//------------------------------------------------------------------------- - -GameResultsQueue::GameResultsQueue() : m_requestCount(0), m_responseCount(0) -{ - for (Int i=0; iExecute(); - } -} - -void GameResultsQueue::endThreads( void ) -{ - for (Int i=0; iIs_Running()) - return true; - } - } - return false; -} - -void GameResultsQueue::addRequest( const GameResultsRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex); - - ++m_requestCount; - m_requests.push(req); -} - -Bool GameResultsQueue::getRequest( GameResultsRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex, 0); - if (m.Failed()) - return false; - - if (m_requests.empty()) - return false; - req = m_requests.front(); - m_requests.pop(); - return true; -} - -void GameResultsQueue::addResponse( const GameResultsResponse& resp ) -{ - { - MutexClass::LockClass m(m_responseMutex); - - ++m_responseCount; - m_responses.push(resp); - } -} - -Bool GameResultsQueue::getResponse( GameResultsResponse& resp ) -{ - MutexClass::LockClass m(m_responseMutex, 0); - if (m.Failed()) - return false; - - if (m_responses.empty()) - return false; - resp = m_responses.front(); - m_responses.pop(); - return true; -} - -Bool GameResultsQueue::areGameResultsBeingSent( void ) -{ - MutexClass::LockClass m(m_requestMutex, 0); - if (m.Failed()) - return true; - - return m_requestCount > 0; -} - -//------------------------------------------------------------------------- - -void GameResultsThreadClass::Thread_Function() -{ - try { - _set_se_translator( DumpExceptionInfo ); // Hook that allows stack trace. - GameResultsRequest req; - - WSADATA wsaData; - - // Fire up winsock (prob already done, but doesn't matter) - WORD wVersionRequested = MAKEWORD(1, 1); - WSAStartup( wVersionRequested, &wsaData ); - - while ( running ) - { - // deal with requests - if (TheGameResultsQueue && TheGameResultsQueue->getRequest(req)) - { - // resolve the hostname - const char *hostnameBuffer = req.hostname.c_str(); - UnsignedInt IP = 0xFFFFFFFF; - if (isdigit(hostnameBuffer[0])) - { - IP = inet_addr(hostnameBuffer); - in_addr hostNode; - hostNode.s_addr = IP; - DEBUG_LOG(("sending game results to %s - IP = %s\n", hostnameBuffer, inet_ntoa(hostNode) )); - } - else - { - HOSTENT *hostStruct; - in_addr *hostNode; - hostStruct = gethostbyname(hostnameBuffer); - if (hostStruct == NULL) - { - DEBUG_LOG(("sending game results to %s - host lookup failed\n", hostnameBuffer)); - - // Even though this failed to resolve IP, still need to send a - // callback. - IP = 0xFFFFFFFF; // flag for IP resolve failed - } - hostNode = (in_addr *) hostStruct->h_addr; - IP = hostNode->s_addr; - DEBUG_LOG(("sending game results to %s IP = %s\n", hostnameBuffer, inet_ntoa(*hostNode) )); - } - - int result = sendGameResults( IP, req.port, req.results ); - GameResultsResponse resp; - resp.hostname = req.hostname; - resp.port = req.port; - resp.sentOk = (result == req.results.length()); - - } - - // end our timeslice - Switch_Thread(); - } - - WSACleanup(); - } catch ( ... ) { - DEBUG_CRASH(("Exception in results thread!")); - } -} - -//------------------------------------------------------------------------- - -#ifdef DEBUG_LOGGING -#define CASE(x) case (x): return #x; - -static const char *getWSAErrorString( Int error ) -{ - switch (error) - { - CASE(WSABASEERR) - CASE(WSAEINTR) - CASE(WSAEBADF) - CASE(WSAEACCES) - CASE(WSAEFAULT) - CASE(WSAEINVAL) - CASE(WSAEMFILE) - CASE(WSAEWOULDBLOCK) - CASE(WSAEINPROGRESS) - CASE(WSAEALREADY) - CASE(WSAENOTSOCK) - CASE(WSAEDESTADDRREQ) - CASE(WSAEMSGSIZE) - CASE(WSAEPROTOTYPE) - CASE(WSAENOPROTOOPT) - CASE(WSAEPROTONOSUPPORT) - CASE(WSAESOCKTNOSUPPORT) - CASE(WSAEOPNOTSUPP) - CASE(WSAEPFNOSUPPORT) - CASE(WSAEAFNOSUPPORT) - CASE(WSAEADDRINUSE) - CASE(WSAEADDRNOTAVAIL) - CASE(WSAENETDOWN) - CASE(WSAENETUNREACH) - CASE(WSAENETRESET) - CASE(WSAECONNABORTED) - CASE(WSAECONNRESET) - CASE(WSAENOBUFS) - CASE(WSAEISCONN) - CASE(WSAENOTCONN) - CASE(WSAESHUTDOWN) - CASE(WSAETOOMANYREFS) - CASE(WSAETIMEDOUT) - CASE(WSAECONNREFUSED) - CASE(WSAELOOP) - CASE(WSAENAMETOOLONG) - CASE(WSAEHOSTDOWN) - CASE(WSAEHOSTUNREACH) - CASE(WSAENOTEMPTY) - CASE(WSAEPROCLIM) - CASE(WSAEUSERS) - CASE(WSAEDQUOT) - CASE(WSAESTALE) - CASE(WSAEREMOTE) - CASE(WSAEDISCON) - CASE(WSASYSNOTREADY) - CASE(WSAVERNOTSUPPORTED) - CASE(WSANOTINITIALISED) - CASE(WSAHOST_NOT_FOUND) - CASE(WSATRY_AGAIN) - CASE(WSANO_RECOVERY) - CASE(WSANO_DATA) - default: - return "Not a Winsock error"; - } -} - -#undef CASE - -#endif -//------------------------------------------------------------------------- - -Int GameResultsThreadClass::sendGameResults( UnsignedInt IP, UnsignedShort port, const std::string& results ) -{ - int error = 0; - - // create the socket - Int sock = socket( AF_INET, SOCK_STREAM, 0 ); - if (sock < 0) - { - DEBUG_LOG(("GameResultsThreadClass::sendGameResults() - socket() returned %d(%s)\n", sock, getWSAErrorString(sock))); - return sock; - } - - // fill in address info - struct sockaddr_in sockAddr; - memset( &sockAddr, 0, sizeof( sockAddr ) ); - sockAddr.sin_family = AF_INET; - sockAddr.sin_addr.s_addr = IP; - sockAddr.sin_port = htons(port); - - // Start the connection process.... - if( connect( sock, (struct sockaddr *)&sockAddr, sizeof( sockAddr ) ) == -1 ) - { - error = WSAGetLastError(); - DEBUG_LOG(("GameResultsThreadClass::sendGameResults() - connect() returned %d(%s)\n", error, getWSAErrorString(error))); - if( ( error == WSAEWOULDBLOCK ) || ( error == WSAEINVAL ) || ( error == WSAEALREADY ) ) - { - return( -1 ); - } - - if( error != WSAEISCONN ) - { - closesocket( sock ); - return( -1 ); - } - } - - if (send( sock, results.c_str(), results.length(), 0 ) == SOCKET_ERROR) - { - error = WSAGetLastError(); - DEBUG_LOG(("GameResultsThreadClass::sendGameResults() - send() returned %d(%s)\n", error, getWSAErrorString(error))); - closesocket(sock); - return WSAGetLastError(); - } - - closesocket(sock); - - return results.length(); -} - - -//------------------------------------------------------------------------- diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PeerThread.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PeerThread.cpp deleted file mode 100644 index 57d2df5fa30..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PeerThread.cpp +++ /dev/null @@ -1,2985 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PeerThread.cpp ////////////////////////////////////////////////////// -// GameSpy Peer (chat) thread -// This thread communicates with GameSpy's chat server -// and talks through a message queue with the rest of -// the game. -// Author: Matthew D. Campbell, June 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/Registry.h" -#include "Common/StackDump.h" -#include "Common/UserPreferences.h" -#include "Common/Version.h" -#include "GameNetwork/IPEnumeration.h" -#include "GameNetwork/GameSpy/BuddyThread.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpy/ThreadUtils.h" - -#include "strtok_r.h" -#include "mutex.h" -#include "thread.h" - -#include "Common/MiniLog.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -// enable this for trying to track down why SBServers are losing their keyvals -MDC 2/20/2003 -#undef SERVER_DEBUGGING -#ifdef SERVER_DEBUGGING -void CheckServers(PEER peer); -#endif // SERVER_DEBUGGING - -#ifdef DEBUG_LOGGING -//#define PING_TEST -static LogClass s_pingLog("Ping.txt"); -#define PING_LOG(x) s_pingLog.log x -#else // DEBUG_LOGGING -#define PING_LOG(x) {} -#endif // DEBUG_LOGGING - -#ifdef DEBUG_LOGGING -static LogClass s_stateChangedLog("StateChanged.txt"); - -#define STATECHANGED_LOG(x) s_stateChangedLog.log x - -#else // DEBUG_LOGGING - -#define STATECHANGED_LOG(x) {} - -#endif // DEBUG_LOGGING - -// we should always be using broadcast keys from now on. Remove the old code sometime when -// we're not in a rush, ok? -// -MDC 2/14/2003 -#define USE_BROADCAST_KEYS - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -int isThreadHosting = 0; -static UnsignedInt s_lastStateChangedHeartbeat = 0; -static Bool s_wantStateChangedHeartbeat = FALSE; -static UnsignedInt s_heartbeatInterval = 10000; - -static SOCKET qr2Sock = INVALID_SOCKET; - -enum -{ - EXECRC_KEY = NUM_RESERVED_KEYS + 1, - INICRC_KEY, - PW_KEY, - OBS_KEY, - USE_STATS_KEY, - LADIP_KEY, - LADPORT_KEY, - PINGSTR_KEY, - NUMPLAYER_KEY, - MAXPLAYER_KEY, - NUMOBS_KEY, - NAME__KEY, - FACTION__KEY, - COLOR__KEY, - WINS__KEY, - LOSSES__KEY -}; - -#define EXECRC_STR "exeCRC" -#define INICRC_STR "iniCRC" -#define PW_STR "pw" -#define OBS_STR "obs" -#define USE_STATS_STR "stat" -#define LADIP_STR "ladIP" -#define LADPORT_STR "ladPort" -#define PINGSTR_STR "pings" -#define NUMPLAYER_STR "numRealPlayers" -#define MAXPLAYER_STR "maxRealPlayers" -#define NUMOBS_STR "numObservers" -#define NAME__STR "name" -#define FACTION__STR "faction" -#define COLOR__STR "color" -#define WINS__STR "wins" -#define LOSSES__STR "losses" - -//------------------------------------------------------------------------- - -typedef std::queue RequestQueue; -typedef std::queue ResponseQueue; -class PeerThreadClass; - -class GameSpyPeerMessageQueue : public GameSpyPeerMessageQueueInterface -{ -public: - virtual ~GameSpyPeerMessageQueue(); - GameSpyPeerMessageQueue(); - virtual void startThread( void ); - virtual void endThread( void ); - virtual Bool isThreadRunning( void ); - virtual Bool isConnected( void ); - virtual Bool isConnecting( void ); - - virtual void addRequest( const PeerRequest& req ); - virtual Bool getRequest( PeerRequest& req ); - - virtual void addResponse( const PeerResponse& resp ); - virtual Bool getResponse( PeerResponse& resp ); - - virtual SerialAuthResult getSerialAuthResult( void ) { return m_serialAuth; } - void setSerialAuthResult( SerialAuthResult result ) { m_serialAuth = result; } - - PeerThreadClass* getThread( void ); - -private: - MutexClass m_requestMutex; - MutexClass m_responseMutex; - RequestQueue m_requests; - ResponseQueue m_responses; - PeerThreadClass *m_thread; - - SerialAuthResult m_serialAuth; -}; - -GameSpyPeerMessageQueueInterface* GameSpyPeerMessageQueueInterface::createNewMessageQueue( void ) -{ - return NEW GameSpyPeerMessageQueue; -} - -GameSpyPeerMessageQueueInterface *TheGameSpyPeerMessageQueue; -#define MESSAGE_QUEUE ((GameSpyPeerMessageQueue *)TheGameSpyPeerMessageQueue) - -//------------------------------------------------------------------------- - -class PeerThreadClass : public ThreadClass -{ - -public: - PeerThreadClass() : ThreadClass() - { - //Added By Sadullah Nader - //Initializations inserted - m_roomJoined = m_allowObservers = m_hasPassword = FALSE; - m_useStats = TRUE; - m_exeCRC = m_iniCRC = 0; - m_gameVersion = 0; - m_ladderPort = 0; - m_localRoomID = 0; - m_maxPlayers = 0; - m_numObservers = 0; - m_maxPlayers = 0; - m_qmGroupRoom = 0; - m_sawEndOfEnumPlayers = m_sawMatchbot = FALSE; - m_sawCompleteGameList = FALSE; - // - m_isConnecting = m_isConnected = false; - m_groupRoomID = m_profileID = 0; - m_nextStagingServer = 1; m_stagingServers.clear(); - m_pingStr = ""; m_mapName = ""; m_ladderIP = ""; m_isHosting = false; - for (Int i=0; i PlayerStatMap; - PlayerStatMap m_groupRoomStats; - PlayerStatMap m_stagingRoomStats; - std::string packStatKey(const char *nick, const char *key); -#endif // USE_BROADCAST_KEYS - - // game-hosting info for GOA callbacks - Bool m_isHosting; - Bool m_hasPassword; - std::string m_mapName; - std::string m_playerNames[MAX_SLOTS]; - UnsignedInt m_exeCRC; - UnsignedInt m_iniCRC; - UnsignedInt m_gameVersion; - Bool m_allowObservers; - Bool m_useStats; - std::string m_pingStr; - std::string m_ladderIP; - UnsignedShort m_ladderPort; - Int m_playerWins[MAX_SLOTS]; - Int m_playerLosses[MAX_SLOTS]; - Int m_playerProfileID[MAX_SLOTS]; - Int m_playerColors[MAX_SLOTS]; - Int m_playerFactions[MAX_SLOTS]; - Int m_numPlayers; - Int m_maxPlayers; - Int m_numObservers; - - Int m_nextStagingServer; - std::map m_stagingServers; - std::wstring m_localStagingServerName; - Int m_localRoomID; - - void doQuickMatch( PEER peer ); - QMStatus m_qmStatus; - PeerRequest m_qmInfo; - Bool m_roomJoined; - Int m_qmGroupRoom; - Bool m_sawEndOfEnumPlayers; - Bool m_sawMatchbot; - std::string m_matchbotName; -}; - -#ifdef USE_BROADCAST_KEYS -const char* PeerThreadClass::s_keys[6] = { "b_locale", "b_wins", "b_losses", "b_points", "b_side", "b_pre" }; -char PeerThreadClass::s_valueBuffers[6][20] = { "", "", "", "", "", "" }; -const char* PeerThreadClass::s_values[6] = { s_valueBuffers[0], s_valueBuffers[1], s_valueBuffers[2], - s_valueBuffers[3], s_valueBuffers[4], s_valueBuffers[5]}; - -void PeerThreadClass::trackStatsForPlayer(RoomType roomType, const char *nick, const char *key, const char *val) -{ - switch (roomType) - { - case GroupRoom: - m_groupRoomStats[packStatKey(nick, key)] = atoi(val); - break; - case StagingRoom: - m_stagingRoomStats[packStatKey(nick, key)] = atoi(val); - break; - } -} - -std::string PeerThreadClass::packStatKey(const char *nick, const char *key) -{ - std::string s = nick; - s.append(key); - return s; -} - -int PeerThreadClass::lookupStatForPlayer(RoomType roomType, const char *nick, const char *key) -{ - std::string fullKey = packStatKey(nick, key); - PlayerStatMap::const_iterator it; - switch (roomType) - { - case GroupRoom: - it = m_groupRoomStats.find(fullKey); - if (it != m_groupRoomStats.end()) - return it->second; - break; - case StagingRoom: - it = m_stagingRoomStats.find(fullKey); - if (it != m_stagingRoomStats.end()) - return it->second; - break; - } - return 0; -} - -void PeerThreadClass::clearPlayerStats(RoomType roomType) -{ - switch (roomType) - { - case GroupRoom: - m_groupRoomStats.clear(); - break; - case StagingRoom: - m_stagingRoomStats.clear(); - break; - } -} - -void PeerThreadClass::pushStatsToRoom(PEER peer) -{ - DEBUG_LOG(("PeerThreadClass::pushStatsToRoom(): stats are %s=%s,%s=%s,%s=%s,%s=%s,%s=%s,%s=%s\n", - s_keys[0], s_values[0], - s_keys[1], s_values[1], - s_keys[2], s_values[2], - s_keys[3], s_values[3], - s_keys[4], s_values[4], - s_keys[5], s_values[5])); - peerSetRoomKeys(peer, GroupRoom, m_loginName.c_str(), 6, s_keys, s_values); - peerSetRoomKeys(peer, StagingRoom, m_loginName.c_str(), 6, s_keys, s_values); -} - -void getRoomKeysCallback(PEER peer, PEERBool success, RoomType roomType, const char *nick, int num, char **keys, char **values, void *param); -void PeerThreadClass::getStatsFromRoom(PEER peer, RoomType roomType) -{ - peerGetRoomKeys(peer, GroupRoom, "*", NumKeys, s_keys, getRoomKeysCallback, this, PEERFalse); -} -#endif // USE_BROADCAST_KEYS - -Int PeerThreadClass::addServerToMap( SBServer server ) -{ - Int val = m_nextStagingServer++; - m_stagingServers[val] = server; - return val; -} - -Int PeerThreadClass::removeServerFromMap( SBServer server ) -{ - for (std::map::iterator it = m_stagingServers.begin(); it != m_stagingServers.end(); ++it) - { - if (it->second == server) - { - Int val = it->first; - m_stagingServers.erase(it); - return val; - } - } - - return 0; -} - -void PeerThreadClass::clearServers( void ) -{ - m_stagingServers.clear(); -} - -SBServer PeerThreadClass::findServerByID( Int id ) -{ - std::map::iterator it = m_stagingServers.find(id); - if (it != m_stagingServers.end()) - { - SBServer server = it->second; - if (server && !server->keyvals) - { - DEBUG_CRASH(("Referencing a missing server!")); - return 0; - } - return it->second; - } - return 0; -} - -Int PeerThreadClass::findServer( SBServer server ) -{ - char tmp[10] = ""; - const char *newName = SBServerGetStringValue(server, "gamename", tmp); - UnsignedInt newPrivateIP = SBServerGetPrivateInetAddress(server); - UnsignedShort newPrivatePort = SBServerGetPrivateQueryPort(server); - UnsignedInt newPublicIP = SBServerGetPublicInetAddress(server); - - SBServer serverToRemove = NULL; - - for (std::map::iterator it = m_stagingServers.begin(); it != m_stagingServers.end(); ++it) - { - if (it->second == server) - { - return it->first; - } - else - { - const char *oldName = SBServerGetStringValue(it->second, "gamename", tmp); - UnsignedInt oldPrivateIP = SBServerGetPrivateInetAddress(it->second); - UnsignedShort oldPrivatePort = SBServerGetPrivateQueryPort(it->second); - UnsignedInt oldPublicIP = SBServerGetPublicInetAddress(it->second); - if (!strcmp(oldName, newName) && - oldPrivateIP == newPrivateIP && - oldPublicIP == newPublicIP && - oldPrivatePort == newPrivatePort) - { - serverToRemove = it->second; - } - } - } - - if (serverToRemove) - { - // this is the same as another game - it has just migrated to another port. Remove the old and replace it. - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_STAGINGROOM; - resp.stagingRoom.id = removeServerFromMap( serverToRemove ); - resp.stagingRoom.action = PEER_REMOVE; - resp.stagingRoom.isStaging = TRUE; - resp.stagingRoom.percentComplete = -1; - TheGameSpyPeerMessageQueue->addResponse(resp); - } - - return addServerToMap(server); -} - -static enum CallbackType -{ - CALLBACK_CONNECT, - CALLBACK_ERROR, - CALLBACK_RECVMESSAGE, - CALLBACK_RECVREQUEST, - CALLBACK_RECVSTATUS, - CALLBACK_MAX -}; - -void connectCallbackWrapper( PEER peer, PEERBool success, int failureReason, void *param ) -{ -#ifdef SERVER_DEBUGGING - DEBUG_LOG(("In connectCallbackWrapper()\n")); - CheckServers(peer); -#endif // SERVER_DEBUGGING - if (param != NULL) - { - ((PeerThreadClass *)param)->connectCallback( peer, success ); - } -} - -void nickErrorCallbackWrapper( PEER peer, Int type, const char *nick, int numSuggestedNicks, const gsi_char** suggestedNicks, void *param ) -{ - if (param != NULL) - { - ((PeerThreadClass *)param)->nickErrorCallback( peer, type, nick ); - } -} - -static void joinRoomCallback(PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, void *param); - -//------------------------------------------------------------------------- - -GameSpyPeerMessageQueue::GameSpyPeerMessageQueue() -{ - m_thread = NULL; - m_serialAuth = SERIAL_OK; -} - -GameSpyPeerMessageQueue::~GameSpyPeerMessageQueue() -{ - endThread(); -} - -void GameSpyPeerMessageQueue::startThread( void ) -{ - if (!m_thread) - { - m_thread = NEW PeerThreadClass; - m_thread->Execute(); - } - else - { - if (!m_thread->Is_Running()) - { - m_thread->Execute(); - } - } -} - -void GameSpyPeerMessageQueue::endThread( void ) -{ - if (m_thread) - delete m_thread; - m_thread = NULL; -} - -Bool GameSpyPeerMessageQueue::isThreadRunning( void ) -{ - return (m_thread) ? m_thread->Is_Running() : false; -} - -Bool GameSpyPeerMessageQueue::isConnected( void ) -{ - return (m_thread) ? m_thread->isConnected() : false; -} - -Bool GameSpyPeerMessageQueue::isConnecting( void ) -{ - return (m_thread) ? m_thread->isConnecting() : false; -} - -void GameSpyPeerMessageQueue::addRequest( const PeerRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex); - if (m.Failed()) - return; - - m_requests.push(req); -} - -//PeerRequest GameSpyPeerMessageQueue::getRequest( void ) -Bool GameSpyPeerMessageQueue::getRequest( PeerRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex, 0); - if (m.Failed()) - return false; - - if (m_requests.empty()) - return false; - req = m_requests.front(); - m_requests.pop(); - return true; -} - -void GameSpyPeerMessageQueue::addResponse( const PeerResponse& resp ) -{ - if (resp.nick == "(END)") - return; - - MutexClass::LockClass m(m_responseMutex); - if (m.Failed()) - return; - - m_responses.push(resp); -} - -//PeerResponse GameSpyPeerMessageQueue::getResponse( void ) -Bool GameSpyPeerMessageQueue::getResponse( PeerResponse& resp ) -{ - MutexClass::LockClass m(m_responseMutex, 0); - if (m.Failed()) - return false; - - if (m_responses.empty()) - return false; - resp = m_responses.front(); - m_responses.pop(); - return true; -} - -PeerThreadClass* GameSpyPeerMessageQueue::getThread( void ) -{ - return m_thread; -} - -//------------------------------------------------------------------------- -static void disconnectedCallback(PEER peer, const char * reason, void * param); -static void roomMessageCallback(PEER peer, RoomType roomType, const char * nick, const char * message, MessageType messageType, void * param); -static void playerMessageCallback(PEER peer, const char * nick, const char * message, MessageType messageType, void * param); -static void playerJoinedCallback(PEER peer, RoomType roomType, const char * nick, void * param); -static void playerLeftCallback(PEER peer, RoomType roomType, const char * nick, const char * reason, void * param); -static void playerChangedNickCallback(PEER peer, RoomType roomType, const char * oldNick, const char * newNick, void * param); -static void playerInfoCallback(PEER peer, RoomType roomType, const char * nick, unsigned int IP, int profileID, void * param); -static void playerFlagsChangedCallback(PEER peer, RoomType roomType, const char * nick, int oldFlags, int newFlags, void * param); -static void listingGamesCallback(PEER peer, PEERBool success, const char * name, SBServer server, PEERBool staging, int msg, Int percentListed, void * param); -static void roomUTMCallback(PEER peer, RoomType roomType, const char * nick, const char * command, const char * parameters, PEERBool authenticated, void * param); -static void playerUTMCallback(PEER peer, const char * nick, const char * command, const char * parameters, PEERBool authenticated, void * param); -static void gameStartedCallback(PEER peer, SBServer server, const char *message, void *param); -static void globalKeyChangedCallback(PEER peer, const char *nick, const char *key, const char *val, void *param); -static void roomKeyChangedCallback(PEER peer, RoomType roomType, const char *nick, const char *key, const char *val, void *param); - -// convenience function to set buddy status -static void updateBuddyStatus( GameSpyBuddyStatus status, Int groupRoom = 0, std::string gameName = "" ) -{ - if (!TheGameSpyBuddyMessageQueue) - return; - - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_SETSTATUS; - switch(status) - { - case BUDDY_OFFLINE: - req.arg.status.status = GP_OFFLINE; - strcpy(req.arg.status.statusString, "Offline"); - strcpy(req.arg.status.locationString, ""); - break; - case BUDDY_ONLINE: - req.arg.status.status = GP_ONLINE; - strcpy(req.arg.status.statusString, "Online"); - strcpy(req.arg.status.locationString, ""); - break; - case BUDDY_LOBBY: - req.arg.status.status = GP_CHATTING; - strcpy(req.arg.status.statusString, "Chatting"); - sprintf(req.arg.status.locationString, "%d", groupRoom); - break; - case BUDDY_STAGING: - req.arg.status.status = GP_STAGING; - strcpy(req.arg.status.statusString, "Staging"); - sprintf(req.arg.status.locationString, "%s", gameName.c_str()); - break; - case BUDDY_LOADING: - req.arg.status.status = GP_PLAYING; - strcpy(req.arg.status.statusString, "Loading"); - sprintf(req.arg.status.locationString, "%s", gameName.c_str()); - break; - case BUDDY_PLAYING: - req.arg.status.status = GP_PLAYING; - strcpy(req.arg.status.statusString, "Playing"); - sprintf(req.arg.status.locationString, "%s", gameName.c_str()); - break; - case BUDDY_MATCHING: - req.arg.status.status = GP_ONLINE; - strcpy(req.arg.status.statusString, "Matching"); - strcpy(req.arg.status.locationString, ""); - break; - } - DEBUG_LOG(("updateBuddyStatus %d:%s\n", req.arg.status.status, req.arg.status.statusString)); - TheGameSpyBuddyMessageQueue->addRequest(req); -} - -static void createRoomCallback(PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, void *param) -{ - Int *s = (Int *)param; - if (s) - *s = result; -} - -static const char * KeyTypeToString(qr2_key_type type) -{ - switch(type) - { - case key_server: - return "server"; - case key_player: - return "player"; - case key_team: - return "team"; - } - - return "Unkown key type"; -} - -static const char * ErrorTypeToString(qr2_error_t error) -{ - switch(error) - { - case e_qrnoerror: - return "noerror"; - case e_qrwsockerror: - return "wsockerror"; - case e_qrbinderror: - return "rbinderror"; - case e_qrdnserror: - return "dnserror"; - case e_qrconnerror: - return "connerror"; - } - - return "Unknown error type"; -} - -static void QRServerKeyCallback -( - PEER peer, - int key, - qr2_buffer_t buffer, - void * param -) -{ - //DEBUG_LOG(("QR_SERVER_KEY | %d (%s)\n", key, qr2_registered_key_list[key])); - PeerThreadClass *t = (PeerThreadClass *)param; - if (!t) - { - DEBUG_LOG(("QRServerKeyCallback: bailing because of no thread info\n")); - return; - } - - if (!t->isHosting()) - t->stopHostingAlready(peer); - -#ifdef DEBUG_LOGGING - AsciiString val = ""; -#define ADD(x) { qr2_buffer_add(buffer, x); val = x; } -#define ADDINT(x) { qr2_buffer_add_int(buffer, x); val.format("%d",x); } -#else -#define ADD(x) { qr2_buffer_add(buffer, x); } -#define ADDINT(x) { qr2_buffer_add_int(buffer, x); } -#endif - - switch(key) - { - case HOSTNAME_KEY: - ADD(t->getPlayerName(0).c_str()); - break; - case GAMEVER_KEY: - ADDINT(t->gameVersion()); - break; - case EXECRC_KEY: - ADDINT(t->exeCRC()); - break; - case INICRC_KEY: - ADDINT(t->iniCRC()); - break; - case GAMENAME_KEY: - { - std::string tmp = t->getPlayerName(0); - tmp.append(" "); - tmp.append(WideCharStringToMultiByte(t->getLocalStagingServerName().c_str())); - ADD(tmp.c_str()); - } - break; - case MAPNAME_KEY: - ADD(t->getMapName().c_str()); - break; - case PW_KEY: - ADDINT(t->hasPassword()); - break; - case OBS_KEY: - ADDINT(t->allowObservers()); - break; - case USE_STATS_KEY: - ADDINT(t->useStats()); - break; - case LADIP_KEY: - ADD(t->ladderIP().c_str()); - break; - case LADPORT_KEY: - ADDINT(t->ladderPort()); - break; - case PINGSTR_KEY: - ADD(t->pingStr().c_str()); - break; - case NUMPLAYER_KEY: - ADDINT(t->getNumPlayers()); - break; - case MAXPLAYER_KEY: - ADDINT(t->getMaxPlayers()); - break; - case NUMOBS_KEY: - ADDINT(t->getNumObservers()); - break; - default: - ADD(""); - //DEBUG_LOG(("QR_SERVER_KEY | %d (%s)\n", key, qr2_registered_key_list[key])); - break; - } - - DEBUG_LOG(("QR_SERVER_KEY | %d (%s) = [%s]\n", key, qr2_registered_key_list[key], val.str())); -} - -static void QRPlayerKeyCallback -( - PEER peer, - int key, - int index, - qr2_buffer_t buffer, - void * param -) -{ - //DEBUG_LOG(("QR_PLAYER_KEY | %d | %d (%s)\n", key, index, qr2_registered_key_list[key])); - PeerThreadClass *t = (PeerThreadClass *)param; - if (!t) - { - DEBUG_LOG(("QRPlayerKeyCallback: bailing because of no thread info\n")); - return; - } - - if (!t->isHosting()) - t->stopHostingAlready(peer); - -#undef ADD -#undef ADDINT -#ifdef DEBUG_LOGGING - AsciiString val = ""; -#define ADD(x) { qr2_buffer_add(buffer, x); val = x; } -#define ADDINT(x) { qr2_buffer_add_int(buffer, x); val.format("%d",x); } -#else -#define ADD(x) { qr2_buffer_add(buffer, x); } -#define ADDINT(x) { qr2_buffer_add_int(buffer, x); } -#endif - - switch(key) - { - case NAME__KEY: - ADD(t->getPlayerName(index).c_str()); - break; - case WINS__KEY: - ADDINT(t->getPlayerWins(index)); - break; - case LOSSES__KEY: - ADDINT(t->getPlayerLosses(index)); - break; - case PID__KEY: - ADDINT(t->getPlayerProfileID(index)); - break; - case FACTION__KEY: - ADDINT(t->getPlayerLosses(index)); - break; - case COLOR__KEY: - ADDINT(t->getPlayerLosses(index)); - break; - default: - ADD(""); - //DEBUG_LOG(("QR_PLAYER_KEY | %d | %d (%s)\n", key, index, qr2_registered_key_list[key])); - break; - } - - DEBUG_LOG(("QR_PLAYER_KEY | %d | %d (%s) = [%s]\n", key, index, qr2_registered_key_list[key], val.str())); -} - -static void QRTeamKeyCallback -( - PEER peer, - int key, - int index, - qr2_buffer_t buffer, - void * param -) -{ - //DEBUG_LOG(("QR_TEAM_KEY | %d | %d\n", key, index)); - - PeerThreadClass *t = (PeerThreadClass *)param; - if (!t) - { - DEBUG_LOG(("QRTeamKeyCallback: bailing because of no thread info\n")); - return; - } - if (!t->isHosting()) - t->stopHostingAlready(peer); - - // we don't report teams, so this shouldn't get called - qr2_buffer_add(buffer, ""); -} - -static void QRKeyListCallback -( - PEER peer, - qr2_key_type type, - qr2_keybuffer_t keyBuffer, - void * param -) -{ - DEBUG_LOG(("QR_KEY_LIST | %s\n", KeyTypeToString(type))); - - /* - PeerThreadClass *t = (PeerThreadClass *)param; - if (!t) - { - DEBUG_LOG(("QRKeyListCallback: bailing because of no thread info\n")); - return; - } - if (!t->isHosting()) - t->stopHostingAlready(peer); - */ - - // register the keys we use - switch(type) - { - case key_server: - qr2_keybuffer_add(keyBuffer, HOSTNAME_KEY); - qr2_keybuffer_add(keyBuffer, GAMEVER_KEY); - //qr2_keybuffer_add(keyBuffer, GAMENAME_KEY); - qr2_keybuffer_add(keyBuffer, MAPNAME_KEY); - qr2_keybuffer_add(keyBuffer, EXECRC_KEY); - qr2_keybuffer_add(keyBuffer, INICRC_KEY); - qr2_keybuffer_add(keyBuffer, PW_KEY); - qr2_keybuffer_add(keyBuffer, OBS_KEY); - qr2_keybuffer_add(keyBuffer, USE_STATS_KEY); - qr2_keybuffer_add(keyBuffer, LADIP_KEY); - qr2_keybuffer_add(keyBuffer, LADPORT_KEY); - qr2_keybuffer_add(keyBuffer, PINGSTR_KEY); - qr2_keybuffer_add(keyBuffer, NUMPLAYER_KEY); - qr2_keybuffer_add(keyBuffer, MAXPLAYER_KEY); - qr2_keybuffer_add(keyBuffer, NUMOBS_KEY); - break; - case key_player: - qr2_keybuffer_add(keyBuffer, NAME__KEY); - qr2_keybuffer_add(keyBuffer, WINS__KEY); - qr2_keybuffer_add(keyBuffer, LOSSES__KEY); - qr2_keybuffer_add(keyBuffer, PID__KEY); - qr2_keybuffer_add(keyBuffer, FACTION__KEY); - qr2_keybuffer_add(keyBuffer, COLOR__KEY); - break; - case key_team: - // no custom team keys - break; - } -} - -static int QRCountCallback -( - PEER peer, - qr2_key_type type, - void * param -) -{ - PeerThreadClass *t = (PeerThreadClass *)param; - if (!t) - { - DEBUG_LOG(("QRCountCallback: bailing because of no thread info\n")); - return 0; - } - if (!t->isHosting()) - t->stopHostingAlready(peer); - - if(type == key_player) - { - DEBUG_LOG(("QR_COUNT | %s = %d\n", KeyTypeToString(type), t->getNumPlayers() + t->getNumObservers())); - return t->getNumPlayers() + t->getNumObservers(); - } - else if(type == key_team) - { - DEBUG_LOG(("QR_COUNT | %s = %d\n", KeyTypeToString(type), 0)); - return 0; - } - - DEBUG_LOG(("QR_COUNT | %s = %d\n", KeyTypeToString(type), 0)); - return 0; -} - -void PeerThreadClass::stopHostingAlready(PEER peer) -{ - isThreadHosting = 0; // debugging - s_lastStateChangedHeartbeat = 0; - s_wantStateChangedHeartbeat = FALSE; - peerStopGame(peer); - if (qr2Sock != INVALID_SOCKET) - { - closesocket(qr2Sock); - qr2Sock = INVALID_SOCKET; - } -} - -static void QRAddErrorCallback -( - PEER peer, - qr2_error_t error, - char * errorString, - void * param -) -{ - DEBUG_LOG(("QR_ADD_ERROR | %s | %s\n", ErrorTypeToString(error), errorString)); - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_FAILEDTOHOST; - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -static void QRNatNegotiateCallback -( - PEER peer, - int cookie, - void * param -) -{ - DEBUG_LOG(("QR_NAT_NEGOTIATE | 0x%08X\n", cookie)); -} - -static void KickedCallback -( - PEER peer, - RoomType roomType, - const char * nick, - const char * reason, - void * param -) -{ - DEBUG_LOG(("Kicked from %d by %s: \"%s\"\n", roomType, nick, reason)); -} - -static void NewPlayerListCallback -( - PEER peer, - RoomType roomType, - void * param -) -{ - DEBUG_LOG(("NewPlayerListCallback\n")); -} - -static void AuthenticateCDKeyCallback -( - PEER peer, - int result, - const char * message, - void * param -) -{ - DEBUG_LOG(("CD Key Result: %s (%d) %X\n", message, result, param)); -#ifdef SERVER_DEBUGGING - CheckServers(peer); -#endif // SERVER_DEBUGGING - SerialAuthResult *val = (SerialAuthResult *)param; - if (val) - { - if (result >= 1) - { - *val = SERIAL_OK; - } - else - { - *val = SERIAL_AUTHFAILED; - } - } -#ifdef SERVER_DEBUGGING - CheckServers(peer); -#endif // SERVER_DEBUGGING -} - -static SerialAuthResult doCDKeyAuthentication( PEER peer ) -{ - SerialAuthResult retval = SERIAL_NONEXISTENT; - if (!peer) - return retval; - - AsciiString s = ""; - if (GetStringFromRegistry("\\ergc", "", s) && s.isNotEmpty()) - { -#ifdef SERVER_DEBUGGING - DEBUG_LOG(("Before peerAuthenticateCDKey()\n")); - CheckServers(peer); -#endif // SERVER_DEBUGGING - peerAuthenticateCDKey(peer, s.str(), AuthenticateCDKeyCallback, &retval, PEERTrue); -#ifdef SERVER_DEBUGGING - DEBUG_LOG(("After peerAuthenticateCDKey()\n")); - CheckServers(peer); -#endif // SERVER_DEBUGGING - } - - if (retval == SERIAL_OK) - { - PSRequest req; - req.requestType = PSRequest::PSREQUEST_READCDKEYSTATS; - req.cdkey = s.str(); - TheGameSpyPSMessageQueue->addRequest(req); - } - - return retval; -} - -#define INBUF_LEN 256 -void checkQR2Queries( PEER peer, SOCKET sock ) -{ - static char indata[INBUF_LEN]; - struct sockaddr_in saddr; - int saddrlen = sizeof(struct sockaddr_in); - fd_set set; - struct timeval timeout = {0,0}; - int error; - - FD_ZERO ( &set ); - FD_SET ( sock, &set ); - - while (1) - { - error = select(FD_SETSIZE, &set, NULL, NULL, &timeout); - if (SOCKET_ERROR == error || 0 == error) - return; - //else we have data - error = recvfrom(sock, indata, INBUF_LEN - 1, 0, (struct sockaddr *)&saddr, &saddrlen); - if (error != SOCKET_ERROR) - { - indata[error] = '\0'; - peerParseQuery( peer, indata, error, (sockaddr *)&saddr ); - } - } -} - -static UnsignedInt localIP = 0; - -void PeerThreadClass::Thread_Function() -{ - try { - _set_se_translator( DumpExceptionInfo ); // Hook that allows stack trace. - - PEER peer; - - // Setup the callbacks. - /////////////////////// - PEERCallbacks callbacks; - memset(&callbacks, 0, sizeof(PEERCallbacks)); - callbacks.disconnected = disconnectedCallback; - //callbacks.readyChanged = readyChangedCallback; - callbacks.roomMessage = roomMessageCallback; - callbacks.playerMessage = playerMessageCallback; - callbacks.gameStarted = gameStartedCallback; - callbacks.playerJoined = playerJoinedCallback; - callbacks.playerLeft = playerLeftCallback; - callbacks.playerChangedNick = playerChangedNickCallback; - callbacks.playerFlagsChanged = playerFlagsChangedCallback; - callbacks.playerInfo = playerInfoCallback; - callbacks.roomUTM = roomUTMCallback; - callbacks.playerUTM = playerUTMCallback; - callbacks.globalKeyChanged = globalKeyChangedCallback; - callbacks.roomKeyChanged = roomKeyChangedCallback; - - callbacks.qrServerKey = QRServerKeyCallback; - callbacks.qrPlayerKey = QRPlayerKeyCallback; - callbacks.qrTeamKey = QRTeamKeyCallback; - callbacks.qrKeyList = QRKeyListCallback; - callbacks.qrCount = QRCountCallback; - callbacks.qrAddError = QRAddErrorCallback; - callbacks.qrNatNegotiateCallback = QRNatNegotiateCallback; - - callbacks.kicked = KickedCallback; - callbacks.newPlayerList = NewPlayerListCallback; - - callbacks.param = this; - - m_qmGroupRoom = 0; - - peer = peerInitialize( &callbacks ); - DEBUG_ASSERTCRASH( peer != NULL, ("NULL peer!") ); - m_isConnected = m_isConnecting = false; - - qr2_register_key(EXECRC_KEY, EXECRC_STR); - qr2_register_key(INICRC_KEY, INICRC_STR); - qr2_register_key(PW_KEY, PW_STR); - qr2_register_key(OBS_KEY, OBS_STR); - qr2_register_key(USE_STATS_KEY, USE_STATS_STR); - qr2_register_key(LADIP_KEY, LADIP_STR); - qr2_register_key(LADPORT_KEY, LADPORT_STR); - qr2_register_key(PINGSTR_KEY, PINGSTR_STR); - qr2_register_key(NUMOBS_KEY, NUMOBS_STR); - qr2_register_key(NUMPLAYER_KEY, NUMPLAYER_STR); - qr2_register_key(MAXPLAYER_KEY, MAXPLAYER_STR); - qr2_register_key(NAME__KEY, NAME__STR "_"); - qr2_register_key(WINS__KEY, WINS__STR "_"); - qr2_register_key(LOSSES__KEY, LOSSES__STR "_"); - qr2_register_key(FACTION__KEY, FACTION__STR "_"); - qr2_register_key(COLOR__KEY, COLOR__STR "_"); - - const Int NumKeys = 15; - unsigned char allKeysArray[NumKeys] = { - /* - PID__KEY, - NAME__KEY, - WINS__KEY, - LOSSES__KEY, - FACTION__KEY, - COLOR__KEY, - */ - MAPNAME_KEY, - GAMEVER_KEY, - GAMENAME_KEY, - EXECRC_KEY, - INICRC_KEY, - PW_KEY, - OBS_KEY, - USE_STATS_KEY, - LADIP_KEY, - LADPORT_KEY, - PINGSTR_KEY, - NUMOBS_KEY, - NUMPLAYER_KEY, - MAXPLAYER_KEY, - HOSTNAME_KEY - }; - - /* - const char *allKeys = "\\pid_\\mapname\\gamever\\gamename" \ - "\\" EXECRC_STR "\\" INICRC_STR \ - "\\" PW_STR "\\" OBS_STR "\\" USE_STATS_STR "\\" LADIP_STR "\\" LADPORT_STR \ - "\\" PINGSTR_STR "\\" NUMOBS_STR \ - "\\" NUMPLAYER_STR "\\" MAXPLAYER_STR \ - "\\" NAME__STR "_" "\\" WINS__STR "_" "\\" LOSSES__STR "_" "\\" FACTION__STR "_" "\\" COLOR__STR "_"; - */ - - const char * key = "username"; - peerSetRoomWatchKeys(peer, StagingRoom, 1, &key, PEERTrue); - peerSetRoomWatchKeys(peer, GroupRoom, 1, &key, PEERTrue); - - m_localRoomID = 0; - m_localStagingServerName = L""; - - m_qmStatus = QM_IDLE; - - // Setup which rooms to do pings and cross-pings in. - //////////////////////////////////////////////////// - PEERBool pingRooms[NumRooms]; - PEERBool crossPingRooms[NumRooms]; - pingRooms[TitleRoom] = PEERFalse; - pingRooms[GroupRoom] = PEERFalse; - pingRooms[StagingRoom] = PEERFalse; - crossPingRooms[TitleRoom] = PEERFalse; - crossPingRooms[GroupRoom] = PEERFalse; - crossPingRooms[StagingRoom] = PEERFalse; - - /********* - First step, set our game authentication info - We could do: - strcpy(gcd_gamename,"ccgenzh"); - strcpy(gcd_secret_key,"D6s9k3"); - or - strcpy(gcd_gamename,"ccgeneralsb"); - strcpy(gcd_secret_key,"whatever the key is"); - ...but this is more secure: - **********/ - char gameName[12] = {0}; - char secretKey[7] = {0}; - /** - gameName[0]='c';gameName[1]='c';gameName[2]='g';gameName[3]='e'; - gameName[4]='n';gameName[5]='e';gameName[6]='r';gameName[7]='a'; - gameName[8]='l';gameName[9]='s';gameName[10]='b';gameName[11]='\0'; - secretKey[0]='g';secretKey[1]='3';secretKey[2]='T';secretKey[3]='9'; - secretKey[4]='s';secretKey[5]='2';secretKey[6]='\0'; - /**/ - gameName[0]='c';gameName[1]='c';gameName[2]='g';gameName[3]='e'; - gameName[4]='n';gameName[5]='z';gameName[6]='h';gameName[7]='\0'; - secretKey[0]='D';secretKey[1]='6';secretKey[2]='s';secretKey[3]='9'; - secretKey[4]='k';secretKey[5]='3';secretKey[6]='\0'; - /**/ - - // Set the title. - ///////////////// - if(!peerSetTitle( peer , gameName, secretKey, gameName, secretKey, GetRegistryVersion(), 30, PEERTrue, pingRooms, crossPingRooms)) - { - DEBUG_CRASH(("Error setting title")); - peerShutdown( peer ); - peer = NULL; - return; - } - - OptionPreferences pref; - UnsignedInt preferredIP = INADDR_ANY; - UnsignedInt selectedIP = pref.getOnlineIPAddress(); - DEBUG_LOG(("Looking for IP %X\n", selectedIP)); - IPEnumeration IPs; - EnumeratedIP *IPlist = IPs.getAddresses(); - while (IPlist) - { - DEBUG_LOG(("Looking at IP %s\n", IPlist->getIPstring().str())); - if (selectedIP == IPlist->getIP()) - { - preferredIP = IPlist->getIP(); - DEBUG_LOG(("Connecting to GameSpy chat server via IP address %8.8X\n", preferredIP)); - break; - } - IPlist = IPlist->getNext(); - } - //chatSetLocalIP(preferredIP); //Aliendroid1: Disabled because it is not supported by the GameSpy implementation we are using - - UnsignedInt preferredQRPort = 0; - AsciiString selectedQRPort = pref["GameSpyQRPort"]; - if (selectedQRPort.isNotEmpty()) - { - preferredQRPort = atoi(selectedQRPort.str()); - } - - PeerRequest incomingRequest; - while ( running ) - { - // deal with requests - if (TheGameSpyPeerMessageQueue->getRequest(incomingRequest)) - { - DEBUG_LOG(("TheGameSpyPeerMessageQueue->getRequest() got request of type %d\n", incomingRequest.peerRequestType)); - switch (incomingRequest.peerRequestType) - { - case PeerRequest::PEERREQUEST_LOGIN: - { - m_isConnecting = true; - m_originalName = incomingRequest.nick; - m_loginName = incomingRequest.nick; - m_profileID = incomingRequest.login.profileID; - m_password = incomingRequest.password; - m_email = incomingRequest.email; - peerConnect( peer, incomingRequest.nick.c_str(), incomingRequest.login.profileID, nickErrorCallbackWrapper, connectCallbackWrapper, this, PEERTrue ); -#ifdef SERVER_DEBUGGING - DEBUG_LOG(("After peerConnect()\n")); - CheckServers(peer); -#endif // SERVER_DEBUGGING - if (m_isConnected) - { - SerialAuthResult ret = doCDKeyAuthentication( peer ); - if (ret != SERIAL_OK) - { - m_isConnecting = m_isConnected = false; - MESSAGE_QUEUE->setSerialAuthResult( ret ); - peerDisconnect( peer ); - } - } - m_isConnecting = false; - - // check our connection - //if (m_isConnected) - //{ - // GetLocalChatConnectionAddress("peerchat.gamespy.com", 6667, localIP); - //} - } - - break; - - case PeerRequest::PEERREQUEST_LOGOUT: - m_isConnecting = m_isConnected = false; - peerDisconnect( peer ); - break; - - case PeerRequest::PEERREQUEST_JOINGROUPROOM: - m_groupRoomID = incomingRequest.groupRoom.id; - isThreadHosting = 0; // debugging - s_lastStateChangedHeartbeat = 0; - s_wantStateChangedHeartbeat = FALSE; - peerStopGame( peer ); - peerLeaveRoom( peer, GroupRoom, NULL ); - peerLeaveRoom( peer, StagingRoom, NULL ); - if (qr2Sock != INVALID_SOCKET) - { - closesocket(qr2Sock); - qr2Sock = INVALID_SOCKET; - } - m_isHosting = false; - m_localRoomID = m_groupRoomID; - DEBUG_LOG(("Requesting to join room %d in thread %X\n", m_localRoomID, this)); - peerJoinGroupRoom( peer, incomingRequest.groupRoom.id, joinRoomCallback, (void *)this, PEERTrue ); - break; - - case PeerRequest::PEERREQUEST_LEAVEGROUPROOM: - m_groupRoomID = 0; - updateBuddyStatus( BUDDY_ONLINE ); - peerLeaveRoom( peer, GroupRoom, NULL ); - peerLeaveRoom( peer, StagingRoom, NULL ); m_isHosting = false; - break; - - case PeerRequest::PEERREQUEST_JOINSTAGINGROOM: - { - m_groupRoomID = 0; - updateBuddyStatus( BUDDY_ONLINE ); - peerLeaveRoom( peer, GroupRoom, NULL ); - peerLeaveRoom( peer, StagingRoom, NULL ); m_isHosting = false; - SBServer server = findServerByID(incomingRequest.stagingRoom.id); - m_localStagingServerName = incomingRequest.text; - DEBUG_LOG(("Setting m_localStagingServerName to [%ls]\n", m_localStagingServerName.c_str())); - m_localRoomID = incomingRequest.stagingRoom.id; - DEBUG_LOG(("Requesting to join room %d\n", m_localRoomID)); - if (server) - { - peerJoinStagingRoom( peer, server, incomingRequest.password.c_str(), joinRoomCallback, (void *)this, PEERTrue ); - } - else - { - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_JOINSTAGINGROOM; - resp.joinStagingRoom.id = incomingRequest.stagingRoom.id; - resp.joinStagingRoom.ok = FALSE; - resp.joinStagingRoom.result = PEERJoinFailed; - TheGameSpyPeerMessageQueue->addResponse(resp); - } - } - break; - - case PeerRequest::PEERREQUEST_LEAVESTAGINGROOM: - m_groupRoomID = 0; - updateBuddyStatus( BUDDY_ONLINE ); - peerLeaveRoom( peer, GroupRoom, NULL ); - peerLeaveRoom( peer, StagingRoom, NULL ); - isThreadHosting = 0; // debugging - s_lastStateChangedHeartbeat = 0; - s_wantStateChangedHeartbeat = FALSE; - if (m_isHosting) - { - peerStopGame( peer ); - if (qr2Sock != INVALID_SOCKET) - { - closesocket(qr2Sock); - qr2Sock = INVALID_SOCKET; - } - m_isHosting = false; - } - break; - - case PeerRequest::PEERREQUEST_MESSAGEPLAYER: - { - std::string s = WideCharStringToMultiByte(incomingRequest.text.c_str()); - peerMessagePlayer( peer, incomingRequest.nick.c_str(), s.c_str(), (incomingRequest.message.isAction)?ActionMessage:NormalMessage ); - } - break; - - case PeerRequest::PEERREQUEST_MESSAGEROOM: - { - std::string s = WideCharStringToMultiByte(incomingRequest.text.c_str()); - peerMessageRoom( peer, (m_groupRoomID)?GroupRoom:StagingRoom, s.c_str(), (incomingRequest.message.isAction)?ActionMessage:NormalMessage ); - } - break; - - case PeerRequest::PEERREQUEST_PUSHSTATS: - { - DEBUG_LOG(("PEERREQUEST_PUSHSTATS: stats are %d,%d,%d,%d,%d,%d\n", - incomingRequest.statsToPush.locale, incomingRequest.statsToPush.wins, incomingRequest.statsToPush.losses, incomingRequest.statsToPush.rankPoints, incomingRequest.statsToPush.side, incomingRequest.statsToPush.preorder)); - - // Testing alternate way to push stats -#ifdef USE_BROADCAST_KEYS - _snprintf(s_valueBuffers[0], 20, "%d", incomingRequest.statsToPush.locale); - _snprintf(s_valueBuffers[1], 20, "%d", incomingRequest.statsToPush.wins); - _snprintf(s_valueBuffers[2], 20, "%d", incomingRequest.statsToPush.losses); - _snprintf(s_valueBuffers[3], 20, "%d", incomingRequest.statsToPush.rankPoints); - _snprintf(s_valueBuffers[4], 20, "%d", incomingRequest.statsToPush.side); - _snprintf(s_valueBuffers[5], 20, "%d", incomingRequest.statsToPush.preorder); - pushStatsToRoom(peer); -#else - const char *keys[6] = { "locale", "wins", "losses", "points", "side", "pre" }; - char valueStrings[6][20]; - char *values[6] = { valueStrings[0], valueStrings[1], valueStrings[2], - valueStrings[3], valueStrings[4], valueStrings[5]}; - _snprintf(values[0], 20, "%d", incomingRequest.statsToPush.locale); - _snprintf(values[1], 20, "%d", incomingRequest.statsToPush.wins); - _snprintf(values[2], 20, "%d", incomingRequest.statsToPush.losses); - _snprintf(values[3], 20, "%d", incomingRequest.statsToPush.rankPoints); - _snprintf(values[4], 20, "%d", incomingRequest.statsToPush.side); - _snprintf(values[5], 20, "%d", incomingRequest.statsToPush.preorder); - peerSetGlobalKeys(peer, 6, (const char **)keys, (const char **)values); - peerSetGlobalWatchKeys(peer, GroupRoom, 0, NULL, PEERFalse); - peerSetGlobalWatchKeys(peer, StagingRoom, 0, NULL, PEERFalse); - peerSetGlobalWatchKeys(peer, GroupRoom, 6, keys, PEERTrue); - peerSetGlobalWatchKeys(peer, StagingRoom, 6, keys, PEERTrue); -#endif - } - break; - - case PeerRequest::PEERREQUEST_SETGAMEOPTIONS: - { - m_mapName = incomingRequest.gameOptsMapName; - m_numPlayers = incomingRequest.gameOptions.numPlayers; - m_numObservers = incomingRequest.gameOptions.numObservers; - m_maxPlayers = incomingRequest.gameOptions.maxPlayers; - DEBUG_LOG(("peerStateChanged(): Marking game options state as changed - %d players, %d observers\n", m_numPlayers, m_numObservers)); - for (Int i=0; iaddResponse(resp); - - if (res != PEERJoinSuccess && res != PEERAlreadyInRoom) - { - m_localRoomID = oldGroupID; - DEBUG_LOG(("Requesting to join room %d\n", m_localRoomID)); - if (incomingRequest.stagingRoomCreation.restrictGameList) - { - peerLeaveRoom( peer, StagingRoom, NULL ); - } - else - { - peerJoinGroupRoom( peer, oldGroupID, joinRoomCallback, (void *)this, PEERTrue ); - } - m_isHosting = FALSE; - m_localStagingServerName = L""; - m_playerNames[0] = ""; - } - else - { - if (incomingRequest.stagingRoomCreation.restrictGameList) - { - peerLeaveRoom( peer, GroupRoom, NULL ); - } - isThreadHosting = 1; // debugging - s_lastStateChangedHeartbeat = timeGetTime(); // wait the full interval before updating state - s_wantStateChangedHeartbeat = FALSE; - m_isHosting = TRUE; - m_allowObservers = incomingRequest.stagingRoomCreation.allowObservers; - m_useStats = incomingRequest.stagingRoomCreation.useStats; - m_mapName = ""; - for (Int i=0; i 0) - m_hasPassword = true; - else - m_hasPassword = false; - m_playerNames[0] = m_loginName; - m_exeCRC = incomingRequest.stagingRoomCreation.exeCRC; - m_iniCRC = incomingRequest.stagingRoomCreation.iniCRC; - m_gameVersion = incomingRequest.stagingRoomCreation.gameVersion; - m_localStagingServerName = incomingRequest.text; - m_ladderIP = incomingRequest.ladderIP; - m_pingStr = incomingRequest.hostPingStr; - m_ladderPort = incomingRequest.stagingRoomCreation.ladPort; - -#ifdef USE_BROADCAST_KEYS - pushStatsToRoom(peer); -#endif // USE_BROADCAST_KEYS - - DEBUG_LOG(("Setting m_localStagingServerName to [%ls]\n", m_localStagingServerName.c_str())); - updateBuddyStatus( BUDDY_STAGING, 0, WideCharStringToMultiByte(m_localStagingServerName.c_str()) ); - } - } - break; - - case PeerRequest::PEERREQUEST_STARTGAMELIST: - { - m_sawCompleteGameList = FALSE; - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_STAGINGROOM; - resp.stagingRoom.action = PEER_CLEAR; - resp.stagingRoom.isStaging = TRUE; - resp.stagingRoom.percentComplete = 0; - clearServers(); - TheGameSpyPeerMessageQueue->addResponse(resp); - peerStartListingGames( peer, allKeysArray, NumKeys, (incomingRequest.gameList.restrictGameList?"~":NULL), listingGamesCallback, this ); - } - break; - - case PeerRequest::PEERREQUEST_STOPGAMELIST: - { - peerStopListingGames( peer ); - } - break; - - case PeerRequest::PEERREQUEST_STARTGAME: - { - peerStartGame( peer, NULL, PEER_STOP_REPORTING); - } - break; - - case PeerRequest::PEERREQUEST_UTMPLAYER: - { - if (incomingRequest.nick.length() > 0) - { - peerUTMPlayer( peer, incomingRequest.nick.c_str(), incomingRequest.id.c_str(), incomingRequest.options.c_str(), PEERFalse ); - } - } - break; - - case PeerRequest::PEERREQUEST_UTMROOM: - { - peerUTMRoom( peer, (incomingRequest.UTM.isStagingRoom)?StagingRoom:GroupRoom, incomingRequest.id.c_str(), incomingRequest.options.c_str(), PEERFalse ); - } - break; - - case PeerRequest::PEERREQUEST_STARTQUICKMATCH: - { - m_qmInfo = incomingRequest; - doQuickMatch( peer ); - } - break; - - } - } - - if (isThreadHosting && s_wantStateChangedHeartbeat) - { - UnsignedInt now = timeGetTime(); - if (now > s_lastStateChangedHeartbeat + s_heartbeatInterval) - { - s_lastStateChangedHeartbeat = now; - s_wantStateChangedHeartbeat = FALSE; - peerStateChanged( peer ); - -#ifdef DEBUG_LOGGING - static UnsignedInt prev = 0; - UnsignedInt now = timeGetTime(); - UnsignedInt diff = now - prev; - prev = now; -#endif - STATECHANGED_LOG(("peerStateChanged() at time %d (difference of %d ms)\n", now, diff)); - } - } - - // update the network - PEERBool isConnected = PEERTrue; - isConnected = peerIsConnected( peer ); - if ( isConnected == PEERTrue ) - { - if (qr2Sock != INVALID_SOCKET) - { - // check hosting activity - checkQR2Queries( peer, qr2Sock ); - } - peerThink( peer ); - } - - // end our timeslice - Switch_Thread(); - } - - DEBUG_LOG(("voluntarily ending peer thread %d\n", running)); - peerShutdown( peer ); - - } catch ( ... ) { - DEBUG_CRASH(("Exception in peer thread!")); - - try { - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT; - resp.discon.reason = DISCONNECT_LOSTCON; - TheGameSpyPeerMessageQueue->addResponse(resp); - } - catch (...) - { - } - } -} - -static void qmProfileIDCallback( PEER peer, PEERBool success, const char *nick, int profileID, void *param ) -{ - Int *i = (Int *)param; - if (!i || !success || !nick) - return; - - *i = profileID; -} - -static Int matchbotProfileID = 0; -void quickmatchEnumPlayersCallback( PEER peer, PEERBool success, RoomType roomType, int index, const char * nick, int flags, void * param ) -{ - PeerThreadClass *t = (PeerThreadClass *)param; - if (!t || !success || nick == NULL || nick[0] == '\0') - { - t->sawEndOfEnumPlayers(); - return; - } - - Int id = 0; - peerGetPlayerProfileID(peer, nick, qmProfileIDCallback, &id, PEERTrue); - DEBUG_LOG(("Saw player %s with id %d (looking for %d)\n", nick, id, matchbotProfileID)); - if (id == matchbotProfileID) - { - t->sawMatchbot(nick); - } - - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERJOIN; - resp.nick = nick; - resp.player.roomType = roomType; - resp.player.IP = 0; - - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -void PeerThreadClass::handleQMMatch(PEER peer, Int mapIndex, Int seed, - char *playerName[MAX_SLOTS], - char *playerIP[MAX_SLOTS], - char *playerSide[MAX_SLOTS], - char *playerColor[MAX_SLOTS], - char *playerNAT[MAX_SLOTS]) -{ - if (m_qmStatus == QM_WORKING) - { - m_qmStatus = QM_MATCHED; - peerLeaveRoom(peer, GroupRoom, ""); - - for (Int i=0; iaddResponse(resp); - } -} - -void PeerThreadClass::doQuickMatch( PEER peer ) -{ - m_qmStatus = QM_JOININGQMCHANNEL; - Bool done = false; - matchbotProfileID = m_qmInfo.QM.botID; - setQMGroupRoom( m_qmInfo.QM.roomID ); - m_sawMatchbot = false; - updateBuddyStatus( BUDDY_MATCHING ); - while (!done && running) - { - if (!peerIsConnected( peer )) - { - done = true; - } - else - { - // update the network - peerThink( peer ); - - // end our timeslice - Switch_Thread(); - - PeerRequest incomingRequest; - if (TheGameSpyPeerMessageQueue->getRequest(incomingRequest)) - { - switch (incomingRequest.peerRequestType) - { - case PeerRequest::PEERREQUEST_WIDENQUICKMATCHSEARCH: - { - if (m_qmStatus != QM_IDLE && m_qmStatus != QM_STOPPED && m_sawMatchbot) - { - peerMessagePlayer( peer, m_matchbotName.c_str(), "\\WIDEN", NormalMessage ); - } - } - break; - case PeerRequest::PEERREQUEST_STOPQUICKMATCH: - { - m_qmStatus = QM_STOPPED; - peerLeaveRoom(peer, GroupRoom, ""); - done = true; - } - break; - case PeerRequest::PEERREQUEST_LOGOUT: - { - m_qmStatus = QM_STOPPED; - peerLeaveRoom(peer, GroupRoom, ""); - done = true; - } - break; - case PeerRequest::PEERREQUEST_LEAVEGROUPROOM: - { - m_qmStatus = QM_STOPPED; - peerLeaveRoom(peer, GroupRoom, ""); - done = true; - } - break; - case PeerRequest::PEERREQUEST_UTMPLAYER: - { - peerUTMPlayer( peer, incomingRequest.nick.c_str(), incomingRequest.id.c_str(), incomingRequest.options.c_str(), PEERFalse ); - } - break; - default: - { - DEBUG_CRASH(("Unanticipated request %d to peer thread!", incomingRequest.peerRequestType)); - } - break; - } - } - - if (!done) - { - // do the next bit of QM - switch (m_qmStatus) - { - case QM_JOININGQMCHANNEL: - { - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS; - resp.qmStatus.status = QM_JOININGQMCHANNEL; - TheGameSpyPeerMessageQueue->addResponse(resp); - - m_groupRoomID = m_qmGroupRoom; - peerLeaveRoom( peer, GroupRoom, NULL ); - peerLeaveRoom( peer, StagingRoom, NULL ); m_isHosting = false; - m_localRoomID = m_groupRoomID; - m_roomJoined = false; - DEBUG_LOG(("Requesting to join room %d in thread %X\n", m_localRoomID, this)); - peerJoinGroupRoom( peer, m_localRoomID, joinRoomCallback, (void *)this, PEERTrue ); - if (m_roomJoined) - { - resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS; - resp.qmStatus.status = QM_LOOKINGFORBOT; - TheGameSpyPeerMessageQueue->addResponse(resp); - - m_qmStatus = QM_LOOKINGFORBOT; - m_sawMatchbot = false; - m_sawEndOfEnumPlayers = false; - peerEnumPlayers( peer, GroupRoom, quickmatchEnumPlayersCallback, this ); - } - else - { - resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS; - resp.qmStatus.status = QM_COULDNOTFINDBOT; - TheGameSpyPeerMessageQueue->addResponse(resp); - done = true; - m_qmStatus = QM_STOPPED; - } - } - break; - case QM_LOOKINGFORBOT: - { - if (m_sawEndOfEnumPlayers) - { - if (m_sawMatchbot) - { - char buf[64]; - buf[63] = '\0'; - std::string msg = "\\CINFO"; - _snprintf(buf, 63, "\\Widen\\%d", m_qmInfo.QM.widenTime); - msg.append(buf); - _snprintf(buf, 63, "\\LadID\\%d", m_qmInfo.QM.ladderID); - msg.append(buf); - _snprintf(buf, 63, "\\LadPass\\%d", m_qmInfo.QM.ladderPassCRC); - msg.append(buf); - _snprintf(buf, 63, "\\PointsMin\\%d", m_qmInfo.QM.minPointPercentage); - msg.append(buf); - _snprintf(buf, 63, "\\PointsMax\\%d", m_qmInfo.QM.maxPointPercentage); - msg.append(buf); - _snprintf(buf, 63, "\\Points\\%d", m_qmInfo.QM.points); - msg.append(buf); - _snprintf(buf, 63, "\\Discons\\%d", m_qmInfo.QM.discons); - msg.append(buf); - _snprintf(buf, 63, "\\DisconMax\\%d", m_qmInfo.QM.maxDiscons); - msg.append(buf); - _snprintf(buf, 63, "\\NumPlayers\\%d", m_qmInfo.QM.numPlayers); - msg.append(buf); - _snprintf(buf, 63, "\\Pings\\%s", m_qmInfo.QM.pings); - msg.append(buf); - _snprintf(buf, 63, "\\IP\\%d", ntohl(peerGetLocalIP(peer)));// not ntohl(localIP), as we need EXTERNAL address for proper NAT negotiation! - msg.append(buf); - _snprintf(buf, 63, "\\Side\\%d", m_qmInfo.QM.side); - msg.append(buf); - _snprintf(buf, 63, "\\Color\\%d", m_qmInfo.QM.color); - msg.append(buf); - _snprintf(buf, 63, "\\NAT\\%d", m_qmInfo.QM.NAT); - msg.append(buf); - _snprintf(buf, 63, "\\EXE\\%d", m_qmInfo.QM.exeCRC); - msg.append(buf); - _snprintf(buf, 63, "\\INI\\%d", m_qmInfo.QM.iniCRC); - msg.append(buf); - buf[0] = 0; - msg.append("\\Maps\\"); - for (Int i=0; iaddResponse(resp); - } - else - { - // no QM bot. Bail. - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS; - resp.qmStatus.status = QM_COULDNOTFINDBOT; - TheGameSpyPeerMessageQueue->addResponse(resp); - - m_qmStatus = QM_STOPPED; - peerLeaveRoom(peer, GroupRoom, ""); - done = true; - } - } - } - break; - case QM_WORKING: - { - } - break; - case QM_MATCHED: - { - // leave QM channel, and clean up. Our work here is done. - peerLeaveRoom( peer, GroupRoom, NULL ); - peerLeaveRoom( peer, StagingRoom, NULL ); m_isHosting = false; - - m_qmStatus = QM_STOPPED; - peerLeaveRoom(peer, GroupRoom, ""); - done = true; - } - break; - case QM_INCHANNEL: - { - } - break; - case QM_NEGOTIATINGFIREWALLS: - { - } - break; - case QM_STARTINGGAME: - { - } - break; - case QM_COULDNOTFINDCHANNEL: - { - } - break; - case QM_COULDNOTNEGOTIATEFIREWALLS: - { - } - break; - } - } - } - } - updateBuddyStatus( BUDDY_ONLINE ); -} - -static void getPlayerProfileIDCallback(PEER peer, PEERBool success, const char * nick, int profileID, void * param) -{ - if (success && param != NULL) - { - *((Int *)param) = profileID; - } -} - -static void stagingRoomPlayerEnum( PEER peer, PEERBool success, RoomType roomType, int index, const char * nick, int flags, void * param ) -{ - DEBUG_LOG(("Enum: success=%d, index=%d, nick=%s, flags=%d\n", success, index, nick, flags)); - if (!nick || !success) - return; - - Int id = 0; - peerGetPlayerProfileID(peer, nick, getPlayerProfileIDCallback, &id, PEERTrue); - DEBUG_ASSERTCRASH(id != 0, ("Failed to fetch player ID!")); - - PeerResponse *resp = (PeerResponse *)param; - if (flags & PEER_FLAG_OP) - { - resp->joinStagingRoom.isHostPresent = TRUE; - } - if (index < MAX_SLOTS) - { - resp->stagingRoomPlayerNames[index] = nick; - } - - if (id) - { - PSRequest req; - req.requestType = PSRequest::PSREQUEST_READPLAYERSTATS; - req.player.id = id; - TheGameSpyPSMessageQueue->addRequest(req); - } -} - -static void joinRoomCallback(PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, void *param) -{ - DEBUG_LOG(("JoinRoomCallback: success==%d, result==%d\n", success, result)); - PeerThreadClass *t = (PeerThreadClass *)param; - if (!t) - return; - DEBUG_LOG(("Room id was %d from thread %X\n", t->getLocalRoomID(), t)); - DEBUG_LOG(("Current staging server name is [%ls]\n", t->getLocalStagingServerName().c_str())); - DEBUG_LOG(("Room type is %d (GroupRoom=%d, StagingRoom=%d, TitleRoom=%d)\n", roomType, GroupRoom, StagingRoom, TitleRoom)); - -#ifdef USE_BROADCAST_KEYS - if (success) - { - t->pushStatsToRoom(peer); - t->getStatsFromRoom(peer, roomType); - } -#endif // USE_BROADCAST_KEYS - - switch (roomType) - { - case GroupRoom: - { -#ifdef USE_BROADCAST_KEYS - t->clearPlayerStats(GroupRoom); -#endif // USE_BROADCAST_KEYS - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_JOINGROUPROOM; - resp.joinGroupRoom.id = t->getLocalRoomID(); - resp.joinGroupRoom.ok = success; - TheGameSpyPeerMessageQueue->addResponse(resp); - t->roomJoined(success == PEERTrue); - DEBUG_LOG(("Entered group room %d, qm is %d\n", t->getLocalRoomID(), t->getQMGroupRoom())); - if ((!t->getQMGroupRoom()) || (t->getQMGroupRoom() != t->getLocalRoomID())) - { - DEBUG_LOG(("Updating buddy status\n")); - updateBuddyStatus( BUDDY_LOBBY, t->getLocalRoomID() ); - } - } - break; - case StagingRoom: - { -#ifdef USE_BROADCAST_KEYS - t->clearPlayerStats(StagingRoom); -#endif // USE_BROADCAST_KEYS - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_JOINSTAGINGROOM; - resp.joinStagingRoom.id = t->getLocalRoomID(); - resp.joinStagingRoom.ok = success; - resp.joinStagingRoom.result = result; - if (success) - { - DEBUG_LOG(("joinRoomCallback() - game name is now '%ls'\n", t->getLocalStagingServerName().c_str())); - updateBuddyStatus( BUDDY_STAGING, 0, WideCharStringToMultiByte(t->getLocalStagingServerName().c_str()) ); - } - - resp.joinStagingRoom.isHostPresent = FALSE; - DEBUG_LOG(("Enum of staging room players\n")); - peerEnumPlayers(peer, StagingRoom, stagingRoomPlayerEnum, &resp); - DEBUG_LOG(("Host %s present\n", (resp.joinStagingRoom.isHostPresent)?"is":"is not")); - - TheGameSpyPeerMessageQueue->addResponse(resp); - } - break; - } -} - -// Gets called once for each group room when listing group rooms. -// After this has been called for each group room, it will be -// called one more time with groupID==0 and name==NULL. -///////////////////////////////////////////////////////////////// -static void listGroupRoomsCallback(PEER peer, PEERBool success, - int groupID, SBServer server, - const char * name, int numWaiting, - int maxWaiting, int numGames, - int numPlaying, void * param) -{ - DEBUG_LOG(("listGroupRoomsCallback, success=%d, server=%X, groupID=%d\n", success, server, groupID)); -#ifdef SERVER_DEBUGGING - CheckServers(peer); -#endif // SERVER_DEBUGGING - PeerThreadClass *t = (PeerThreadClass *)param; - if (!t) - { - DEBUG_LOG(("No thread! Bailing!\n")); - return; - } - - if (success) - { - DEBUG_LOG(("Saw group room of %d (%s) at address %X %X\n", groupID, name, server, (server)?server->keyvals:0)); - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_GROUPROOM; - resp.groupRoom.id = groupID; - resp.groupRoom.numWaiting = numWaiting; - resp.groupRoom.maxWaiting = maxWaiting; - resp.groupRoom.numGames = numGames; - resp.groupRoom.numPlaying = numPlaying; - if (name) - { - resp.groupRoomName = name; - //t->setQMGroupRoom(groupID); - } - else - { - resp.groupRoomName.empty(); - } - TheGameSpyPeerMessageQueue->addResponse(resp); -#ifdef SERVER_DEBUGGING - CheckServers(peer); - DEBUG_LOG(("\n")); -#endif // SERVER_DEBUGGING - } - else - { - DEBUG_LOG(("Failure!\n")); - } -} - -void PeerThreadClass::connectCallback( PEER peer, PEERBool success ) -{ - PeerResponse resp; - if(!success) - { - //updateBuddyStatus( BUDDY_OFFLINE ); - resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT; - resp.discon.reason = DISCONNECT_COULDNOTCONNECT; - TheGameSpyPeerMessageQueue->addResponse(resp); - return; - } - - updateBuddyStatus( BUDDY_ONLINE ); - - m_isConnected = true; - DEBUG_LOG(("Connected as profile %d (%s)\n", m_profileID, m_loginName.c_str())); - resp.peerResponseType = PeerResponse::PEERRESPONSE_LOGIN; - resp.player.profileID = m_profileID; - resp.nick = m_loginName; - GetLocalChatConnectionAddress("peerchat.gamespy.com", 6667, localIP); - //chatSetLocalIP(preferredIP); //Aliendroid1: Disabled because it is not supported by the GameSpy implementation we are using - resp.player.internalIP = ntohl(localIP); - resp.player.externalIP = ntohl(peerGetLocalIP(peer)); - TheGameSpyPeerMessageQueue->addResponse(resp); - - PSRequest psReq; - psReq.requestType = PSRequest::PSREQUEST_READPLAYERSTATS; - psReq.player.id = m_profileID; - psReq.nick = m_originalName; - psReq.email = m_email; - psReq.password = m_password; - TheGameSpyPSMessageQueue->addRequest(psReq); - -#ifdef SERVER_DEBUGGING - DEBUG_LOG(("Before peerListGroupRooms()\n")); - CheckServers(peer); -#endif // SERVER_DEBUGGING - peerListGroupRooms( peer, NULL, listGroupRoomsCallback, this, PEERTrue ); -#ifdef SERVER_DEBUGGING - DEBUG_LOG(("After peerListGroupRooms()\n")); - CheckServers(peer); -#endif // SERVER_DEBUGGING -} - -void PeerThreadClass::nickErrorCallback( PEER peer, Int type, const char *nick ) -{ - if(type == PEER_IN_USE) - { - Int len = strlen(nick); - std::string nickStr = nick; - Int newVal = 0; - if (nick[len-1] == '}' && nick[len-3] == '{' && isdigit(nick[len-2])) - { - newVal = nick[len-2] - '0' + 1; - nickStr.erase(len-3, 3); - } - - DEBUG_LOG(("Nickname taken: was %s, new val = %d, new nick = %s\n", nick, newVal, nickStr.c_str())); - - if (newVal < 10) - { - nickStr.append("{"); - char tmp[2]; - tmp[0] = '0'+newVal; - tmp[1] = '\0'; - nickStr.append(tmp); - nickStr.append("}"); - // Retry the connect with a similar nick. - m_loginName = nickStr; - peerRetryWithNick(peer, nickStr.c_str()); - } - else - { - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT; - resp.discon.reason = DISCONNECT_NICKTAKEN; - TheGameSpyPeerMessageQueue->addResponse(resp); - - // Cancel the connect. - peerRetryWithNick(peer, NULL); - } - } - else - { - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT; - resp.discon.reason = DISCONNECT_BADNICK; - TheGameSpyPeerMessageQueue->addResponse(resp); - - // Cancel the connect. - peerRetryWithNick(peer, NULL); - } -} - -void disconnectedCallback(PEER peer, const char * reason, void * param) -{ - DEBUG_LOG(("disconnectedCallback(): reason was '%s'\n", reason)); - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (t) - t->markAsDisconnected(); - //updateBuddyStatus( BUDDY_OFFLINE ); - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT; - resp.discon.reason = DISCONNECT_LOSTCON; - SerialAuthResult res = TheGameSpyPeerMessageQueue->getSerialAuthResult(); - switch (res) - { - case SERIAL_NONEXISTENT: - resp.discon.reason = DISCONNECT_SERIAL_NOT_PRESENT; - break; - case SERIAL_AUTHFAILED: - resp.discon.reason = DISCONNECT_SERIAL_INVALID; - break; - case SERIAL_BANNED: - resp.discon.reason = DISCONNECT_SERIAL_BANNED; - break; - } - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -void roomMessageCallback(PEER peer, RoomType roomType, const char * nick, const char * message, MessageType messageType, void * param) -{ - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_MESSAGE; - resp.nick = nick; - resp.text = MultiByteToWideCharSingleLine(message); - resp.message.isPrivate = FALSE; - resp.message.isAction = (messageType == ActionMessage); - TheGameSpyPeerMessageQueue->addResponse(resp); - DEBUG_LOG(("Saw text [%hs] (%ls) %d chars Orig was %s (%d chars)\n", nick, resp.text.c_str(), resp.text.length(), message, strlen(message))); - - UnsignedInt IP; - peerGetPlayerInfoNoWait(peer, nick, &IP, &resp.message.profileID); - - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (t && (t->getQMStatus() != QM_IDLE && t->getQMStatus() != QM_STOPPED)) - { - if (resp.message.profileID == matchbotProfileID) - { - char *lastStr = NULL; - char *cmd = strtok_r((char *)message, " ", &lastStr); - if ( cmd && strcmp(cmd, "MBOT:POOLSIZE") == 0 ) - { - Int poolSize = 0; - - while (1) - { - char *poolStr = strtok_r(NULL, " ", &lastStr); - char *sizeStr = strtok_r(NULL, " ", &lastStr); - if (poolStr && sizeStr) - { - Int pool = atoi(poolStr); - Int size = atoi(sizeStr); - if (pool == t->getQMLadder()) - { - poolSize = size; - break; - } - } - else - break; - } - - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS; - resp.qmStatus.status = QM_POOLSIZE; - resp.qmStatus.poolSize = poolSize; - TheGameSpyPeerMessageQueue->addResponse(resp); - } - } - } -} - -void gameStartedCallback( PEER peer, SBServer server, const char *message, void *param ) -{ - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_GAMESTART; - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -void playerMessageCallback(PEER peer, const char * nick, const char * message, MessageType messageType, void * param) -{ - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_MESSAGE; - resp.nick = nick; - resp.text = MultiByteToWideCharSingleLine(message); - resp.message.isPrivate = TRUE; - resp.message.isAction = (messageType == ActionMessage); - UnsignedInt IP; - peerGetPlayerInfoNoWait(peer, nick, &IP, &resp.message.profileID); - TheGameSpyPeerMessageQueue->addResponse(resp); - - - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (t && (t->getQMStatus() != QM_IDLE && t->getQMStatus() != QM_STOPPED)) - { - if (resp.message.isPrivate && resp.message.profileID == matchbotProfileID) - { - char *lastStr = NULL; - char *cmd = strtok_r((char *)message, " ", &lastStr); - if ( cmd && strcmp(cmd, "MBOT:MATCHED") == 0 ) - { - char *mapNumStr = strtok_r(NULL, " ", &lastStr); - char *seedStr = strtok_r(NULL, " ", &lastStr); - char *playerStr[MAX_SLOTS]; - char *playerIPStr[MAX_SLOTS]; - char *playerSideStr[MAX_SLOTS]; - char *playerColorStr[MAX_SLOTS]; - char *playerNATStr[MAX_SLOTS]; - Int numPlayers = 0; - for (Int i=0; i 1) - { - // woohoo! got everything needed for a match! - DEBUG_LOG(("Saw %d-player QM match: map index = %s, seed = %s\n", numPlayers, mapNumStr, seedStr)); - t->handleQMMatch(peer, atoi(mapNumStr), atoi(seedStr), playerStr, playerIPStr, playerSideStr, playerColorStr, playerNATStr); - } - } - else if ( cmd && strcmp(cmd, "MBOT:WORKING") == 0 ) - { - Int poolSize = 0; - char *poolStr = strtok_r(NULL, " ", &lastStr); - if (poolStr) - poolSize = atoi(poolStr); - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS; - resp.qmStatus.status = QM_WORKING; - resp.qmStatus.poolSize = poolSize; - TheGameSpyPeerMessageQueue->addResponse(resp); - } - else if ( cmd && strcmp(cmd, "MBOT:WIDENINGSEARCH") == 0 ) - { - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS; - resp.qmStatus.status = QM_WIDENINGSEARCH; - TheGameSpyPeerMessageQueue->addResponse(resp); - } - } - } -} - -void roomUTMCallback(PEER peer, RoomType roomType, const char * nick, const char * command, const char * parameters, PEERBool authenticated, void * param) -{ - DEBUG_LOG(("roomUTMCallback: %s says %s = [%s]\n", nick, command, parameters)); - if (roomType != StagingRoom) - return; - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_ROOMUTM; - resp.nick = nick; - resp.command = command; - resp.commandOptions = parameters; - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -void playerUTMCallback(PEER peer, const char * nick, const char * command, const char * parameters, PEERBool authenticated, void * param) -{ - DEBUG_LOG(("playerUTMCallback: %s says %s = [%s]\n", nick, command, parameters)); - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERUTM; - resp.nick = nick; - resp.command = command; - resp.commandOptions = parameters; - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -static void getPlayerInfo(PeerThreadClass *t, PEER peer, const char *nick, Int& id, UnsignedInt& IP, - std::string& locale, Int& wins, Int& losses, Int& rankPoints, Int& side, Int& preorder, - RoomType roomType, Int& flags) -{ - if (!t || !nick) - return; - peerGetPlayerInfoNoWait(peer, nick, &IP, &id); -#ifdef USE_BROADCAST_KEYS - //locale.printf - Int localeIndex = t->lookupStatForPlayer(roomType, nick, "b_locale"); - AsciiString tmp; - tmp.format("%d", localeIndex); - locale = tmp.str(); - - wins = t->lookupStatForPlayer(roomType, nick, "b_wins"); - losses = t->lookupStatForPlayer(roomType, nick, "b_losses"); - rankPoints = t->lookupStatForPlayer(roomType, nick, "b_points"); - side = t->lookupStatForPlayer(roomType, nick, "b_side"); - preorder = t->lookupStatForPlayer(roomType, nick, "b_pre"); -#else // USE_BROADCAST_KEYS - const char *s; - s = peerGetGlobalWatchKey(peer, nick, "locale"); - locale = (s)?s:""; - s = peerGetGlobalWatchKey(peer, nick, "wins"); - wins = atoi((s)?s:""); - s = peerGetGlobalWatchKey(peer, nick, "losses"); - losses = atoi((s)?s:""); - s = peerGetGlobalWatchKey(peer, nick, "points"); - rankPoints = atoi((s)?s:""); - s = peerGetGlobalWatchKey(peer, nick, "side"); - side = atoi((s)?s:""); - s = peerGetGlobalWatchKey(peer, nick, "pre"); - preorder = atoi((s)?s:""); -#endif // USE_BROADCAST_KEYS - flags = 0; - peerGetPlayerFlags(peer, nick, roomType, &flags); - DEBUG_LOG(("getPlayerInfo(%d) - %s has locale %s, wins:%d, losses:%d, rankPoints:%d, side:%d, preorder:%d\n", - id, nick, locale.c_str(), wins, losses, rankPoints, side, preorder)); -} - -static void roomKeyChangedCallback(PEER peer, RoomType roomType, const char *nick, const char *key, const char *val, void *param) -{ -#ifdef USE_BROADCAST_KEYS - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (!t || !nick || !key || !val) - { - DEBUG_ASSERTCRASH(nick && strcmp(nick,"(END)")==0, ("roomKeyChangedCallback bad values = nick:%X:%s, key:%X:%s, val:%X:%s\n", nick, nick, key, key, val, val)); - return; - } - -#ifdef DEBUG_LOGGING - if (strcmp(key, "username") && strcmp(key, "b_flags")) - { - DEBUG_LOG(("roomKeyChangedCallback() - %s set %s=%s\n", nick, key, val)); - } -#endif - - t->trackStatsForPlayer(roomType, nick, key, val); - - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERINFO; - resp.nick = nick; - resp.player.roomType = roomType; - - getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP, - resp.locale, resp.player.wins, resp.player.losses, - resp.player.rankPoints, resp.player.side, resp.player.preorder, - resp.player.roomType, resp.player.flags); - TheGameSpyPeerMessageQueue->addResponse(resp); -#endif // USE_BROADCAST_KEYS -} - -#ifdef USE_BROADCAST_KEYS -void getRoomKeysCallback(PEER peer, PEERBool success, RoomType roomType, const char *nick, int num, char **keys, char **values, void *param) -{ - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (!t || !nick || !num || !success || !keys || !values) - { - DEBUG_ASSERTCRASH(!nick || strcmp(nick,"(END)")==0, ("getRoomKeysCallback bad key/value %X/%X, nick=%s", keys, values, nick)); - return; - } - - for (Int i=0; itrackStatsForPlayer(roomType, nick, keys[i], values[i]); - } - - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERINFO; - resp.nick = nick; - resp.player.roomType = roomType; - - getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP, - resp.locale, resp.player.wins, resp.player.losses, - resp.player.rankPoints, resp.player.side, resp.player.preorder, - resp.player.roomType, resp.player.flags); - TheGameSpyPeerMessageQueue->addResponse(resp); -} -#endif // USE_BROADCAST_KEYS - -static void globalKeyChangedCallback(PEER peer, const char *nick, const char *key, const char *val, void *param) -{ - if (!nick) - return; - - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (!t) - return; - - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERINFO; - resp.nick = nick; - resp.player.roomType = t->getCurrentGroupRoom()?GroupRoom:StagingRoom; - - getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP, - resp.locale, resp.player.wins, resp.player.losses, - resp.player.rankPoints, resp.player.side, resp.player.preorder, - resp.player.roomType, resp.player.flags); - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -void playerJoinedCallback(PEER peer, RoomType roomType, const char * nick, void * param) -{ - if (!nick) - return; - - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (!t) - return; - - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERJOIN; - resp.nick = nick; - resp.player.roomType = roomType; - - getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP, - resp.locale, resp.player.wins, resp.player.losses, - resp.player.rankPoints, resp.player.side, resp.player.preorder, - roomType, resp.player.flags); - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -void playerLeftCallback(PEER peer, RoomType roomType, const char * nick, const char * reason, void * param) -{ - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERLEFT; - resp.nick = nick; - resp.player.roomType = roomType; - resp.player.profileID = 0; - - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (!t) - return; - - getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP, - resp.locale, resp.player.wins, resp.player.losses, - resp.player.rankPoints, resp.player.side, resp.player.preorder, - roomType, resp.player.flags); - TheGameSpyPeerMessageQueue->addResponse(resp); - -// PeerThreadClass *t = (PeerThreadClass *)param; -// DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (t->getQMStatus() != QM_IDLE && t->getQMStatus() != QM_STOPPED) - { - if (!stricmp(t->getQMBotName().c_str(), nick)) - { - // matchbot left - bail - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS; - resp.qmStatus.status = QM_COULDNOTFINDBOT; - TheGameSpyPeerMessageQueue->addResponse(resp); - - PeerRequest req; - req.peerRequestType = PeerRequest::PEERREQUEST_STOPQUICKMATCH; - TheGameSpyPeerMessageQueue->addRequest(req); - } - } -} - -void playerChangedNickCallback(PEER peer, RoomType roomType, const char * oldNick, const char * newNick, void * param) -{ - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERCHANGEDNICK; - resp.nick = newNick; - resp.oldNick = oldNick; - resp.player.roomType = roomType; - - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (!t) - return; - - getPlayerInfo(t, peer, newNick, resp.player.profileID, resp.player.IP, - resp.locale, resp.player.wins, resp.player.losses, - resp.player.rankPoints, resp.player.side, resp.player.preorder, - roomType, resp.player.flags); - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -static void playerInfoCallback(PEER peer, RoomType roomType, const char * nick, unsigned int IP, int profileID, void * param) -{ - if (!nick) - return; - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERINFO; - resp.nick = nick; - resp.player.roomType = roomType; - - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (!t) - return; - - getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP, - resp.locale, resp.player.wins, resp.player.losses, - resp.player.rankPoints, resp.player.side, resp.player.preorder, - roomType, resp.player.flags); -DEBUG_LOG(("**GS playerInfoCallback name=%s, local=%s\n", nick, resp.locale.c_str() )); - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -static void playerFlagsChangedCallback(PEER peer, RoomType roomType, const char * nick, int oldFlags, int newFlags, void * param) -{ - if (!nick) - return; - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERCHANGEDFLAGS; - resp.nick = nick; - resp.player.roomType = roomType; - - PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(t, ("No Peer thread!")); - if (!t) - return; - - getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP, - resp.locale, resp.player.wins, resp.player.losses, - resp.player.rankPoints, resp.player.side, resp.player.preorder, - roomType, resp.player.flags); - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -#ifdef DEBUG_LOGGING -/* -static void enumFunc(char *key, char *val, void *param) -{ - DEBUG_LOG((" [%s] = [%s]\n", key, val)); -} -*/ -#endif - -static void listingGamesCallback(PEER peer, PEERBool success, const char * name, SBServer server, PEERBool staging, int msg, Int percentListed, void * param) -{ - PeerThreadClass *t = (PeerThreadClass *)param; - if (!t || !success) - return; - -#ifdef DEBUG_LOGGING - AsciiString cmdStr = ""; - switch(msg) - { - case PEER_ADD: - cmdStr = "PEER_ADD"; - break; - case PEER_UPDATE: - cmdStr = "PEER_UPDATE"; - break; - case PEER_REMOVE: - cmdStr = "PEER_REMOVE"; - break; - case PEER_CLEAR: - cmdStr = "PEER_CLEAR"; - break; - case PEER_COMPLETE: - cmdStr = "PEER_COMPLETE"; - break; - } - DEBUG_LOG(("listingGamesCallback() - doing command %s on server %X\n", cmdStr.str(), server)); -#endif // DEBUG_LOGGING - -// PeerThreadClass *t = (PeerThreadClass *)param; - DEBUG_ASSERTCRASH(name || msg==PEER_CLEAR || msg==PEER_COMPLETE, ("Game has no name!\n")); - if (!t || !success || (!name && (msg == PEER_ADD || msg == PEER_UPDATE))) - { - DEBUG_LOG(("Bailing from listingGamesCallback() - success=%d, name=%X, server=%X, msg=%X\n", success, name, server, msg)); - return; - } - if (!name) - name = "bogus"; - - if (server && (msg == PEER_ADD || msg == PEER_UPDATE)) - { - DEBUG_ASSERTCRASH(server->keyvals, ("Looking at an already-freed server for msg type %d!", msg)); - if (!server->keyvals) - { - msg = PEER_REMOVE; - } - } - - if (server && success && (msg == PEER_ADD || msg == PEER_UPDATE)) - { - DEBUG_LOG(("Game name is '%s'\n", name)); - const char *newname = SBServerGetStringValue(server, "gamename", (char *)name); - if (strcmp(newname, "ccgenzh")) - name = newname; - DEBUG_LOG(("Game name is now '%s'\n", name)); - } - - DEBUG_LOG(("listingGamesCallback - got percent complete %d\n", percentListed)); - if (percentListed == 100) - { - if (!t->getSawCompleteGameList()) - { - t->setSawCompleteGameList(TRUE); - PeerResponse completeResp; - completeResp.peerResponseType = PeerResponse::PEERRESPONSE_STAGINGROOMLISTCOMPLETE; - TheGameSpyPeerMessageQueue->addResponse(completeResp); - } - } - - AsciiString gameName = name; - AsciiString tmp = gameName; - AsciiString hostName; - tmp.nextToken(&hostName, " "); - const char *firstSpace = gameName.find(' '); - if(firstSpace) - { - gameName.set(firstSpace + 1); - //gameName.trim(); - DEBUG_LOG(("Hostname/Gamename split leaves '%s' hosting '%s'\n", hostName.str(), gameName.str())); - } - PeerResponse resp; - resp.peerResponseType = PeerResponse::PEERRESPONSE_STAGINGROOM; - resp.stagingRoom.action = msg; - resp.stagingRoom.isStaging = staging; - resp.stagingRoom.percentComplete = percentListed; - - if (server && (msg == PEER_ADD || msg == PEER_UPDATE)) - { - Bool hasPassword = (Bool)SBServerGetIntValue(server, PW_STR, FALSE); - Bool allowObservers = (Bool)SBServerGetIntValue(server, OBS_STR, FALSE); - Bool usesStats = (Bool)SBServerGetIntValue(server, USE_STATS_STR, TRUE); - const char *verStr = SBServerGetStringValue(server, "gamever", "000000"); - const char *exeStr = SBServerGetStringValue(server, EXECRC_STR, "000000"); - const char *iniStr = SBServerGetStringValue(server, INICRC_STR, "000000"); - const char *ladIPStr = SBServerGetStringValue(server, LADIP_STR, "000000"); - const char *pingStr = SBServerGetStringValue(server, PINGSTR_STR, "FFFFFFFFFFFFFFFF"); - UnsignedShort ladPort = (UnsignedShort)SBServerGetIntValue(server, LADPORT_STR, 0); - UnsignedInt verVal = strtoul(verStr, NULL, 10); - UnsignedInt exeVal = strtoul(exeStr, NULL, 10); - UnsignedInt iniVal = strtoul(iniStr, NULL, 10); - resp.stagingRoom.requiresPassword = hasPassword; - resp.stagingRoom.allowObservers = allowObservers; - resp.stagingRoom.useStats = usesStats; - resp.stagingRoom.version = verVal; - resp.stagingRoom.exeCRC = exeVal; - resp.stagingRoom.iniCRC = iniVal; - resp.stagingServerLadderIP = ladIPStr; - resp.stagingServerPingString = pingStr; - resp.stagingRoom.ladderPort = ladPort; - resp.stagingRoom.numPlayers = SBServerGetIntValue(server, NUMPLAYER_STR, 0); - resp.stagingRoom.numObservers = SBServerGetIntValue(server, NUMOBS_STR, 0); - resp.stagingRoom.maxPlayers = SBServerGetIntValue(server, MAXPLAYER_STR, 8); - resp.stagingRoomMapName = SBServerGetStringValue(server, "mapname", ""); - for (Int i=0; ifindServer( server ); - DEBUG_LOG(("Add/update a 0/0 server %X (%d, %s) - requesting full update to see if that helps.\n", - server, resp.stagingRoom.id, gameName.str())); - TheGameSpyPeerMessageQueue->addRequest(req); - } - return; // don't actually try to list it. - } - } - - switch (msg) - { - case PEER_CLEAR: - t->clearServers(); - break; - case PEER_ADD: - case PEER_UPDATE: - resp.stagingRoom.id = t->findServer( server ); - DEBUG_LOG(("Add/update on server %X (%d, %s)\n", server, resp.stagingRoom.id, gameName.str())); - resp.stagingServerName = MultiByteToWideCharSingleLine( gameName.str() ); - DEBUG_LOG(("Server had basic=%d, full=%d\n", SBServerHasBasicKeys(server), SBServerHasFullKeys(server))); -#ifdef DEBUG_LOGGING - //SBServerEnumKeys(server, enumFunc, NULL); -#endif - break; - case PEER_REMOVE: - DEBUG_LOG(("Removing server %X (%d)\n", server, resp.stagingRoom.id)); - resp.stagingRoom.id = t->removeServerFromMap( server ); - break; - } - - TheGameSpyPeerMessageQueue->addResponse(resp); -} - -//------------------------------------------------------------------------- - diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PersistentStorageThread.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PersistentStorageThread.cpp deleted file mode 100644 index f0f518570a3..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PersistentStorageThread.cpp +++ /dev/null @@ -1,1479 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PersistentStorageThread.cpp ////////////////////////////////////////////////////// -// GameSpy Persistent Storage thread -// This thread communicates with GameSpy's persistent storage server -// and talks through a message queue with the rest of -// the game. -// Author: Matthew D. Campbell, July 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/UserPreferences.h" -#include "Common/PlayerTemplate.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpy/PeerDefs.h" - -#include "mutex.h" -#include "thread.h" - -#include "Common/StackDump.h" -#include "Common/SubsystemInterface.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -//------------------------------------------------------------------------- - -PSRequest::PSRequest() -{ - player.reset(); - requestType = PSREQUEST_READPLAYERSTATS; - addDiscon = addDesync = FALSE; - lastHouse = -1; -} - -//------------------------------------------------------------------------- - -#define DEBUG_MAP(x) for (it = stats.x.begin(); it != stats.x.end(); ++it) \ -{ \ - if (it->second > 0) \ - { \ - DEBUG_LOG(("%s(%d): %d\n", #x, it->first, it->second)); \ - } \ -} - -static void debugDumpPlayerStats( const PSPlayerStats& stats ) -{ - DEBUG_LOG(("-----------------------------------------\n")); - DEBUG_LOG(("Tracking player stats for player %d:\n", stats.id)); - PerGeneralMap::const_iterator it; - DEBUG_MAP(wins); - DEBUG_MAP(losses); - DEBUG_MAP(games); - DEBUG_MAP(duration); - DEBUG_MAP(unitsKilled); - DEBUG_MAP(unitsLost); - DEBUG_MAP(unitsBuilt); - DEBUG_MAP(buildingsKilled); - DEBUG_MAP(buildingsLost); - DEBUG_MAP(buildingsBuilt); - DEBUG_MAP(earnings); - DEBUG_MAP(techCaptured); - DEBUG_MAP(discons); - DEBUG_MAP(desyncs); - DEBUG_MAP(surrenders); - DEBUG_MAP(gamesOf2p); - DEBUG_MAP(gamesOf3p); - DEBUG_MAP(gamesOf4p); - DEBUG_MAP(gamesOf5p); - DEBUG_MAP(gamesOf6p); - DEBUG_MAP(gamesOf7p); - DEBUG_MAP(gamesOf8p); - DEBUG_MAP(customGames); - DEBUG_MAP(QMGames); - - if (stats.locale > 0) - { - DEBUG_LOG(("Locale: %d\n", stats.locale)); - } - - if (stats.gamesAsRandom > 0) - { - DEBUG_LOG(("gamesAsRandom: %d\n", stats.gamesAsRandom)); - } - - if (stats.options.length()) - { - DEBUG_LOG(("Options: %s\n", stats.options.c_str())); - } - - if (stats.systemSpec.length()) - { - DEBUG_LOG(("systemSpec: %s\n", stats.systemSpec.c_str())); - } - - if (stats.lastFPS > 0.0f) - { - DEBUG_LOG(("lastFPS: %g\n", stats.lastFPS)); - } - - if (stats.battleHonors > 0) - { - DEBUG_LOG(("battleHonors: %x\n", stats.battleHonors)); - } - if (stats.challengeMedals > 0) - { - DEBUG_LOG(("challengeMedals: %x\n", stats.challengeMedals)); - } - if (stats.lastGeneral >= 0) - { - DEBUG_LOG(("lastGeneral: %d\n", stats.lastGeneral)); - } - if (stats.gamesInRowWithLastGeneral >= 0) - { - DEBUG_LOG(("gamesInRowWithLastGeneral: %d\n", stats.gamesInRowWithLastGeneral)); - } - if (stats.builtSCUD >= 0) - { - DEBUG_LOG(("builtSCUD: %d\n", stats.builtSCUD)); - } - if (stats.builtNuke >= 0) - { - DEBUG_LOG(("builtNuke: %d\n", stats.builtNuke)); - } - if (stats.builtParticleCannon >= 0) - { - DEBUG_LOG(("builtParticleCannon: %d\n", stats.builtParticleCannon)); - } - - if (stats.winsInARow >= 0) - { - DEBUG_LOG(("winsInARow: %d\n", stats.winsInARow)); - } - if (stats.maxWinsInARow >= 0) - { - DEBUG_LOG(("maxWinsInARow: %d\n", stats.maxWinsInARow)); - } - if (stats.disconsInARow >= 0) - { - DEBUG_LOG(("disconsInARow: %d\n", stats.disconsInARow)); - } - if (stats.maxDisconsInARow >= 0) - { - DEBUG_LOG(("maxDisconsInARow: %d\n", stats.maxDisconsInARow)); - } - if (stats.lossesInARow >= 0) - { - DEBUG_LOG(("lossesInARow: %d\n", stats.lossesInARow)); - } - if (stats.maxLossesInARow >= 0) - { - DEBUG_LOG(("maxLossesInARow: %d\n", stats.maxLossesInARow)); - } - if (stats.desyncsInARow >= 0) - { - DEBUG_LOG(("desyncsInARow: %d\n", stats.desyncsInARow)); - } - if (stats.maxDesyncsInARow >= 0) - { - DEBUG_LOG(("maxDesyncsInARow: %d\n", stats.maxDesyncsInARow)); - } - - if (stats.lastLadderPort >= 0) - { - DEBUG_LOG(("lastLadderPort: %d\n", stats.lastLadderPort)); - } - - if (stats.lastLadderHost.length()) - { - DEBUG_LOG(("lastLadderHost: %s\n", stats.lastLadderHost.c_str())); - } - - - -} - -//------------------------------------------------------------------------- - -#define INCORPORATE_MAP(x) for (it = other.x.begin(); it != other.x.end(); ++it) \ -{ \ - if (it->second > 0) \ - { \ - x[it->first] = it->second; \ - } \ -} - -void PSPlayerStats::incorporate( const PSPlayerStats& other ) -{ - PerGeneralMap::const_iterator it; - INCORPORATE_MAP(wins); - INCORPORATE_MAP(losses); - INCORPORATE_MAP(games); - INCORPORATE_MAP(duration); - INCORPORATE_MAP(unitsKilled); - INCORPORATE_MAP(unitsLost); - INCORPORATE_MAP(unitsBuilt); - INCORPORATE_MAP(buildingsKilled); - INCORPORATE_MAP(buildingsLost); - INCORPORATE_MAP(buildingsBuilt); - INCORPORATE_MAP(earnings); - INCORPORATE_MAP(techCaptured); - - //GS Clear all disconnects so that we don't retain any that were - //previously reported as 1 by updateAdditionalGameSpyDisconnections - discons.clear(); - INCORPORATE_MAP(discons); - - INCORPORATE_MAP(desyncs); - INCORPORATE_MAP(surrenders); - INCORPORATE_MAP(gamesOf2p); - INCORPORATE_MAP(gamesOf3p); - INCORPORATE_MAP(gamesOf4p); - INCORPORATE_MAP(gamesOf5p); - INCORPORATE_MAP(gamesOf6p); - INCORPORATE_MAP(gamesOf7p); - INCORPORATE_MAP(gamesOf8p); - INCORPORATE_MAP(customGames); - INCORPORATE_MAP(QMGames); - - if (other.locale > 0) - { - locale = other.locale; - } - - if (other.gamesAsRandom > 0) - { - gamesAsRandom = other.gamesAsRandom; - } - - if (other.options.length()) - { - options = other.options; - } - - if (other.systemSpec.length()) - { - systemSpec = other.systemSpec; - } - - if (other.lastFPS > 0.0f) - { - lastFPS = other.lastFPS; - } - - if (other.battleHonors > 0) - { - battleHonors |= other.battleHonors; - } - if (other.challengeMedals > 0) - { - challengeMedals |= other.challengeMedals; - } - if (other.lastGeneral >= 0) - { - lastGeneral = other.lastGeneral; - } - if (other.gamesInRowWithLastGeneral >= 0) - { - gamesInRowWithLastGeneral = other.gamesInRowWithLastGeneral; - } - if (other.builtParticleCannon >= 0) - { - builtParticleCannon = other.builtParticleCannon; - } - if (other.builtNuke >= 0) - { - builtNuke = other.builtNuke; - } - if (other.builtSCUD >= 0) - { - builtSCUD = other.builtSCUD; - } - if (other.winsInARow >= 0) - { - winsInARow = other.winsInARow; - } - if (other.maxWinsInARow >= 0) - { - maxWinsInARow = other.maxWinsInARow; - } - if (other.lossesInARow >= 0) - { - lossesInARow = other.lossesInARow; - } - if (other.maxLossesInARow >= 0) - { - maxLossesInARow = other.maxLossesInARow; - } - if (other.disconsInARow >= 0) - { - disconsInARow = other.disconsInARow; - } - if (other.maxDisconsInARow >= 0) - { - maxDisconsInARow = other.maxDisconsInARow; - } - if (other.desyncsInARow >= 0) - { - desyncsInARow = other.desyncsInARow; - } - if (other.maxDesyncsInARow >= 0) - { - maxDesyncsInARow = other.maxDesyncsInARow; - } - if (other.lastLadderPort >= 0) - { - lastLadderPort = other.lastLadderPort; - } - if (other.lastLadderHost.length()) - { - lastLadderHost = other.lastLadderHost; - } -} - -PSPlayerStats::PSPlayerStats( const PSPlayerStats& other ) -{ - incorporate(other); - id = other.id; - locale = other.locale; - gamesAsRandom = other.gamesAsRandom; - options = other.options; - systemSpec = other.systemSpec; - lastFPS = other.lastFPS; - lastGeneral = other.lastGeneral; - gamesInRowWithLastGeneral = other.gamesInRowWithLastGeneral; - builtParticleCannon = other.builtParticleCannon; - builtNuke = other.builtNuke; - builtSCUD = other.builtSCUD; - challengeMedals = other.challengeMedals; - battleHonors = other.battleHonors; - winsInARow = other.winsInARow; - maxWinsInARow = other.maxWinsInARow; - lossesInARow = other.lossesInARow; - maxLossesInARow = other.maxLossesInARow; - disconsInARow = other.disconsInARow; - maxDisconsInARow = other.maxDisconsInARow; - desyncsInARow = other.desyncsInARow; - maxDesyncsInARow = other.maxDesyncsInARow; - lastLadderHost = other.lastLadderHost; - lastLadderPort = other.lastLadderPort; -} - -//------------------------------------------------------------------------- - -typedef std::queue RequestQueue; -typedef std::queue ResponseQueue; -class PSThreadClass; - -class GameSpyPSMessageQueue : public GameSpyPSMessageQueueInterface -{ -public: - virtual ~GameSpyPSMessageQueue(); - GameSpyPSMessageQueue(); - virtual void startThread( void ); - virtual void endThread( void ); - virtual Bool isThreadRunning( void ); - - virtual void addRequest( const PSRequest& req ); - virtual Bool getRequest( PSRequest& req ); - - virtual void addResponse( const PSResponse& resp ); - virtual Bool getResponse( PSResponse& resp ); - - virtual void trackPlayerStats( PSPlayerStats stats ); - virtual PSPlayerStats findPlayerStatsByID( Int id ); - - PSThreadClass* getThread( void ); - - Int getLocalPlayerID(void) { return m_localPlayerID; } - void setLocalPlayerID(Int localPlayerID) { m_localPlayerID = localPlayerID; } - - std::string getEmail() { return m_email; } - std::string getNick() { return m_nick; } - std::string getPassword() { return m_password; } - - void setEmail(std::string email) { m_email = email; } - void setNick(std::string nick) { m_nick = nick; } - void setPassword(std::string password) { m_password = password; } - -private: - MutexClass m_requestMutex; - MutexClass m_responseMutex; - RequestQueue m_requests; - ResponseQueue m_responses; - PSThreadClass *m_thread; - Int m_localPlayerID; - - std::string m_email; - std::string m_nick; - std::string m_password; - - std::map m_playerStats; -}; - -GameSpyPSMessageQueueInterface* GameSpyPSMessageQueueInterface::createNewMessageQueue( void ) -{ - return NEW GameSpyPSMessageQueue; -} - -GameSpyPSMessageQueueInterface *TheGameSpyPSMessageQueue = NULL; -#define MESSAGE_QUEUE ((GameSpyPSMessageQueue *)TheGameSpyPSMessageQueue) - -//------------------------------------------------------------------------- - -class PSThreadClass : public ThreadClass -{ - -public: - PSThreadClass() : ThreadClass() - { - m_loginOK = m_sawLocalData = m_doneTryingToLogin = false; - m_opCount = 0; - } - - void Thread_Function(); - - void persAuthCallback( Bool val ) { m_loginOK = val; m_doneTryingToLogin = true; } - void decrOpCount( void ) { --m_opCount; } - void incrOpCount( void ) { ++m_opCount; } - Int getOpCount( void ) { return m_opCount; } - Bool sawLocalPlayerData( void ) { return m_sawLocalData; } - void gotLocalPlayerData( void ) { m_sawLocalData = TRUE; } - -private: - Bool tryConnect( void ); - Bool tryLogin( Int id, std::string nick, std::string password, std::string email ); - Bool m_loginOK; - Bool m_doneTryingToLogin; - Int m_opCount; - Bool m_sawLocalData; -}; - - -//------------------------------------------------------------------------- - -GameSpyPSMessageQueue::GameSpyPSMessageQueue() -{ - m_thread = NULL; - m_localPlayerID = 0; -} - -GameSpyPSMessageQueue::~GameSpyPSMessageQueue() -{ - endThread(); -} - -void GameSpyPSMessageQueue::startThread( void ) -{ - if (!m_thread) - { - m_thread = NEW PSThreadClass; - m_thread->Execute(); - } - else - { - if (!m_thread->Is_Running()) - { - m_thread->Execute(); - } - } -} - -void GameSpyPSMessageQueue::endThread( void ) -{ - if (m_thread) - delete m_thread; - m_thread = NULL; -} - -Bool GameSpyPSMessageQueue::isThreadRunning( void ) -{ - return (m_thread) ? m_thread->Is_Running() : false; -} - -void GameSpyPSMessageQueue::addRequest( const PSRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex); - if (m.Failed()) - return; - - m_requests.push(req); -} - -Bool GameSpyPSMessageQueue::getRequest( PSRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex, 0); - if (m.Failed()) - return false; - - if (m_requests.empty()) - return false; - req = m_requests.front(); - m_requests.pop(); - return true; -} - -void GameSpyPSMessageQueue::addResponse( const PSResponse& resp ) -{ - MutexClass::LockClass m(m_responseMutex); - if (m.Failed()) - return; - - m_responses.push(resp); -} - -Bool GameSpyPSMessageQueue::getResponse( PSResponse& resp ) -{ - MutexClass::LockClass m(m_responseMutex, 0); - if (m.Failed()) - return false; - - if (m_responses.empty()) - return false; - resp = m_responses.front(); - m_responses.pop(); - return true; -} - -PSThreadClass* GameSpyPSMessageQueue::getThread( void ) -{ - return m_thread; -} - -void GameSpyPSMessageQueue::trackPlayerStats( PSPlayerStats stats ) -{ -#ifdef DEBUG_LOGGING - debugDumpPlayerStats( stats ); - DEBUG_ASSERTCRASH(stats.id != 0, ("Tracking stats with ID of 0\n")); -#endif - PSPlayerStats newStats; - std::map::iterator it = m_playerStats.find(stats.id); - if (it != m_playerStats.end()) - { - newStats = it->second; - newStats.incorporate(stats); - m_playerStats[stats.id] = newStats; - } - else - { - m_playerStats[stats.id] = stats; - } -} - -PSPlayerStats GameSpyPSMessageQueue::findPlayerStatsByID( Int id ) -{ - std::map::iterator it = m_playerStats.find(id); - if (it != m_playerStats.end()) - { - return it->second; - } - - PSPlayerStats empty; - empty.id = 0; - return empty; -} - -//------------------------------------------------------------------------- - -Bool PSThreadClass::tryConnect( void ) -{ - Int result; - - DEBUG_LOG(("m_opCount = %d - opening connection\n", m_opCount)); - - if (IsStatsConnected()) - { - DEBUG_LOG(("connection already open!\n")); - return true; - } - - // this may block for 1-2 seconds (according to GS) so it's nice we're not in the UI thread :) - result = InitStatsConnection(0); - - if (result != GE_NOERROR) - { - DEBUG_LOG(("InitStatsConnection() returned %d\n", result)); - return false; - } - - return true; -} - -static void persAuthCallback(int localid, int profileid, int authenticated, char *errmsg, void *instance) -{ - PSThreadClass *t = (PSThreadClass *)instance; - DEBUG_LOG(("Auth callback: localid: %d profileid: %d auth: %d err: %s\n",localid, profileid, authenticated, errmsg)); - if (t) - t->persAuthCallback(authenticated != 0); -} - -Bool PSThreadClass::tryLogin( Int id, std::string nick, std::string password, std::string email ) -{ - char validate[33]; - DEBUG_LOG(("PSThreadClass::tryLogin id = %d, nick = %s, password = %s, email = %s\n", id, nick.c_str(), password.c_str(), email.c_str())); - /*********** - We'll go ahead and start the authentication, using a Presence & Messaging SDK - profileid / password. To generate the new validation token, we'll need to pass - in the password for the profile we are authenticating. - Again, if this is done in a client/server setting, with the Persistent Storage - access being done on the server, and the P&M SDK is used on the client, the - server will need to send the challenge (GetChallenge(NULL)) to the client, the - client will create the validation token using GenerateAuth, and send it - back to the server for use in PreAuthenticatePlayerPM - ***********/ - char *munkeeHack = strdup(password.c_str()); // GenerateAuth takes a char*, not a const char* :P - GenerateAuth(GetChallenge(NULL), munkeeHack, validate); - free (munkeeHack); - - /************ - After we get the validation token, we pass it and the profileid of the user - we are authenticating into PreAuthenticatePlayerPM. - We pass the same authentication callback as for the first user, but a different - localid this time. - ************/ - m_loginOK = false; - m_doneTryingToLogin = false; - PreAuthenticatePlayerPM(id, id, validate, ::persAuthCallback, this); - while (!m_doneTryingToLogin && IsStatsConnected()) - PersistThink(); - DEBUG_LOG(("Persistant Storage Login success %d\n", m_loginOK)); - return m_loginOK; -} - -static void getPersistentDataCallback(int localid, int profileid, persisttype_t type, int index, int success, time_t modified, char *data, int len, void *instance) -{ - DEBUG_LOG(("Data get callback: localid: %d profileid: %d success: %d len: %d data: %s\n",localid, profileid, success, len, data)); - PSThreadClass *t = (PSThreadClass *)instance; - if (!t) - return; - - t->decrOpCount(); - - PSResponse resp; - - if (!success) - { - resp.responseType = PSResponse::PSRESPONSE_COULDNOTCONNECT; - resp.player.id = profileid; - TheGameSpyPSMessageQueue->addResponse(resp); - if (!t->getOpCount() && !t->sawLocalPlayerData()) - { - // we haven't gotten stats for ourselves - try again - PSRequest req; - req.requestType = PSRequest::PSREQUEST_READPLAYERSTATS; - req.player.id = MESSAGE_QUEUE->getLocalPlayerID(); - TheGameSpyPSMessageQueue->addRequest(req); - } - return; - } - - if (profileid == MESSAGE_QUEUE->getLocalPlayerID() && TheGameSpyGame && TheGameSpyGame->getUseStats()) - { - t->gotLocalPlayerData(); - DEBUG_LOG(("getPersistentDataCallback() - got local player info\n")); - - // check if we have discons we should update on the server - UserPreferences pref; - AsciiString userPrefFilename; - userPrefFilename.format("GeneralsOnline\\MiscPref%d.ini", MESSAGE_QUEUE->getLocalPlayerID()); - DEBUG_LOG(("using the file %s\n", userPrefFilename.str())); - pref.load(userPrefFilename); - Int addedInDesyncs2 = pref.getInt("0", 0); - DEBUG_LOG(("addedInDesyncs2 = %d\n", addedInDesyncs2)); - if (addedInDesyncs2 < 0) - addedInDesyncs2 = 10; - Int addedInDesyncs3 = pref.getInt("1", 0); - DEBUG_LOG(("addedInDesyncs3 = %d\n", addedInDesyncs3)); - if (addedInDesyncs3 < 0) - addedInDesyncs3 = 10; - Int addedInDesyncs4 = pref.getInt("2", 0); - DEBUG_LOG(("addedInDesyncs4 = %d\n", addedInDesyncs4)); - if (addedInDesyncs4 < 0) - addedInDesyncs4 = 10; - Int addedInDiscons2 = pref.getInt("3", 0); - DEBUG_LOG(("addedInDiscons2 = %d\n", addedInDiscons2)); - if (addedInDiscons2 < 0) - addedInDiscons2 = 10; - Int addedInDiscons3 = pref.getInt("4", 0); - DEBUG_LOG(("addedInDiscons3 = %d\n", addedInDiscons3)); - if (addedInDiscons3 < 0) - addedInDiscons3 = 10; - Int addedInDiscons4 = pref.getInt("5", 0); - DEBUG_LOG(("addedInDiscons4 = %d\n", addedInDiscons4)); - if (addedInDiscons4 < 0) - addedInDiscons4 = 10; - - DEBUG_LOG(("addedInDesync=%d,%d,%d, addedInDiscon=%d,%d,%d\n", - addedInDesyncs2, addedInDesyncs3, addedInDesyncs4, - addedInDiscons2, addedInDiscons3, addedInDiscons4)); - - if (addedInDesyncs2 || addedInDesyncs3 || addedInDesyncs4 || addedInDiscons2 || addedInDiscons3 || addedInDiscons4) - { - DEBUG_LOG(("We have a previous discon we can attempt to update! Bummer...\n")); - - PSRequest req; - req.requestType = PSRequest::PSREQUEST_UPDATEPLAYERSTATS; - req.email = MESSAGE_QUEUE->getEmail(); - req.nick = MESSAGE_QUEUE->getNick(); - req.password = MESSAGE_QUEUE->getPassword(); - req.player = GameSpyPSMessageQueueInterface::parsePlayerKVPairs((len)?data:""); - req.player.id = profileid; - req.addDesync = FALSE; - req.addDiscon = FALSE; - req.lastHouse = 0; - TheGameSpyPSMessageQueue->addRequest(req); - } - } - - resp.responseType = PSResponse::PSRESPONSE_PLAYERSTATS; - resp.player = GameSpyPSMessageQueueInterface::parsePlayerKVPairs((len)?data:""); - resp.player.id = profileid; - - TheGameSpyPSMessageQueue->addResponse(resp); -} - -static void setPersistentDataLocaleCallback(int localid, int profileid, persisttype_t type, int index, int success, time_t modified, void *instance) -{ - DEBUG_LOG(("Data save callback: localid: %d profileid: %d success: %d\n", localid, profileid, success)); - - PSThreadClass *t = (PSThreadClass *)instance; - if (!t) - return; - - t->decrOpCount(); -} - -static void setPersistentDataCallback(int localid, int profileid, persisttype_t type, int index, int success, time_t modified, void *instance) -{ - DEBUG_LOG(("Data save callback: localid: %d profileid: %d success: %d\n", localid, profileid, success)); - - PSThreadClass *t = (PSThreadClass *)instance; - if (!t) - return; - - if (success) - { - UserPreferences pref; - AsciiString userPrefFilename; - userPrefFilename.format("GeneralsOnline\\MiscPref%d.ini", profileid); - DEBUG_LOG(("setPersistentDataCallback - writing stats to file %s\n", userPrefFilename.str())); - pref.load(userPrefFilename); - pref.clear(); - pref.write(); - } - t->decrOpCount(); -} - -struct CDAuthInfo -{ - Bool success; - Bool done; - Int id; -}; - -void preAuthCDCallback(int localid, int profileid, int authenticated, char *errmsg, void *instance) -{ - DEBUG_LOG(("preAuthCDCallback(): profileid: %d auth: %d err: %s\n", profileid, authenticated, errmsg)); - - CDAuthInfo *authInfo = (CDAuthInfo *)instance; - authInfo->success = authenticated; - authInfo->done = TRUE; - authInfo->id = profileid; -} - -static void getPreorderCallback(int localid, int profileid, persisttype_t type, int index, int success, time_t modified, char *data, int len, void *instance) -{ - PSThreadClass *t = (PSThreadClass *)instance; - if (!t) - return; - - t->decrOpCount(); - - PSResponse resp; - - if (!success) - { - DEBUG_LOG(("Failed getPreorderCallback()\n")); - return; - } - - resp.responseType = PSResponse::PSRESPONSE_PREORDER; - resp.preorder = (data && strcmp(data, "\\preorder\\1") == 0); - DEBUG_LOG(("getPreorderCallback() - data was '%s'\n", data)); - - TheGameSpyPSMessageQueue->addResponse(resp); -} - -void PSThreadClass::Thread_Function() -{ - try { - _set_se_translator( DumpExceptionInfo ); // Hook that allows stack trace. - /********* - First step, set our game authentication info - We could do: - strcpy(gcd_gamename,"ccgenzh"); - strcpy(gcd_secret_key,"D6s9k3"); - or - strcpy(gcd_gamename,"ccgeneralsb"); - strcpy(gcd_secret_key,"whatever the key is"); - ...but this is more secure: - **********/ - /** - gcd_gamename[0]='c';gcd_gamename[1]='c';gcd_gamename[2]='g';gcd_gamename[3]='e'; - gcd_gamename[4]='n';gcd_gamename[5]='e';gcd_gamename[6]='r';gcd_gamename[7]='a'; - gcd_gamename[8]='l';gcd_gamename[9]='s';gcd_gamename[10]='b';gcd_gamename[11]='\0'; - gcd_secret_key[0]='g';gcd_secret_key[1]='3';gcd_secret_key[2]='T';gcd_secret_key[3]='9'; - gcd_secret_key[4]='s';gcd_secret_key[5]='2';gcd_secret_key[6]='\0'; - /**/ - gcd_gamename[0]='c';gcd_gamename[1]='c';gcd_gamename[2]='g';gcd_gamename[3]='e'; - gcd_gamename[4]='n';gcd_gamename[5]='z';gcd_gamename[6]='h';gcd_gamename[7]='\0'; - gcd_secret_key[0]='D';gcd_secret_key[1]='6';gcd_secret_key[2]='s';gcd_secret_key[3]='9'; - gcd_secret_key[4]='k';gcd_secret_key[5]='3';gcd_secret_key[6]='\0'; - /**/ - - //strcpy(StatsServerHostname, "sdkdev.gamespy.com"); - - PSRequest req; - while ( running ) - { - // deal with requests - if (TheGameSpyPSMessageQueue->getRequest(req)) - { - switch (req.requestType) - { - case PSRequest::PSREQUEST_SENDGAMERESTOGAMESPY: - { - if (tryConnect()) - { - NewGame(0); -#ifdef DEBUG_LOGGING - Int res = -#endif // DEBUG_LOGGING - SendGameSnapShot(NULL, req.results.c_str(), SNAP_FINAL); - DEBUG_LOG(("Just sent game results - res was %d\n", res)); - FreeGame(NULL); - } - } - break; - case PSRequest::PSREQUEST_READPLAYERSTATS: - { - if (!MESSAGE_QUEUE->getLocalPlayerID()) - { - MESSAGE_QUEUE->setLocalPlayerID(req.player.id); // first request is for ourselves - MESSAGE_QUEUE->setEmail(req.email); - MESSAGE_QUEUE->setNick(req.nick); - MESSAGE_QUEUE->setPassword(req.password); - DEBUG_LOG(("Setting email/nick/password = %s/%s/%s\n", req.email.c_str(), req.nick.c_str(), req.password.c_str())); - } - DEBUG_LOG(("Processing PSRequest::PSREQUEST_READPLAYERSTATS\n")); - if (tryConnect()) - { - incrOpCount(); - GetPersistDataValues(0, req.player.id, pd_public_rw, 0, "", getPersistentDataCallback, this); - } - } - break; - case PSRequest::PSREQUEST_UPDATEPLAYERLOCALE: - { - DEBUG_LOG(("Processing PSRequest::PSREQUEST_UPDATEPLAYERLOCALE\n")); - if (tryConnect() && tryLogin(req.player.id, req.nick, req.password, req.email)) - { - char kvbuf[256]; - sprintf(kvbuf, "\\locale\\%d", req.player.locale); - incrOpCount(); - SetPersistDataValues(0, req.player.id, pd_public_rw, 0, kvbuf, setPersistentDataLocaleCallback, this); - } - } - break; - case PSRequest::PSREQUEST_UPDATEPLAYERSTATS: - { - /* - ** NOTE THAT THIS IS HIGHLY DEPENDENT ON INI ORDERING FOR THE PLAYERTEMPLATES!!! - */ - DEBUG_LOG(("Processing PSRequest::PSREQUEST_UPDATEPLAYERSTATS\n")); - UserPreferences pref; - AsciiString userPrefFilename; - userPrefFilename.format("GeneralsOnline\\MiscPref%d.ini", MESSAGE_QUEUE->getLocalPlayerID()); - DEBUG_LOG(("using the file %s\n", userPrefFilename.str())); - pref.load(userPrefFilename); - Int addedInDesyncs2 = pref.getInt("0", 0); - DEBUG_LOG(("addedInDesyncs2 = %d\n", addedInDesyncs2)); - if (addedInDesyncs2 < 0) - addedInDesyncs2 = 10; - Int addedInDesyncs3 = pref.getInt("1", 0); - DEBUG_LOG(("addedInDesyncs3 = %d\n", addedInDesyncs3)); - if (addedInDesyncs3 < 0) - addedInDesyncs3 = 10; - Int addedInDesyncs4 = pref.getInt("2", 0); - DEBUG_LOG(("addedInDesyncs4 = %d\n", addedInDesyncs4)); - if (addedInDesyncs4 < 0) - addedInDesyncs4 = 10; - Int addedInDiscons2 = pref.getInt("3", 0); - DEBUG_LOG(("addedInDiscons2 = %d\n", addedInDiscons2)); - if (addedInDiscons2 < 0) - addedInDiscons2 = 10; - Int addedInDiscons3 = pref.getInt("4", 0); - DEBUG_LOG(("addedInDiscons3 = %d\n", addedInDiscons3)); - if (addedInDiscons3 < 0) - addedInDiscons3 = 10; - Int addedInDiscons4 = pref.getInt("5", 0); - DEBUG_LOG(("addedInDiscons4 = %d\n", addedInDiscons4)); - if (addedInDiscons4 < 0) - addedInDiscons4 = 10; - - DEBUG_LOG(("req.addDesync=%d, req.addDiscon=%d, addedInDesync=%d,%d,%d, addedInDiscon=%d,%d,%d\n", - req.addDesync, req.addDiscon, addedInDesyncs2, addedInDesyncs3, addedInDesyncs4, - addedInDiscons2, addedInDiscons3, addedInDiscons4)); - - if (req.addDesync || req.addDiscon) - { - AsciiString val; - if (req.lastHouse == 2) - { - val.format("%d", addedInDesyncs2 + req.addDesync); - pref["0"] = val; - val.format("%d", addedInDiscons2 + req.addDiscon); - pref["3"] = val; - DEBUG_LOG(("house 2 req.addDesync || req.addDiscon: %d %d\n", - addedInDesyncs2 + req.addDesync, addedInDiscons2 + req.addDiscon)); - } - else if (req.lastHouse == 3) - { - val.format("%d", addedInDesyncs3 + req.addDesync); - pref["1"] = val; - val.format("%d", addedInDiscons3 + req.addDiscon); - pref["4"] = val; - DEBUG_LOG(("house 3 req.addDesync || req.addDiscon: %d %d\n", - addedInDesyncs3 + req.addDesync, addedInDiscons3 + req.addDiscon)); - } - else - { - val.format("%d", addedInDesyncs4 + req.addDesync); - pref["2"] = val; - val.format("%d", addedInDiscons4 + req.addDiscon); - pref["5"] = val; - DEBUG_LOG(("house 4 req.addDesync || req.addDiscon: %d %d\n", - addedInDesyncs4 + req.addDesync, addedInDiscons4 + req.addDiscon)); - } - pref.write(); - if (req.password.size() == 0) - return; - } - if (!req.player.id) - { - DEBUG_LOG(("Bailing because ID is NULL!\n")); - return; - } - req.player.desyncs[2] += addedInDesyncs2; - req.player.games[2] += addedInDesyncs2; - req.player.discons[2] += addedInDiscons2; - req.player.games[2] += addedInDiscons2; - req.player.desyncs[3] += addedInDesyncs3; - req.player.games[3] += addedInDesyncs3; - req.player.discons[3] += addedInDiscons3; - req.player.games[3] += addedInDiscons3; - req.player.desyncs[4] += addedInDesyncs4; - req.player.games[4] += addedInDesyncs4; - req.player.discons[4] += addedInDiscons4; - req.player.games[4] += addedInDiscons4; - DEBUG_LOG(("House2: %d/%d/%d, House3: %d/%d/%d, House4: %d/%d/%d\n", - req.player.desyncs[2], req.player.discons[2], req.player.games[2], - req.player.desyncs[3], req.player.discons[3], req.player.games[3], - req.player.desyncs[4], req.player.discons[4], req.player.games[4] - )); - if (tryConnect() && tryLogin(req.player.id, req.nick, req.password, req.email)) - { - DEBUG_LOG(("Logged in!\n")); - if (TheGameSpyPSMessageQueue) - TheGameSpyPSMessageQueue->trackPlayerStats(req.player); - - char *munkeeHack = strdup(GameSpyPSMessageQueueInterface::formatPlayerKVPairs(req.player).c_str()); // GS takes a char* for some reason - incrOpCount(); - DEBUG_LOG(("Setting values %s\n", munkeeHack)); - SetPersistDataValues(0, req.player.id, pd_public_rw, 0, munkeeHack, setPersistentDataCallback, this); - free(munkeeHack); - } - else - { - DEBUG_LOG(("Cannot connect!\n")); - //if (IsStatsConnected()) - //CloseStatsConnection(); - } - } - break; - case PSRequest::PSREQUEST_READCDKEYSTATS: - { - DEBUG_LOG(("Processing PSRequest::PSREQUEST_READCDKEYSTATS\n")); - if (tryConnect()) - { - incrOpCount(); - CDAuthInfo cdAuthInfo; - cdAuthInfo.done = FALSE; - cdAuthInfo.success = FALSE; - cdAuthInfo.id = 0; - char cdkeyHash[33] = ""; - char validationToken[33] = ""; - char *munkeeHack = strdup(req.cdkey.c_str()); // GenerateAuth takes a char*, not a const char* :P - - GenerateAuth(GetChallenge(NULL), munkeeHack, validationToken); // validation token - GenerateAuth("", munkeeHack, cdkeyHash); // cdkey hash - - free (munkeeHack); - - PreAuthenticatePlayerCD( 0, "preorder", cdkeyHash, validationToken, preAuthCDCallback , &cdAuthInfo); - - while (running && IsStatsConnected() && !cdAuthInfo.done) - PersistThink(); - - DEBUG_LOG(("Looking for preorder status for %d (success=%d, done=%d) from CDKey %s with hash %s\n", - cdAuthInfo.id, cdAuthInfo.success, cdAuthInfo.done, req.cdkey.c_str(), cdkeyHash)); - if (cdAuthInfo.done && cdAuthInfo.success) - GetPersistDataValues(0, cdAuthInfo.id, pd_public_ro, 0, "\\preorder", getPreorderCallback, this); - else - decrOpCount(); - } - } - break; - } - } - - // update the network - if (IsStatsConnected()) - { - PersistThink(); - if (m_opCount <= 0) - { - DEBUG_ASSERTCRASH(m_opCount == 0, ("Negative operations pending!!!")); - DEBUG_LOG(("m_opCount = %d - closing connection\n", m_opCount)); - CloseStatsConnection(); - m_opCount = 0; - } - } - - // end our timeslice - Switch_Thread(); - } - - if (IsStatsConnected()) - CloseStatsConnection(); - } catch ( ... ) { - DEBUG_CRASH(("Exception in storage thread!")); - } -} - -//------------------------------------------------------------------------- -PSPlayerStats::PSPlayerStats( void ) -{ - reset(); -} - -void PSPlayerStats::reset( void ) -{ - id = 0; - locale = 0; - gamesAsRandom = 0; - lastFPS = 0; - lastGeneral = 0; - gamesInRowWithLastGeneral = 0; - builtNuke = 0; - builtSCUD = 0; - builtParticleCannon = 0; - challengeMedals = 0; - battleHonors = 0; - winsInARow = 0; - maxWinsInARow = 0; - lossesInARow = 0; - maxLossesInARow = 0; - disconsInARow = 0; - maxDisconsInARow = 0; - desyncsInARow = 0; - maxDesyncsInARow = 0; - lastLadderPort = 0; - - //Added By Sadullah Nader - maxQMwinsInARow = 0; - QMwinsInARow = 0; - // -} - -//------------------------------------------------------------------------- -#define CHECK(x) if (k == #x && generalMarker >= 0) { s.x[generalMarker] = atoi(v.c_str()); continue; } - -PSPlayerStats GameSpyPSMessageQueueInterface::parsePlayerKVPairs( std::string kvPairs ) -{ - PSPlayerStats s; - kvPairs.append("\\"); - - Int offset = 0; - while (1) - { - Int firstMarker = kvPairs.find_first_of('\\', offset); - if (firstMarker < 0) - break; - Int secondMarker = kvPairs.find_first_of('\\', firstMarker + 1); - if (secondMarker < 0) - break; - Int thirdMarker = kvPairs.find_first_of('\\', secondMarker + 1); - if (thirdMarker < 0) - break; - Int generalMarker = kvPairs.find_last_not_of("0123456789", secondMarker - 1); - std::string k, v, g; - if (generalMarker == secondMarker - 1) - { - k = kvPairs.substr(firstMarker + 1, secondMarker - firstMarker - 1); - generalMarker = -1; - } - else - { - k = kvPairs.substr(firstMarker + 1, generalMarker - firstMarker); - g = kvPairs.substr(generalMarker + 1, secondMarker - generalMarker - 1); - generalMarker = atoi(g.c_str()); - } - v = kvPairs.substr(secondMarker + 1, thirdMarker - secondMarker - 1); - //DEBUG_LOG(("%d [%s] [%s]\n", generalMarker, k.c_str(), v.c_str())); - offset = thirdMarker - 1; - - CHECK(wins); - CHECK(losses); - CHECK(games); - CHECK(duration); - CHECK(unitsKilled); - CHECK(unitsLost); - CHECK(unitsBuilt); - CHECK(buildingsKilled); - CHECK(buildingsLost); - CHECK(buildingsBuilt); - CHECK(earnings); - CHECK(techCaptured); - CHECK(discons); - CHECK(desyncs); - CHECK(surrenders); - CHECK(gamesOf2p); - CHECK(gamesOf3p); - CHECK(gamesOf4p); - CHECK(gamesOf5p); - CHECK(gamesOf6p); - CHECK(gamesOf7p); - CHECK(gamesOf8p); - CHECK(customGames); - CHECK(QMGames); - - if (k == "locale" && generalMarker < 0) - { - s.locale = atoi(v.c_str()); - continue; - } - - if (k == "random" && generalMarker < 0) - { - s.gamesAsRandom = atoi(v.c_str()); - continue; - } - - if (k == "options" && generalMarker < 0) - { - s.options = v; - continue; - } - - if (k == "systemSpec" && generalMarker < 0) - { - s.systemSpec = v; - continue; - } - - if (k == "fps" && generalMarker < 0) - { - s.lastFPS = atof(v.c_str()); - continue; - } - - if (k == "lastGeneral" && generalMarker < 0) - { - s.lastGeneral = atoi(v.c_str()); - continue; - } - if (k == "genInRow" && generalMarker < 0) - { - s.gamesInRowWithLastGeneral = atoi(v.c_str()); - continue; - } - if (k == "builtNuke" && generalMarker < 0) - { - s.builtNuke = atoi(v.c_str()); - continue; - } - if (k == "builtSCUD" && generalMarker < 0) - { - s.builtSCUD = atoi(v.c_str()); - continue; - } - if (k == "builtCannon" && generalMarker < 0) - { - s.builtParticleCannon = atoi(v.c_str()); - continue; - } - if (k == "challenge" && generalMarker < 0) - { - s.challengeMedals = atoi(v.c_str()); - continue; - } - if (k == "battle" && generalMarker < 0) - { - s.battleHonors = atoi(v.c_str()); - continue; - } - - if (k == "WinRow" && generalMarker < 0) - { - s.winsInARow = atoi(v.c_str()); - continue; - } - if (k == "WinRowMax" && generalMarker < 0) - { - s.maxWinsInARow = atoi(v.c_str()); - continue; - } - - if (k == "LossRow" && generalMarker < 0) - { - s.lossesInARow = atoi(v.c_str()); - continue; - } - if (k == "LossRowMax" && generalMarker < 0) - { - s.maxLossesInARow = atoi(v.c_str()); - continue; - } - - if (k == "DSRow" && generalMarker < 0) - { - s.desyncsInARow = atoi(v.c_str()); - continue; - } - if (k == "DSRowMax" && generalMarker < 0) - { - s.maxDesyncsInARow = atoi(v.c_str()); - continue; - } - - if (k == "DCRow" && generalMarker < 0) - { - s.disconsInARow = atoi(v.c_str()); - continue; - } - if (k == "DCRowMax" && generalMarker < 0) - { - s.maxDisconsInARow = atoi(v.c_str()); - continue; - } - - if (k == "ladderPort" && generalMarker < 0) - { - s.lastLadderPort = atoi(v.c_str()); - continue; - } - if (k == "ladderHost" && generalMarker < 0) - { - s.lastLadderHost = v; - continue; - } - - //DEBUG_ASSERTCRASH(generalMarker >= 0, ("Unknown KV Pair in persistent storage: [%s] = [%s]\n", k.c_str(), v.c_str())); - //DEBUG_ASSERTCRASH(generalMarker < 0, ("Unknown KV Pair in persistent storage for PlayerTemplate %d: [%s] = [%s]\n", generalMarker, k.c_str(), v.c_str())); - } - - return s; -} - -#define ITERATE_OVER(x) for (it = stats.x.begin(); it != stats.x.end(); ++it) \ -{ \ - if (it->second > 0) \ - { \ - sprintf(kvbuf, "\\" #x "%d\\%d", it->first, it->second); \ - s.append(kvbuf); \ - } \ -} - -#include "Common/PlayerTemplate.h" - -std::string GameSpyPSMessageQueueInterface::formatPlayerKVPairs( PSPlayerStats stats ) -{ - char kvbuf[256]; - std::string s = ""; - PerGeneralMap::iterator it; - - ITERATE_OVER(wins); - ITERATE_OVER(losses); - ITERATE_OVER(games); - ITERATE_OVER(duration); - ITERATE_OVER(unitsKilled); - ITERATE_OVER(unitsLost); - ITERATE_OVER(unitsBuilt); - ITERATE_OVER(buildingsKilled); - ITERATE_OVER(buildingsLost); - ITERATE_OVER(buildingsBuilt); - ITERATE_OVER(earnings); - ITERATE_OVER(techCaptured); - - //GS Report all disconnects, even if zero, because might have been - //previously reported as 1 by updateAdditionalGameSpyDisconnections -// ITERATE_OVER(discons); - for (Int ptIdx = 0; ptIdx < ThePlayerTemplateStore->getPlayerTemplateCount(); ++ptIdx) - { -// const PlayerTemplate* pTemplate = ThePlayerTemplateStore->getNthPlayerTemplate(ptIdx); -// const GeneralPersona* pGeneral = TheChallengeGenerals->getGeneralByTemplateName(pTemplate->getName()); -// BOOL isReported = pGeneral ? pGeneral->isStartingEnabled() : FALSE; -// if( !isReported ) -// continue; //don't report unplayable templates (observer, boss, etc.) - - sprintf(kvbuf, "\\discons%d\\%d", ptIdx, stats.discons[ptIdx]); - s.append(kvbuf); - } - - ITERATE_OVER(desyncs); - ITERATE_OVER(surrenders); - ITERATE_OVER(gamesOf2p); - ITERATE_OVER(gamesOf3p); - ITERATE_OVER(gamesOf4p); - ITERATE_OVER(gamesOf5p); - ITERATE_OVER(gamesOf6p); - ITERATE_OVER(gamesOf7p); - ITERATE_OVER(gamesOf8p); - ITERATE_OVER(customGames); - ITERATE_OVER(QMGames); - - if (stats.locale > 0) - { - sprintf(kvbuf, "\\locale\\%d", stats.locale); - s.append(kvbuf); - } - - if (stats.gamesAsRandom > 0) - { - sprintf(kvbuf, "\\random\\%d", stats.gamesAsRandom); - s.append(kvbuf); - } - - if (stats.options.length()) - { - _snprintf(kvbuf, 256, "\\options\\%s", stats.options.c_str()); - kvbuf[255] = 0; - s.append(kvbuf); - } - - if (stats.systemSpec.length()) - { - _snprintf(kvbuf, 256, "\\systemSpec\\%s", stats.systemSpec.c_str()); - kvbuf[255] = 0; - s.append(kvbuf); - } - - if (stats.lastFPS > 0.0f) - { - sprintf(kvbuf, "\\fps\\%g", stats.lastFPS); - s.append(kvbuf); - } - if (stats.lastGeneral >= 0) - { - sprintf(kvbuf, "\\lastGeneral\\%d", stats.lastGeneral); - s.append(kvbuf); - } - if (stats.gamesInRowWithLastGeneral >= 0) - { - sprintf(kvbuf, "\\genInRow\\%d", stats.gamesInRowWithLastGeneral); - s.append(kvbuf); - } - if (stats.builtParticleCannon >= 0) - { - sprintf(kvbuf, "\\builtCannon\\%d", stats.builtParticleCannon); - s.append(kvbuf); - } - if (stats.builtNuke >= 0) - { - sprintf(kvbuf, "\\builtNuke\\%d", stats.builtNuke); - s.append(kvbuf); - } - if (stats.builtSCUD >= 0) - { - sprintf(kvbuf, "\\builtSCUD\\%d", stats.builtSCUD); - s.append(kvbuf); - } - if (stats.challengeMedals > 0) - { - sprintf(kvbuf, "\\challenge\\%d", stats.challengeMedals); - s.append(kvbuf); - } - if (stats.battleHonors > 0) - { - sprintf(kvbuf, "\\battle\\%d", stats.battleHonors); - s.append(kvbuf); - } - - //if (stats.winsInARow > 0) - { - sprintf(kvbuf, "\\WinRow\\%d", stats.winsInARow); - s.append(kvbuf); - } - if (stats.maxWinsInARow > 0) - { - sprintf(kvbuf, "\\WinRowMax\\%d", stats.maxWinsInARow); - s.append(kvbuf); - } - - //if (stats.lossesInARow > 0) - { - sprintf(kvbuf, "\\LossRow\\%d", stats.lossesInARow); - s.append(kvbuf); - } - if (stats.maxLossesInARow > 0) - { - sprintf(kvbuf, "\\LossRowMax\\%d", stats.maxLossesInARow); - s.append(kvbuf); - } - - //if (stats.disconsInARow > 0) - { - sprintf(kvbuf, "\\DCRow\\%d", stats.disconsInARow); - s.append(kvbuf); - } - if (stats.maxDisconsInARow > 0) - { - sprintf(kvbuf, "\\DCRowMax\\%d", stats.maxDisconsInARow); - s.append(kvbuf); - } - - //if (stats.desyncsInARow > 0) - { - sprintf(kvbuf, "\\DSRow\\%d", stats.desyncsInARow); - s.append(kvbuf); - } - if (stats.maxDesyncsInARow > 0) - { - sprintf(kvbuf, "\\DSRowMax\\%d", stats.maxDesyncsInARow); - s.append(kvbuf); - } - - if (stats.lastLadderPort > 0) - { - sprintf(kvbuf, "\\ladderPort\\%d", stats.lastLadderPort); - s.append(kvbuf); - } - if (stats.lastLadderHost.length()) - { - _snprintf(kvbuf, 256, "\\ladderHost\\%s", stats.lastLadderHost.c_str()); - kvbuf[255] = 0; - s.append(kvbuf); - } - - DEBUG_LOG(("Formatted persistent values as '%s'\n", s.c_str())); - return s; -} - -//------------------------------------------------------------------------- diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PingThread.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PingThread.cpp deleted file mode 100644 index 75ea0c1058b..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PingThread.cpp +++ /dev/null @@ -1,575 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: PingThread.cpp ////////////////////////////////////////////////////// -// Ping thread -// Author: Matthew D. Campbell, August 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include // This one has to be here. Prevents collisions with windsock2.h - -#include "GameNetwork/GameSpy/PingThread.h" -#include "mutex.h" -#include "thread.h" - -#include "Common/StackDump.h" -#include "Common/SubsystemInterface.h" - -//------------------------------------------------------------------------- - -static const Int NumWorkerThreads = 10; - -typedef std::queue RequestQueue; -typedef std::queue ResponseQueue; -class PingThreadClass; - -class Pinger : public PingerInterface -{ -public: - virtual ~Pinger(); - Pinger(); - virtual void startThreads( void ); - virtual void endThreads( void ); - virtual Bool areThreadsRunning( void ); - - virtual void addRequest( const PingRequest& req ); - virtual Bool getRequest( PingRequest& resp ); - - virtual void addResponse( const PingResponse& resp ); - virtual Bool getResponse( PingResponse& resp ); - - virtual Bool arePingsInProgress( void ); - virtual Int getPing( AsciiString hostname ); - - virtual void clearPingMap( void ); - virtual AsciiString getPingString( Int timeout ); - -private: - MutexClass m_requestMutex; - MutexClass m_responseMutex; - MutexClass m_pingMapMutex; - RequestQueue m_requests; - ResponseQueue m_responses; - Int m_requestCount; - Int m_responseCount; - - std::map m_pingMap; - - PingThreadClass *m_workerThreads[NumWorkerThreads]; -}; - -PingerInterface* PingerInterface::createNewPingerInterface( void ) -{ - return NEW Pinger; -} - -PingerInterface *ThePinger; - -//------------------------------------------------------------------------- - -class PingThreadClass : public ThreadClass -{ - -public: - PingThreadClass() : ThreadClass() {} - - void Thread_Function(); - -private: - Int doPing( UnsignedInt IP, Int timeout ); -}; - - -//------------------------------------------------------------------------- - -Pinger::Pinger() : m_requestCount(0), m_responseCount(0) -{ - for (Int i=0; iExecute(); - } -} - -void Pinger::endThreads( void ) -{ - for (Int i=0; iIs_Running()) - return true; - } - } - return false; -} - -void Pinger::addRequest( const PingRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex); - - ++m_requestCount; - m_requests.push(req); -} - -Bool Pinger::getRequest( PingRequest& req ) -{ - MutexClass::LockClass m(m_requestMutex, 0); - if (m.Failed()) - return false; - - if (m_requests.empty()) - return false; - req = m_requests.front(); - m_requests.pop(); - return true; -} - -void Pinger::addResponse( const PingResponse& resp ) -{ - { - MutexClass::LockClass m(m_pingMapMutex); - - m_pingMap[resp.hostname] = resp.avgPing; - } - { - MutexClass::LockClass m(m_responseMutex); - - ++m_responseCount; - m_responses.push(resp); - } -} - -Bool Pinger::getResponse( PingResponse& resp ) -{ - MutexClass::LockClass m(m_responseMutex, 0); - if (m.Failed()) - return false; - - if (m_responses.empty()) - return false; - resp = m_responses.front(); - m_responses.pop(); - return true; -} - -Bool Pinger::arePingsInProgress( void ) -{ - return (m_requestCount != m_responseCount); -} - -Int Pinger::getPing( AsciiString hostname ) -{ - MutexClass::LockClass m(m_pingMapMutex, 0); - if (m.Failed()) - return false; - - std::map::const_iterator it = m_pingMap.find(hostname.str()); - if (it != m_pingMap.end()) - return it->second; - - return -1; -} - -void Pinger::clearPingMap( void ) -{ - MutexClass::LockClass m(m_pingMapMutex); - m_pingMap.clear(); -} - -AsciiString Pinger::getPingString( Int timeout ) -{ - MutexClass::LockClass m(m_pingMapMutex); - - AsciiString pingString; - AsciiString tmp; - for (std::map::const_iterator it = m_pingMap.begin(); it != m_pingMap.end(); ++it) - { - Int ping = it->second; - if (ping < 0 || ping > timeout) - ping = timeout; - ping = ping * 255 / timeout; - tmp.format("%2.2X", ping); - pingString.concat(tmp); - } - return pingString; -} - -//------------------------------------------------------------------------- - -void PingThreadClass::Thread_Function() -{ - try { - _set_se_translator( DumpExceptionInfo ); // Hook that allows stack trace. - PingRequest req; - - WSADATA wsaData; - - // Fire up winsock (prob already done, but doesn't matter) - WORD wVersionRequested = MAKEWORD(1, 1); - WSAStartup( wVersionRequested, &wsaData ); - - while ( running ) - { - // deal with requests - if (ThePinger->getRequest(req)) - { - // resolve the hostname - const char *hostnameBuffer = req.hostname.c_str(); - UnsignedInt IP = 0xFFFFFFFF; - if (isdigit(hostnameBuffer[0])) - { - IP = inet_addr(hostnameBuffer); - in_addr hostNode; - hostNode.s_addr = IP; - DEBUG_LOG(("pinging %s - IP = %s\n", hostnameBuffer, inet_ntoa(hostNode) )); - } - else - { - HOSTENT *hostStruct; - in_addr *hostNode; - hostStruct = gethostbyname(hostnameBuffer); - if (hostStruct == NULL) - { - DEBUG_LOG(("pinging %s - host lookup failed\n", hostnameBuffer)); - - // Even though this failed to resolve IP, still need to send a - // callback. - IP = 0xFFFFFFFF; // flag for IP resolve failed - } - hostNode = (in_addr *) hostStruct->h_addr; - IP = hostNode->s_addr; - DEBUG_LOG(("pinging %s IP = %s\n", hostnameBuffer, inet_ntoa(*hostNode) )); - } - - // do ping - Int totalPing = 0; - Int goodReps = 0; - Int reps = req.repetitions; - while (reps-- && running && IP != 0xFFFFFFFF) - { - Int ping = doPing(IP, req.timeout); - if (ping >= 0) - { - totalPing += ping; - ++goodReps; - } - - // end our timeslice - Switch_Thread(); - } - if (!goodReps) - totalPing = -1; - else - totalPing = totalPing / goodReps; - - PingResponse resp; - resp.hostname = req.hostname; - resp.avgPing = totalPing; - resp.repetitions = goodReps; - ThePinger->addResponse(resp); - } - - // end our timeslice - Switch_Thread(); - } - - WSACleanup(); - } catch ( ... ) { - DEBUG_CRASH(("Exception in ping thread!")); - } -} - -//------------------------------------------------------------------------- -//------------------------------------------------------------------------- -//------------------------------------------------------------------------- -//------------------------------------------------------------------------- -//------------------------------------------------------------------------- -//------------------------------------------------------------------------- - -HANDLE WINAPI IcmpCreateFile(VOID); /* INVALID_HANDLE_VALUE on error */ -BOOL WINAPI IcmpCloseHandle(HANDLE IcmpHandle); /* FALSE on error */ - -/* Note 2: For the most part, you can refer to RFC 791 for detials - * on how to fill in values for the IP option information structure. - */ -typedef struct ip_option_information -{ - UnsignedByte Ttl; /* Time To Live (used for traceroute) */ - UnsignedByte Tos; /* Type Of Service (usually 0) */ - UnsignedByte Flags; /* IP header flags (usually 0) */ - UnsignedByte OptionsSize; /* Size of options data (usually 0, max 40) */ - UnsignedByte FAR *OptionsData; /* Options data buffer */ -} -IPINFO, *PIPINFO, FAR *LPIPINFO; - - -/* Note 1: The Reply Buffer will have an array of ICMP_ECHO_REPLY - * structures, followed by options and the data in ICMP echo reply - * datagram received. You must have room for at least one ICMP - * echo reply structure, plus 8 bytes for an ICMP header. - */ -typedef struct icmp_echo_reply -{ - UnsignedInt Address; /* source address */ - ////////UnsignedInt Status; /* IP status value (see below) */ - UnsignedInt RTTime; /* Round Trip Time in milliseconds */ - UnsignedShort DataSize; /* reply data size */ - UnsignedShort Reserved; /* */ - void FAR *Data; /* reply data buffer */ - struct ip_option_information Options; /* reply options */ -} -ICMPECHO, *PICMPECHO, FAR *LPICMPECHO; - - -DWORD WINAPI IcmpSendEcho( - HANDLE IcmpHandle, /* handle returned from IcmpCreateFile() */ - UnsignedInt DestAddress, /* destination IP address (in network order) */ - LPVOID RequestData, /* pointer to buffer to send */ - WORD RequestSize, /* length of data in buffer */ - LPIPINFO RequestOptns, /* see Note 2 */ - LPVOID ReplyBuffer, /* see Note 1 */ - DWORD ReplySize, /* length of reply (must allow at least 1 reply) */ - DWORD Timeout /* time in milliseconds to wait for reply */ -); - - -#define IP_STATUS_BASE 11000 -#define IP_SUCCESS 0 -#define IP_BUF_TOO_SMALL (IP_STATUS_BASE + 1) -#define IP_DEST_NET_UNREACHABLE (IP_STATUS_BASE + 2) -#define IP_DEST_HOST_UNREACHABLE (IP_STATUS_BASE + 3) -#define IP_DEST_PROT_UNREACHABLE (IP_STATUS_BASE + 4) -#define IP_DEST_PORT_UNREACHABLE (IP_STATUS_BASE + 5) -#define IP_NO_RESOURCES (IP_STATUS_BASE + 6) -#define IP_BAD_OPTION (IP_STATUS_BASE + 7) -#define IP_HW_ERROR (IP_STATUS_BASE + 8) -#define IP_PACKET_TOO_BIG (IP_STATUS_BASE + 9) -#define IP_REQ_TIMED_OUT (IP_STATUS_BASE + 10) -#define IP_BAD_REQ (IP_STATUS_BASE + 11) -#define IP_BAD_ROUTE (IP_STATUS_BASE + 12) -#define IP_TTL_EXPIRED_TRANSIT (IP_STATUS_BASE + 13) -#define IP_TTL_EXPIRED_REASSEM (IP_STATUS_BASE + 14) -#define IP_PARAM_PROBLEM (IP_STATUS_BASE + 15) -#define IP_SOURCE_QUENCH (IP_STATUS_BASE + 16) -#define IP_OPTION_TOO_BIG (IP_STATUS_BASE + 17) -#define IP_BAD_DESTINATION (IP_STATUS_BASE + 18) -#define IP_ADDR_DELETED (IP_STATUS_BASE + 19) -#define IP_SPEC_MTU_CHANGE (IP_STATUS_BASE + 20) -#define IP_MTU_CHANGE (IP_STATUS_BASE + 21) -#define IP_UNLOAD (IP_STATUS_BASE + 22) -#define IP_GENERAL_FAILURE (IP_STATUS_BASE + 50) -#define MAX_IP_STATUS IP_GENERAL_FAILURE -#define IP_PENDING (IP_STATUS_BASE + 255) - - -#define BUFSIZE 8192 -#define DEFAULT_LEN 32 -#define LOOPLIMIT 4 -#define DEFAULT_TTL 64 - -Int PingThreadClass::doPing(UnsignedInt IP, Int timeout) -{ - /* - * Initialize default settings - */ - - IPINFO stIPInfo, *lpstIPInfo; - HANDLE hICMP, hICMP_DLL; - int i, j, nDataLen, nLoopLimit, nTimeOut, nTTL, nTOS; - DWORD dwReplyCount; - ///////IN_ADDR stDestAddr; - BOOL fRet, fDontStop; - ///BOOL fTraceRoute; - - nDataLen = DEFAULT_LEN; - nLoopLimit = LOOPLIMIT; - nTimeOut = timeout; - fDontStop = FALSE; - lpstIPInfo = NULL; - nTTL = DEFAULT_TTL; - nTOS = 0; - - Int pingTime = -1; // in case of error - - char achReqData[BUFSIZE]; - char achRepData[sizeof(ICMPECHO) + BUFSIZE]; - - - HANDLE ( WINAPI *lpfnIcmpCreateFile )( VOID ) = NULL; - BOOL ( WINAPI *lpfnIcmpCloseHandle )( HANDLE ) = NULL; - DWORD (WINAPI *lpfnIcmpSendEcho)(HANDLE, DWORD, LPVOID, WORD, LPVOID, - LPVOID, DWORD, DWORD) = NULL; - - - /* - * Load the ICMP.DLL - */ - hICMP_DLL = LoadLibrary("ICMP.DLL"); - if (hICMP_DLL == 0) - { - DEBUG_LOG(("LoadLibrary() failed: Unable to locate ICMP.DLL!\n")); - goto cleanup; - } - - /* - * Get pointers to ICMP.DLL functions - */ - lpfnIcmpCreateFile = (void * (__stdcall *)(void))GetProcAddress( (HINSTANCE)hICMP_DLL, "IcmpCreateFile"); - lpfnIcmpCloseHandle = (int (__stdcall *)(void *))GetProcAddress( (HINSTANCE)hICMP_DLL, "IcmpCloseHandle"); - lpfnIcmpSendEcho = (unsigned long (__stdcall *)(void *, unsigned long, void *, unsigned short, - void *, void *, unsigned long, unsigned long))GetProcAddress( (HINSTANCE)hICMP_DLL, "IcmpSendEcho" ); - - if ((!lpfnIcmpCreateFile) || - (!lpfnIcmpCloseHandle) || - (!lpfnIcmpSendEcho)) - { - DEBUG_LOG(("GetProcAddr() failed for at least one function.\n")); - goto cleanup; - } - - - /* - * IcmpCreateFile() - Open the ping service - */ - hICMP = (HANDLE) lpfnIcmpCreateFile(); - if (hICMP == INVALID_HANDLE_VALUE) - { - DEBUG_LOG(("IcmpCreateFile() failed")); - goto cleanup; - } - - /* - * Init data buffer printable ASCII - * 32 (space) through 126 (tilde) - */ - for (j = 0, i = 32; j < nDataLen; j++, i++) - { - if (i >= 126) - i = 32; - achReqData[j] = i; - } - - /* - * Init IPInfo structure - */ - lpstIPInfo = &stIPInfo; - stIPInfo.Ttl = nTTL; - stIPInfo.Tos = nTOS; - stIPInfo.Flags = 0; - stIPInfo.OptionsSize = 0; - stIPInfo.OptionsData = NULL; - - - - /* - * IcmpSendEcho() - Send the ICMP Echo Request - * and read the Reply - */ - dwReplyCount = lpfnIcmpSendEcho( - hICMP, - IP, - achReqData, - nDataLen, - lpstIPInfo, - achRepData, - sizeof(achRepData), - nTimeOut); - if (dwReplyCount != 0) - { - //////////IN_ADDR stDestAddr; - DWORD dwStatus; - - pingTime = (*(UnsignedInt *) & (achRepData[8])); - - // I've seen the ping time bigger than the timeout by a little - // bit. How lame. - if (pingTime > timeout) - pingTime = timeout; - - dwStatus = *(DWORD *) & (achRepData[4]); - if (dwStatus != IP_SUCCESS) - { - DEBUG_LOG(("ICMPERR: %d\n", dwStatus)); - } - - } - else - { - DEBUG_LOG(("IcmpSendEcho() failed: %d\n", dwReplyCount)); - // Ok we didn't get a packet, just say everything's OK - // and the time was -1 - pingTime = -1; - goto cleanup; - } - - - /* - * IcmpCloseHandle - Close the ICMP handle - */ - fRet = lpfnIcmpCloseHandle(hICMP); - if (fRet == FALSE) - { - DEBUG_LOG(("Error closing ICMP handle\n")); - } - - // Say what you will about goto's but it's handy for stuff like this -cleanup: - - // Shut down... - if (hICMP_DLL) - FreeLibrary((HINSTANCE)hICMP_DLL); - - return pingTime; -} - - -//------------------------------------------------------------------------- diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/ThreadUtils.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/ThreadUtils.cpp deleted file mode 100644 index f2835739e75..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/ThreadUtils.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ThreadUtils.cpp ////////////////////////////////////////////////////// -// GameSpy thread utils -// Author: Matthew D. Campbell, July 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -//------------------------------------------------------------------------- - -std::wstring MultiByteToWideCharSingleLine( const char *orig ) -{ - Int len = strlen(orig); - WideChar *dest = NEW WideChar[len+1]; - - MultiByteToWideChar(CP_UTF8, 0, orig, -1, dest, len); - WideChar *c = NULL; - do - { - c = wcschr(dest, L'\n'); - if (c) - { - *c = L' '; - } - } - while ( c != NULL ); - do - { - c = wcschr(dest, L'\r'); - if (c) - { - *c = L' '; - } - } - while ( c != NULL ); - - dest[len] = 0; - std::wstring ret = dest; - delete dest; - return ret; -} - -std::string WideCharStringToMultiByte( const WideChar *orig ) -{ - std::string ret; - Int len = WideCharToMultiByte( CP_UTF8, 0, orig, wcslen(orig), NULL, 0, NULL, NULL ) + 1; - if (len > 0) - { - char *dest = NEW char[len]; - WideCharToMultiByte( CP_UTF8, 0, orig, -1, dest, len, NULL, NULL ); - dest[len-1] = 0; - ret = dest; - delete dest; - } - return ret; -} - -//------------------------------------------------------------------------- - diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpyChat.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpyChat.cpp deleted file mode 100644 index 23d9be07b64..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpyChat.cpp +++ /dev/null @@ -1,455 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameSpyChat.cpp ////////////////////////////////////////////////////// -// GameSpy chat handlers -// Author: Matthew D. Campbell, February 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "GameClient/GameText.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/LanguageFilter.h" -#include "GameNetwork/GameSpy.h" -#include "GameNetwork/GameSpyChat.h" -#include "Common/QuotedPrintable.h" - -typedef set::const_iterator AsciiSetIter; - -/** - * handleSlashCommands looks for slash ccommands and handles them, - * returning true if it found one, false otherwise. - * /i,/ignore list ignored players - * /i,/ignore +name1 -name2 ignore name1, stop ignoring name2 - * /m,/me: shorthand for an action - * /o,/on: find command to look up a user's location - * /f,/find: find command to look up a user's location - * /p,/page: page user(s) - * /r,/reply: reply to last page - * /raw: raw IRC command (only in debug & internal) - * /oper: become an IRC op (only in debug & internal) - * /quit: send the IRC quit command to exit WOL - */ -static Bool handleSlashCommands( UnicodeString message, Bool isAction, GameWindow *playerListbox ) -{ - /* - if (message.getCharAt(0) == L'/') - { - UnicodeString remainder = UnicodeString(message.str() + 1); - UnicodeString token; - - switch (message.getCharAt(1)) - { - case L'i': - case L'I': - remainder.nextToken(&token); - if (token.compareNoCase(L"i") == 0 || token.compareNoCase(L"ignore") == 0) - { - if (remainder.isEmpty()) - { - // List the people we're ignoring - TheWOL->addText(TheGameText->fetch("WOL:BeginIgnoreList")); - set *ignoreList = getIgnoreList(); - if (ignoreList) - { - UnicodeString msg; - UnicodeString uName; - AsciiSetIter iter = ignoreList->begin(); - while (iter != ignoreList->end()) - { - uName.translate(*iter); - msg.format(TheGameText->fetch("WOL:IgnoredUser"), uName.str()); - TheWOL->addText(msg); - iter++; - } - } - TheWOL->addText(TheGameText->fetch("WOL:EndIgnoreList")); - } - - while ( remainder.nextToken(&token) ) - { - AsciiString name; - int doIgnore = 0; - if (token.getCharAt(0) == L'+') - { - // Ignore somebody - token = UnicodeString(token.str() + 1); - name.translate(token); - doIgnore = 1; - } - else if (token.getCharAt(0) == L'-') - { - // Listen to someone again - token = UnicodeString(token.str() + 1); - name.translate(token); - doIgnore = 0; - } - else - { - // Ignore somebody - token = UnicodeString(token.str()); - name.translate(token); - doIgnore = 1; - } - IChat *ichat = TheWOL->getIChat(); - User user; - strncpy((char *)user.name, name.str(), 9); - user.name[9] = 0; - ichat->SetSquelch(&user, doIgnore); - - if (doIgnore) - addIgnore(name); - else - removeIgnore(name); - - UnicodeString msg; - UnicodeString uName; - uName.translate(name); - msg.format(TheGameText->fetch("WOL:IgnoredUser"), uName.str()); - TheWOL->addText(msg); - } - return true; - } - break; - case L'r': - case L'R': - remainder.nextToken(&token); -#if defined _DEBUG || defined _INTERNAL - if (token.compareNoCase(L"raw") == 0) - { - // Send raw IRC commands (Ascii only) - AsciiString str; - str.translate(remainder); - str.concat('\n'); - IChat *ichat = TheWOL->getIChat(); - ichat->RequestRawMessage(str.str()); - TheWOL->addText(remainder); - return true; // show it anyway - } -#endif - break; -#if defined _DEBUG || defined _INTERNAL - case L'k': - case L'K': - remainder.nextToken(&token); - if (token.compareNoCase(L"kick") == 0) - { - - while ( remainder.nextToken(&token) ) - { - AsciiString name; - name.translate(token); - IChat *ichat = TheWOL->getIChat(); - User user; - strncpy((char *)user.name, name.str(), 9); - user.name[9] = 0; - ichat->RequestUserKick(&user); - } - return true; - } - break; -#endif - case L'o': - case L'O': - remainder.nextToken(&token); - if (token.compareNoCase(L"on") == 0 || token.compareNoCase(L"o") == 0) - { - remainder.nextToken(&token); - AsciiString userName; - userName.translate(token); - User user; - strncpy((char *)user.name, userName.str(), 10); - user.name[9] = 0; - if (user.name[0] == 0) - { - // didn't enter a name - TheWOL->addText(message); - } - else - { - // Send find command - IChat *ichat = TheWOL->getIChat(); - ichat->RequestGlobalFind(&user); - } - return true; // show it anyway - } -#if defined _DEBUG || defined _INTERNAL - else if (token.compareNoCase(L"oper") == 0) - { - // Send raw IRC oper command - AsciiString str; - str.translate(message); - str.concat('\n'); - IChat *ichat = TheWOL->getIChat(); - ichat->RequestRawMessage(str.str()); - TheWOL->addText(message); - return true; // show it anyway - } -#endif - break; - case L'p': - case L'P': - remainder.nextToken(&token); - if (token.compareNoCase(L"page") == 0 || token.compareNoCase(L"p") == 0) - { - remainder.nextToken(&token); - AsciiString userName; - userName.translate(token); - User user; - strncpy((char *)user.name, userName.str(), 10); - user.name[9] = 0; - remainder.trim(); - if (user.name[0] == 0 || remainder.isEmpty()) - { - // didn't enter a name or message - TheWOL->addText(message); - } - else - { - // Send page command - IChat *ichat = TheWOL->getIChat(); - ichat->RequestGlobalUnicodePage(&user, remainder.str()); - } - return true; // show it anyway - } - break; - case L'q': - case L'Q': - remainder.nextToken(&token); - if (token.compareNoCase(L"quit") == 0) - { - TheWOL->setState(WOLAPI_LOGIN); - TheWOL->addCommand(WOLCOMMAND_LOGOUT); - //TheWOL->setScreen(WOLAPI_MENU_WELCOME); - return true; // show it anyway - } - break; -#if defined _DEBUG || defined _INTERNAL - case L'c': - case L'C': - remainder.nextToken(&token); - if (token.compareNoCase(L"colortest") == 0) - { - addColorText(token, 0xDD, 0xE2, 0x0D, 0xff); - addColorText(token, 0xFF, 0x19, 0x19, 0xff); - addColorText(token, 0x2A, 0x74, 0xE2, 0xff); - addColorText(token, 0x3E, 0xD1, 0x2E, 0xff); - addColorText(token, 0xFF, 0xA0, 0x19, 0xff); - addColorText(token, 0x32, 0xD7, 0xE6, 0xff); - addColorText(token, 0x95, 0x28, 0xBD, 0xff); - addColorText(token, 0xFF, 0x9A, 0xEB, 0xff); - return true; // show it anyway - } - break; -#endif // _DEBUG || defined _INTERNAL - } - } - */ - return false; -} - -static handleUnicodeMessage( const char *nick, UnicodeString msg, Bool isPublic, Bool isAction ); - -Bool GameSpySendChat( UnicodeString message, Bool isAction, GameWindow *playerListbox ) -{ - RoomType roomType = StagingRoom; - if (TheGameSpyChat->getCurrentGroupRoomID()) - roomType = GroupRoom; - - message.trim(); - // Echo the user's input to the chat window - if (!message.isEmpty()) - { - // Check for slash commands - if (handleSlashCommands(message, isAction, playerListbox)) - { - return false; // already handled - } - - if (!playerListbox) - { - // Public message - if (isAction) - { - peerMessageRoom(TheGameSpyChat->getPeer(), roomType, UnicodeStringToQuotedPrintable(message).str(), ActionMessage); - //if (roomType == StagingRoom) - //handleUnicodeMessage(TheGameSpyChat->getloginName().str(), message, true, true); - } - else - { - peerMessageRoom(TheGameSpyChat->getPeer(), roomType, UnicodeStringToQuotedPrintable(message).str(), NormalMessage); - //if (roomType == StagingRoom) - //handleUnicodeMessage(TheGameSpyChat->getloginName().str(), message, true, false); - } - return false; - } - - // Get the selections (is this a private message?) - Int maxSel = GadgetListBoxGetListLength(playerListbox); - Int *selections; - GadgetListBoxGetSelected(playerListbox, (Int *)&selections); - - if (selections[0] == -1) - { - // Public message - if (isAction) - { - peerMessageRoom(TheGameSpyChat->getPeer(), roomType, UnicodeStringToQuotedPrintable(message).str(), ActionMessage); - //if (roomType == StagingRoom) - //handleUnicodeMessage(TheGameSpyChat->getloginName().str(), message, true, true); - } - else - { - peerMessageRoom(TheGameSpyChat->getPeer(), roomType, UnicodeStringToQuotedPrintable(message).str(), NormalMessage); - //if (roomType == StagingRoom) - //handleUnicodeMessage(TheGameSpyChat->getloginName().str(), message, true, false); - } - return false; - } - else - { - // Private message - - // Construct a list - AsciiString names = AsciiString::TheEmptyString; - AsciiString tmp = AsciiString::TheEmptyString; - AsciiString aStr; // AsciiString buf for translating Unicode entries - names.format("%s", TheGameSpyChat->getLoginName().str()); - for (int i=0; igetLoginName())) - { - tmp.format(",%s", aStr.str()); - names.concat(tmp); - } - } - else - { - break; - } - } - - if (!names.isEmpty()) - { - if (isAction) - { - peerMessagePlayer(TheGameSpyChat->getPeer(), names.str(), UnicodeStringToQuotedPrintable(message).str(), ActionMessage); - } - else - { - peerMessagePlayer(TheGameSpyChat->getPeer(), names.str(), UnicodeStringToQuotedPrintable(message).str(), NormalMessage); - } - } - - return true; - } - } - return false; -} - -void RoomMessageCallback(PEER peer, RoomType roomType, - const char * nick, const char * message, - MessageType messageType, void * param) -{ - DEBUG_LOG(("RoomMessageCallback\n")); - handleUnicodeMessage(nick, QuotedPrintableToUnicodeString(message), true, (messageType == ActionMessage)); -} - -void PlayerMessageCallback(PEER peer, - const char * nick, const char * message, - MessageType messageType, void * param) -{ - DEBUG_LOG(("PlayerMessageCallback\n")); - handleUnicodeMessage(nick, QuotedPrintableToUnicodeString(message), false, (messageType == ActionMessage)); -} - -static handleUnicodeMessage( const char *nick, UnicodeString msg, Bool isPublic, Bool isAction ) -{ - GameSpyColors style; - - Bool isOwner = false; - Int flags = 0; - if (TheGameSpyChat->getCurrentGroupRoomID()) - peerGetPlayerFlags(TheGameSpyChat->getPeer(), nick, GroupRoom, &flags); - else - peerGetPlayerFlags(TheGameSpyChat->getPeer(), nick, StagingRoom, &flags); - isOwner = flags & PEER_FLAG_OP; - - if (isPublic && isAction) - { - style = (isOwner)?GSCOLOR_CHAT_OWNER_EMOTE:GSCOLOR_CHAT_EMOTE; - } - else if (isPublic) - { - style = (isOwner)?GSCOLOR_CHAT_OWNER:GSCOLOR_CHAT_NORMAL; - } - else if (isAction) - { - style = (isOwner)?GSCOLOR_CHAT_PRIVATE_OWNER_EMOTE:GSCOLOR_CHAT_PRIVATE_EMOTE; - } - else - { - style = (isOwner)?GSCOLOR_CHAT_PRIVATE_OWNER:GSCOLOR_CHAT_PRIVATE; - } - - UnicodeString name; - name.translate(nick); - - // filters language -// if( TheGlobalData->m_languageFilterPref ) -// { - TheLanguageFilter->filterLine(msg); -// } - - UnicodeString fullMsg; - if (isAction) - { - fullMsg.format( L"%ls %ls", name.str(), msg.str() ); - } - else - { - fullMsg.format( L"[%ls] %ls", name.str(), msg.str() ); - } - GameSpyAddText(fullMsg, style); -} - -void GameSpyAddText( UnicodeString message, GameSpyColors color ) -{ - GameWindow *textWindow = NULL; - - if (!textWindow) - textWindow = listboxLobbyChat; - if (!textWindow) - textWindow = listboxGameSetupChat; - - if (!textWindow) - return; - - GadgetListBoxAddEntryText(textWindow, message, GameSpyColor[color], -1, -1); - -} - diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpyGP.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpyGP.cpp deleted file mode 100644 index a81eef1ac30..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpyGP.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameSpyGP.cpp ////////////////////////////////////////////////////// -// GameSpy GP callbacks, utils, etc -// Author: Matthew D. Campbell, February 2002 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "GameClient/GameText.h" -#include "GameNetwork/GameSpy.h" -#include "GameNetwork/GameSpyGP.h" -#include "GameNetwork/GameSpyOverlay.h" - -GPConnection TheGPConnectionObj; -GPConnection *TheGPConnection = &TheGPConnectionObj; -GPProfile GameSpyLocalProfile = 0; -char GameSpyProfilePassword[64]; - -void GPRecvBuddyMessageCallback(GPConnection * pconnection, GPRecvBuddyMessageArg * arg, void * param) -{ - DEBUG_LOG(("GPRecvBuddyMessageCallback: message from %d is %s\n", arg->profile, arg->message)); - - //gpGetInfo(pconn, arg->profile, GP_DONT_CHECK_CACHE, GP_BLOCKING, (GPCallback)Whois, NULL); - //printf("MESSAGE (%d): %s: %s\n", msgCount,whois, arg->message); -} - -static void buddyTryReconnect( void ) -{ - TheGameSpyChat->reconnectProfile(); -} - -void GPErrorCallback(GPConnection * pconnection, GPErrorArg * arg, void * param) -{ - DEBUG_LOG(("GPErrorCallback\n")); - - AsciiString errorCodeString; - AsciiString resultString; - - #define RESULT(x) case x: resultString = #x; break; - switch(arg->result) - { - RESULT(GP_NO_ERROR) - RESULT(GP_MEMORY_ERROR) - RESULT(GP_PARAMETER_ERROR) - RESULT(GP_NETWORK_ERROR) - RESULT(GP_SERVER_ERROR) - default: - resultString = "Unknown result!"; - } - #undef RESULT - - #define ERRORCODE(x) case x: errorCodeString = #x; break; - switch(arg->errorCode) - { - ERRORCODE(GP_GENERAL) - ERRORCODE(GP_PARSE) - ERRORCODE(GP_NOT_LOGGED_IN) - ERRORCODE(GP_BAD_SESSKEY) - ERRORCODE(GP_DATABASE) - ERRORCODE(GP_NETWORK) - ERRORCODE(GP_FORCED_DISCONNECT) - ERRORCODE(GP_CONNECTION_CLOSED) - ERRORCODE(GP_LOGIN) - ERRORCODE(GP_LOGIN_TIMEOUT) - ERRORCODE(GP_LOGIN_BAD_NICK) - ERRORCODE(GP_LOGIN_BAD_EMAIL) - ERRORCODE(GP_LOGIN_BAD_PASSWORD) - ERRORCODE(GP_LOGIN_BAD_PROFILE) - ERRORCODE(GP_LOGIN_PROFILE_DELETED) - ERRORCODE(GP_LOGIN_CONNECTION_FAILED) - ERRORCODE(GP_LOGIN_SERVER_AUTH_FAILED) - ERRORCODE(GP_NEWUSER) - ERRORCODE(GP_NEWUSER_BAD_NICK) - ERRORCODE(GP_NEWUSER_BAD_PASSWORD) - ERRORCODE(GP_UPDATEUI) - ERRORCODE(GP_UPDATEUI_BAD_EMAIL) - ERRORCODE(GP_NEWPROFILE) - ERRORCODE(GP_NEWPROFILE_BAD_NICK) - ERRORCODE(GP_NEWPROFILE_BAD_OLD_NICK) - ERRORCODE(GP_UPDATEPRO) - ERRORCODE(GP_UPDATEPRO_BAD_NICK) - ERRORCODE(GP_ADDBUDDY) - ERRORCODE(GP_ADDBUDDY_BAD_FROM) - ERRORCODE(GP_ADDBUDDY_BAD_NEW) - ERRORCODE(GP_ADDBUDDY_ALREADY_BUDDY) - ERRORCODE(GP_AUTHADD) - ERRORCODE(GP_AUTHADD_BAD_FROM) - ERRORCODE(GP_AUTHADD_BAD_SIG) - ERRORCODE(GP_STATUS) - ERRORCODE(GP_BM) - ERRORCODE(GP_BM_NOT_BUDDY) - ERRORCODE(GP_GETPROFILE) - ERRORCODE(GP_GETPROFILE_BAD_PROFILE) - ERRORCODE(GP_DELBUDDY) - ERRORCODE(GP_DELBUDDY_NOT_BUDDY) - ERRORCODE(GP_DELPROFILE) - ERRORCODE(GP_DELPROFILE_LAST_PROFILE) - ERRORCODE(GP_SEARCH) - ERRORCODE(GP_SEARCH_CONNECTION_FAILED) - default: - errorCodeString = "Unknown error code!"; - } - #undef ERRORCODE - - if(arg->fatal) - { - DEBUG_LOG(( "-----------\n")); - DEBUG_LOG(( "GP FATAL ERROR\n")); - DEBUG_LOG(( "-----------\n")); - - // if we're still connected to the chat server, tell the user. He can always hit the buddy - // button to try reconnecting. Oh yes, also hide the buddy popup. - GameSpyCloseOverlay(GSOVERLAY_BUDDY); - if (TheGameSpyChat->isConnected()) - { - GSMessageBoxYesNo(TheGameText->fetch("GUI:GPErrorTitle"), TheGameText->fetch("GUI:GPDisconnected"), buddyTryReconnect, NULL); - } - } - else - { - DEBUG_LOG(( "-----\n")); - DEBUG_LOG(( "GP ERROR\n")); - DEBUG_LOG(( "-----\n")); - } - DEBUG_LOG(( "RESULT: %s (%d)\n", resultString.str(), arg->result)); - DEBUG_LOG(( "ERROR CODE: %s (0x%X)\n", errorCodeString.str(), arg->errorCode)); - DEBUG_LOG(( "ERROR STRING: %s\n", arg->errorString)); -} - -void GPRecvBuddyStatusCallback(GPConnection * connection, GPRecvBuddyStatusArg * arg, void * param) -{ - DEBUG_LOG(("GPRecvBuddyStatusCallback: info on %d is in %d\n", arg->profile, arg->index)); - - //GameSpyUpdateBuddyOverlay(); -} - -void GPRecvBuddyRequestCallback(GPConnection * connection, GPRecvBuddyRequestArg * arg, void * param) -{ - DEBUG_LOG(("GPRecvBuddyRequestCallback: %d wants to be our buddy because '%s'\n", arg->profile, arg->reason)); -} diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpyGameInfo.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpyGameInfo.cpp deleted file mode 100644 index 3bccc0a63b5..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpyGameInfo.cpp +++ /dev/null @@ -1,754 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameSpyGameInfo.cpp ////////////////////////////////////////////////////// -// GameSpy game setup state info -// Author: Matthew D. Campbell, December 2001 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "Common/GameEngine.h" -#include "Common/Player.h" -#include "Common/PlayerList.h" -#include "Common/RandomValue.h" -#include "Common/Scorekeeper.h" -#include "GameClient/Shell.h" -#include "GameClient/GameText.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpyGameInfo.h" -#include "GameNetwork/NetworkInterface.h" -#include "GameNetwork/NetworkUtil.h" -#include "GameNetwork/NetworkDefs.h" -#include "GameNetwork/NAT.h" -#include "GameLogic/GameLogic.h" -#include "GameLogic/VictoryConditions.h" - -// Singleton ------------------------------------------ - -GameSpyGameInfo *TheGameSpyGame = NULL; - -// Helper Functions ---------------------------------------- - -GameSpyGameSlot::GameSpyGameSlot() -{ - GameSlot(); - m_gameSpyLogin.clear(); - m_gameSpyLocale.clear(); - m_profileID = 0; -} - -// Helper Functions ---------------------------------------- -/* -** Function definitions for the MIB-II entry points. -*/ - -BOOL (__stdcall *SnmpExtensionInitPtr)(IN DWORD dwUpTimeReference, OUT HANDLE *phSubagentTrapEvent, OUT AsnObjectIdentifier *pFirstSupportedRegion); -BOOL (__stdcall *SnmpExtensionQueryPtr)(IN BYTE bPduType, IN OUT RFC1157VarBindList *pVarBindList, OUT AsnInteger32 *pErrorStatus, OUT AsnInteger32 *pErrorIndex); -LPVOID (__stdcall *SnmpUtilMemAllocPtr)(IN DWORD bytes); -VOID (__stdcall *SnmpUtilMemFreePtr)(IN LPVOID pMem); - -typedef struct tConnInfoStruct { - unsigned int State; - unsigned long LocalIP; - unsigned short LocalPort; - unsigned long RemoteIP; - unsigned short RemotePort; -} ConnInfoStruct; - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) -#endif - -/*********************************************************************************************** - * Get_Local_Chat_Connection_Address -- Which address are we using to talk to the chat server? * - * * - * * - * * - * INPUT: Ptr to address to return local address * * - * * - * OUTPUT: True if success * - * * - * WARNINGS: None * - * * - * HISTORY: * - * 10/27/00 3:24PM ST : Created * - *=============================================================================================*/ -Bool GetLocalChatConnectionAddress(AsciiString serverName, UnsignedShort serverPort, UnsignedInt& localIP) -{ - //return false; - /* - ** Local defines. - */ - enum { - CLOSED = 1, - LISTENING, - SYN_SENT, - SEN_RECEIVED, - ESTABLISHED, - FIN_WAIT, - FIN_WAIT2, - CLOSE_WAIT, - LAST_ACK, - CLOSING, - TIME_WAIT, - DELETE_TCB - }; - - enum { - tcpConnState = 1, - tcpConnLocalAddress, - tcpConnLocalPort, - tcpConnRemAddress, - tcpConnRemPort - }; - - - /* - ** Locals. - */ - unsigned char serverAddress[4]; - unsigned char remoteAddress[4]; - HANDLE trap_handle; - AsnObjectIdentifier first_supported_region; - std::vector connectionVector; - int last_field; - int index; - AsnInteger error_status; - AsnInteger error_index; - int conn_entry_type_index; - int conn_entry_type; - Bool found; - - /* - ** Statics. - */ - static char _conn_state[][32] = { - "?", - "CLOSED", - "LISTENING", - "SYN_SENT", - "SEN_RECEIVED", - "ESTABLISHED", - "FIN_WAIT", - "FIN_WAIT2", - "CLOSE_WAIT", - "LAST_ACK", - "CLOSING", - "TIME_WAIT", - "DELETE_TCB" - }; - - DEBUG_LOG(("Finding local address used to talk to the chat server\n")); - DEBUG_LOG(("Current chat server name is %s\n", serverName.str())); - DEBUG_LOG(("Chat server port is %d\n", serverPort)); - - /* - ** Get the address of the chat server. - */ - DEBUG_LOG( ("About to call gethostbyname\n")); - struct hostent *host_info = gethostbyname(serverName.str()); - - if (!host_info) { - DEBUG_LOG( ("gethostbyname failed! Error code %d\n", WSAGetLastError())); - return(false); - } - - memcpy(serverAddress, &host_info->h_addr_list[0][0], 4); - unsigned long temp = *((unsigned long*)(&serverAddress[0])); - temp = ntohl(temp); - *((unsigned long*)(&serverAddress[0])) = temp; - - DEBUG_LOG(("Host address is %d.%d.%d.%d\n", serverAddress[3], serverAddress[2], serverAddress[1], serverAddress[0])); - - /* - ** Load the MIB-II SNMP DLL. - */ - DEBUG_LOG(("About to load INETMIB1.DLL\n")); - - HINSTANCE mib_ii_dll = LoadLibrary("inetmib1.dll"); - if (mib_ii_dll == NULL) { - DEBUG_LOG(("Failed to load INETMIB1.DLL\n")); - return(false); - } - - DEBUG_LOG(("About to load SNMPAPI.DLL\n")); - - HINSTANCE snmpapi_dll = LoadLibrary("snmpapi.dll"); - if (snmpapi_dll == NULL) { - DEBUG_LOG(("Failed to load SNMPAPI.DLL\n")); - FreeLibrary(mib_ii_dll); - return(false); - } - - /* - ** Get the function pointers into the .dll - */ - SnmpExtensionInitPtr = (int (__stdcall *)(unsigned long,void ** ,AsnObjectIdentifier *)) GetProcAddress(mib_ii_dll, "SnmpExtensionInit"); - SnmpExtensionQueryPtr = (int (__stdcall *)(unsigned char,SnmpVarBindList *,long *,long *)) GetProcAddress(mib_ii_dll, "SnmpExtensionQuery"); - SnmpUtilMemAllocPtr = (void *(__stdcall *)(unsigned long)) GetProcAddress(snmpapi_dll, "SnmpUtilMemAlloc"); - SnmpUtilMemFreePtr = (void (__stdcall *)(void *)) GetProcAddress(snmpapi_dll, "SnmpUtilMemFree"); - if (SnmpExtensionInitPtr == NULL || SnmpExtensionQueryPtr == NULL || SnmpUtilMemAllocPtr == NULL || SnmpUtilMemFreePtr == NULL) { - DEBUG_LOG(("Failed to get proc addresses for linked functions\n")); - FreeLibrary(snmpapi_dll); - FreeLibrary(mib_ii_dll); - return(false); - } - - - RFC1157VarBindList *bind_list_ptr = (RFC1157VarBindList *) SnmpUtilMemAllocPtr(sizeof(RFC1157VarBindList)); - RFC1157VarBind *bind_ptr = (RFC1157VarBind *) SnmpUtilMemAllocPtr(sizeof(RFC1157VarBind)); - - /* - ** OK, here we go. Try to initialise the .dll - */ - DEBUG_LOG(("About to init INETMIB1.DLL\n")); - int ok = SnmpExtensionInitPtr(GetCurrentTime(), &trap_handle, &first_supported_region); - - if (!ok) { - /* - ** Aw crap. - */ - DEBUG_LOG(("Failed to init the .dll\n")); - SnmpUtilMemFreePtr(bind_list_ptr); - SnmpUtilMemFreePtr(bind_ptr); - FreeLibrary(snmpapi_dll); - FreeLibrary(mib_ii_dll); - return(false); - } - - /* - ** Name of mib_ii object we want to query. See RFC 1213. - ** - ** iso.org.dod.internet.mgmt.mib-2.tcp.tcpConnTable.TcpConnEntry.tcpConnState - ** 1 3 6 1 2 1 6 13 1 1 - */ - unsigned int mib_ii_name[] = {1,3,6,1,2,1,6,13,1,1}; - unsigned int *mib_ii_name_ptr = (unsigned int *) SnmpUtilMemAllocPtr(sizeof(mib_ii_name)); - memcpy(mib_ii_name_ptr, mib_ii_name, sizeof(mib_ii_name)); - - /* - ** Get the index of the conn entry data. - */ - conn_entry_type_index = ARRAY_SIZE(mib_ii_name) - 1; - - /* - ** Set up the bind list. - */ - bind_ptr->name.idLength = ARRAY_SIZE(mib_ii_name); - bind_ptr->name.ids = mib_ii_name; - bind_list_ptr->list = bind_ptr; - bind_list_ptr->len = 1; - - - /* - ** We start with the tcpConnLocalAddress field. - */ - last_field = 1; - - /* - ** First connection. - */ - index = 0; - - /* - ** Suck out that tcp connection info.... - */ - while (true) { - - if (!SnmpExtensionQueryPtr(SNMP_PDU_GETNEXT, bind_list_ptr, &error_status, &error_index)) { - //if (!SnmpExtensionQueryPtr(ASN_RFC1157_GETNEXTREQUEST, bind_list_ptr, &error_status, &error_index)) { - DEBUG_LOG(("SnmpExtensionQuery returned false\n")); - SnmpUtilMemFreePtr(bind_list_ptr); - SnmpUtilMemFreePtr(bind_ptr); - FreeLibrary(snmpapi_dll); - FreeLibrary(mib_ii_dll); - return(false); - } - - /* - ** If this is something new we aren't looking for then we are done. - */ - if (bind_ptr->name.idLength < ARRAY_SIZE(mib_ii_name)) { - break; - } - - /* - ** Get the type of info we are looking at. See RFC1213. - ** - ** 1 = tcpConnState - ** 2 = tcpConnLocalAddress - ** 3 = tcpConnLocalPort - ** 4 = tcpConnRemAddress - ** 5 = tcpConnRemPort - ** - ** tcpConnState is one of the following... - ** - ** 1 closed - ** 2 listen - ** 3 synSent - ** 4 synReceived - ** 5 established - ** 6 finWait1 - ** 7 finWait2 - ** 8 closeWait - ** 9 lastAck - ** 10 closing - ** 11 timeWait - ** 12 deleteTCB - */ - conn_entry_type = bind_ptr->name.ids[conn_entry_type_index]; - - if (last_field != conn_entry_type) { - index = 0; - last_field = conn_entry_type; - } - - switch (conn_entry_type) { - - /* - ** 1. First field in the entry. Need to create a new connection info struct - ** here to store this connection in. - */ - case tcpConnState: - { - ConnInfoStruct new_conn; - new_conn.State = bind_ptr->value.asnValue.number; - connectionVector.push_back(new_conn); - break; - } - - /* - ** 2. Local address field. - */ - case tcpConnLocalAddress: - DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index")); - connectionVector[index].LocalIP = *((unsigned long*)bind_ptr->value.asnValue.address.stream); - index++; - break; - - /* - ** 3. Local port field. - */ - case tcpConnLocalPort: - DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index")); - connectionVector[index].LocalPort = bind_ptr->value.asnValue.number; - //connectionVector[index]->LocalPort = ntohs(connectionVector[index]->LocalPort); - index++; - break; - - /* - ** 4. Remote address field. - */ - case tcpConnRemAddress: - DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index")); - connectionVector[index].RemoteIP = *((unsigned long*)bind_ptr->value.asnValue.address.stream); - index++; - break; - - /* - ** 5. Remote port field. - */ - case tcpConnRemPort: - DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index")); - connectionVector[index].RemotePort = bind_ptr->value.asnValue.number; - //connectionVector[index]->RemotePort = ntohs(connectionVector[index]->RemotePort); - index++; - break; - } - } - - SnmpUtilMemFreePtr(bind_list_ptr); - SnmpUtilMemFreePtr(bind_ptr); - SnmpUtilMemFreePtr(mib_ii_name_ptr); - - DEBUG_LOG(("Got %d connections in list, parsing...\n", connectionVector.size())); - - /* - ** Right, we got the lot. Lets see if any of them have the same address as the chat - ** server we think we are talking to. - */ - found = false; - for (Int i=0; igetSlot(i); - if (slot && slot->isOccupied()) - numUsers++; - } - - if (numUsers < 2) - { - if (TheGameSpyGame->amIHost()) - { - UnicodeString text; - text.format(TheGameText->fetch("LAN:NeedMorePlayers"),numUsers); - TheGameSpyInfo->addText(text, GSCOLOR_DEFAULT, NULL); - } - return; - } - - TheGameSpyGame->startGame(0); - } -} - -void GameSpyLaunchGame( void ) -{ - if (TheGameSpyGame) - { - - // Set up the game network - AsciiString user; - AsciiString userList; - DEBUG_ASSERTCRASH(TheNetwork == NULL, ("For some reason TheNetwork isn't NULL at the start of this game. Better look into that.")); - - if (TheNetwork != NULL) { - delete TheNetwork; - TheNetwork = NULL; - } - - // Time to initialize TheNetwork for this game. - TheNetwork = NetworkInterface::createNetwork(); - TheNetwork->init(); - /* - if (!TheGameSpyGame->amIHost()) - TheNetwork->setLocalAddress((207<<24) | (138<<16) | (47<<8) | 15, 8088); - else - */ - TheNetwork->setLocalAddress(TheGameSpyGame->getLocalIP(), TheNAT->getSlotPort(TheGameSpyGame->getLocalSlotNum())); - TheNetwork->attachTransport(TheNAT->getTransport()); - - user = TheGameSpyInfo->getLocalName(); - for (Int i=0; igetSlot(i); - if (!slot) - { - DEBUG_CRASH(("No GameSlot[%d]!", i)); - delete TheNetwork; - TheNetwork = NULL; - return; - } - -// UnsignedInt ip = htonl(slot->getIP()); - UnsignedInt ip = slot->getIP(); - AsciiString tmpUserName; - tmpUserName.translate(slot->getName()); - if (ip) - { - /* - if (i == 1) - { - user.format(",%s@207.138.47.15:8088", tmpUserName.str()); - } - else - */ - { - user.format(",%s@%d.%d.%d.%d:%d", tmpUserName.str(), - ((ip & 0xff000000) >> 24), - ((ip & 0xff0000) >> 16), - ((ip & 0xff00) >> 8), - ((ip & 0xff)), - TheNAT->getSlotPort(i) - ); - } - userList.concat(user); - } - } - userList.trim(); - - TheNetwork->parseUserList(TheGameSpyGame); - - // shutdown the top, but do not pop it off the stack -// TheShell->hideShell(); - // setup the Global Data with the Map and Seed - TheGlobalData->m_pendingFile = TheGameSpyGame->getMap(); - - if (TheGameLogic->isInGame()) { - TheGameLogic->clearGameData(); - } - // send a message to the logic for a new game - GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_NEW_GAME ); - msg->appendIntegerArgument(GAME_INTERNET); - - TheGlobalData->m_useFpsLimit = false; - - // Set the random seed - InitGameLogicRandom( TheGameSpyGame->getSeed() ); - DEBUG_LOG(("InitGameLogicRandom( %d )\n", TheGameSpyGame->getSeed())); - - if (TheNAT != NULL) { - delete TheNAT; - TheNAT = NULL; - } - } -} - -void GameSpyGameInfo::init( void ) -{ - GameInfo::init(); - - m_hasBeenQueried = false; -} - -void GameSpyGameInfo::resetAccepted( void ) -{ - GameInfo::resetAccepted(); - - if (m_hasBeenQueried && amIHost()) - { - // ANCIENTMUNKEE peerStateChanged(TheGameSpyChat->getPeer()); - m_hasBeenQueried = false; - DEBUG_LOG(("resetAccepted() called peerStateChange()\n")); - } -} - -Int GameSpyGameInfo::getLocalSlotNum( void ) const -{ - DEBUG_ASSERTCRASH(m_inGame, ("Looking for local game slot while not in game")); - if (!m_inGame) - return -1; - - AsciiString localName = TheGameSpyInfo->getLocalName(); - - for (Int i=0; iisPlayer(localName)) - return i; - } - return -1; -} - -void GameSpyGameInfo::gotGOACall( void ) -{ - DEBUG_LOG(("gotGOACall()\n")); - m_hasBeenQueried = true; -} - -void GameSpyGameInfo::startGame(Int gameID) -{ - DEBUG_LOG(("GameSpyGameInfo::startGame - game id = %d\n", gameID)); - DEBUG_ASSERTCRASH(m_transport == NULL, ("m_transport is not NULL when it should be")); - DEBUG_ASSERTCRASH(TheNAT == NULL, ("TheNAT is not NULL when it should be")); - - // fill in GS-specific info - for (Int i=0; igetPlayerInfoMap(); - PlayerInfoMap::iterator it = pInfoMap->find(gsName); - if (it != pInfoMap->end()) - { - m_GameSpySlot[i].setProfileID(it->second.m_profileID); - m_GameSpySlot[i].setLocale(it->second.m_locale); - } - else - { - DEBUG_CRASH(("No player info for %s", gsName.str())); - } - } - } - - if (TheNAT != NULL) { - delete TheNAT; - TheNAT = NULL; - } - TheNAT = NEW NAT(); - TheNAT->attachSlotList(m_slot, getLocalSlotNum(), m_localIP); - TheNAT->establishConnectionPaths(); -} - -AsciiString GameSpyGameInfo::generateGameResultsPacket( void ) -{ - Int i; - Int endFrame = TheVictoryConditions->getEndFrame(); - Int localSlotNum = getLocalSlotNum(); - //GameSlot *localSlot = getSlot(localSlotNum); - Bool sawGameEnd = (endFrame > 0);// && localSlot->lastFrameInGame() <= endFrame); - Int winningTeam = -1; - Int numPlayers = 0; - Int numTeamsAtGameEnd = 0; - Int lastTeamAtGameEnd = -1; - for (i=0; ifindPlayerWithNameKey(NAMEKEY(playerName)); - if (p) - { - ++numPlayers; - if (TheVictoryConditions->hasAchievedVictory(p)) - { - winningTeam = getSlot(i)->getTeamNumber(); - } - - // check if he lasted - GameSlot *slot = getSlot(i); - if (!slot->disconnected()) - { - if (slot->getTeamNumber() != lastTeamAtGameEnd || numTeamsAtGameEnd == 0) - { - lastTeamAtGameEnd = slot->getTeamNumber(); - ++numTeamsAtGameEnd; - } - } - } - } - - AsciiString results; - results.format("seed=%d,slotNum=%d,sawDesync=%d,sawGameEnd=%d,winningTeam=%d,disconEnd=%d,duration=%d,numPlayers=%d,isQM=%d", - getSeed(), localSlotNum, TheNetwork->sawCRCMismatch(), sawGameEnd, winningTeam, (numTeamsAtGameEnd != 0), - endFrame, numPlayers, m_isQM); - - Int playerID = 0; - for (i=0; ifindPlayerWithNameKey(NAMEKEY(playerName)); - if (p) - { - GameSpyGameSlot *slot = &(m_GameSpySlot[i]); - ScoreKeeper *keeper = p->getScoreKeeper(); - AsciiString playerName = slot->getLoginName(); - Int gsPlayerID = slot->getProfileID(); - AsciiString locale = slot->getLocale(); - Int fps = TheNetwork->getAverageFPS(); - Int unitsKilled = keeper->getTotalUnitsDestroyed(); - Int unitsLost = keeper->getTotalUnitsLost(); - Int unitsBuilt = keeper->getTotalUnitsBuilt(); - Int buildingsKilled = keeper->getTotalBuildingsDestroyed(); - Int buildingsLost = keeper->getTotalBuildingsLost(); - Int buildingsBuilt = keeper->getTotalBuildingsBuilt(); - Int earnings = keeper->getTotalMoneyEarned(); - Int techCaptured = keeper->getTotalTechBuildingsCaptured(); - Bool disconnected = slot->disconnected(); - - AsciiString playerStr; - playerStr.format(",player%d=%s,playerID%d=%d,locale%d=%s", - playerID, playerName.str(), playerID, gsPlayerID, playerID, locale.str()); - results.concat(playerStr); - playerStr.format(",unitsKilled%d=%d,unitsLost%d=%d,unitsBuilt%d=%d", - playerID, unitsKilled, playerID, unitsLost, playerID, unitsBuilt); - results.concat(playerStr); - playerStr.format(",buildingsKilled%d=%d,buildingsLost%d=%d,buildingsBuilt%d=%d", - playerID, buildingsKilled, playerID, buildingsLost, playerID, buildingsBuilt); - results.concat(playerStr); - playerStr.format(",fps%d=%d,cash%d=%d,capturedTech%d=%d,discon%d=%d", - playerID, fps, playerID, earnings, playerID, techCaptured, playerID, disconnected); - results.concat(playerStr); - - ++playerID; - } - } - - // Add a trailing size value (so the server can ensure it got the entire packet) - int resultsLen = results.getLength()+10; - AsciiString tail; - tail.format("%10.10d", resultsLen); - results.concat(tail); - - return results; -} - diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpyOverlay.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpyOverlay.cpp deleted file mode 100644 index 22476a807ba..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpyOverlay.cpp +++ /dev/null @@ -1,333 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: wolscreens.cpp ////////////////////////////////////////////////////// -// Westwood Online screen setup/teardown -// Author: Matthew D. Campbell, November 2001 - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine -#include "Common/AudioEventRTS.h" - -#include "GameClient/GadgetListBox.h" -#include "GameClient/GameText.h" -#include "GameClient/MessageBox.h" -#include "GameClient/ShellHooks.h" -//#include "GameNetwork/GameSpy.h" -//#include "GameNetwork/GameSpyGP.h" - -#include "GameNetwork/GameSpyOverlay.h" -//#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/BuddyThread.h" - -void deleteNotificationBox( void ); -static void raiseOverlays( void ); - -// Message boxes ------------------------------------- -static GameWindow *messageBoxWindow = NULL; -static GameWinMsgBoxFunc okFunc = NULL; -static GameWinMsgBoxFunc cancelFunc = NULL; -static Bool reOpenPlayerInfoFlag = FALSE; -/** - * messageBoxOK is called when a message box is destroyed - * by way of an OK button, so we can clear our pointers to it. - */ -static void messageBoxOK( void ) -{ - DEBUG_ASSERTCRASH(messageBoxWindow, ("Message box window went away without being there in the first place!")); - messageBoxWindow = NULL; - if (okFunc) - { - okFunc(); - okFunc = NULL; - } -} - -/** - * messageBoxCancel is called when a message box is destroyed - * by way of a Cancel button, so we can clear our pointers to it. - */ -static void messageBoxCancel( void ) -{ - DEBUG_ASSERTCRASH(messageBoxWindow, ("Message box window went away without being there in the first place!")); - messageBoxWindow = NULL; - if (cancelFunc) - { - cancelFunc(); - cancelFunc = NULL; - } -} - -/** - * clearGSMessageBoxes removes the current message box if - * one is present. This is usually done when putting up a - * second messageBox. - */ -void ClearGSMessageBoxes( void ) -{ - if (messageBoxWindow) - { - TheWindowManager->winDestroy(messageBoxWindow); - messageBoxWindow = NULL; - } - - if (okFunc) - { - okFunc = NULL; - } - - if (cancelFunc) - { - cancelFunc = NULL; - } -} - -/** - * GSMessageBoxOk puts up an OK dialog box and saves the - * pointers to it and its callbacks. - */ -void GSMessageBoxOk(UnicodeString title, UnicodeString message, GameWinMsgBoxFunc newOkFunc) -{ - ClearGSMessageBoxes(); - messageBoxWindow = MessageBoxOk(title, message, messageBoxOK); - okFunc = newOkFunc; -} - -/** - * GSMessageBoxOkCancel puts up an OK/Cancel dialog box and saves the - * pointers to it and its callbacks. - */ -void GSMessageBoxOkCancel(UnicodeString title, UnicodeString message, GameWinMsgBoxFunc newOkFunc, GameWinMsgBoxFunc newCancelFunc) -{ - ClearGSMessageBoxes(); - messageBoxWindow = MessageBoxOkCancel(title, message, messageBoxOK, messageBoxCancel); - okFunc = newOkFunc; - cancelFunc = newCancelFunc; -} - -/** - * GSMessageBoxYesNo puts up a Yes/No dialog box and saves the - * pointers to it and its callbacks. - */ -void GSMessageBoxYesNo(UnicodeString title, UnicodeString message, GameWinMsgBoxFunc newYesFunc, GameWinMsgBoxFunc newNoFunc) -{ - ClearGSMessageBoxes(); - messageBoxWindow = MessageBoxYesNo(title, message, messageBoxOK, messageBoxCancel); - okFunc = newYesFunc; - cancelFunc = newNoFunc; -} - -/** - * If the screen transitions underneath the dialog box, we - * need to raise it to keep it visible. - */ -void RaiseGSMessageBox( void ) -{ - raiseOverlays(); - - if (!messageBoxWindow) - return; - - messageBoxWindow->winBringToTop(); -} - -// Overlay screens ------------------------------------- - -/** - * gsOverlays holds a list of the .wnd files used in GS overlays. - * The entries *MUST* be in the same order as the GSOverlayType enum. - */ -static const char * gsOverlays[GSOVERLAY_MAX] = -{ - "Menus/PopupPlayerInfo.wnd", // Player info (right-click) - "Menus/WOLMapSelectMenu.wnd", // Map select - "Menus/WOLBuddyOverlay.wnd", // Buddy list - "Menus/WOLPageOverlay.wnd", // Find/page - "Menus/PopupHostGame.wnd", // Hosting options (game name, password, etc) - "Menus/PopupJoinGame.wnd", // Joining options (password, etc) - "Menus/PopupLadderSelect.wnd",// LadderSelect - "Menus/PopupLocaleSelect.wnd",// Prompt for user's locale - "Menus/OptionsMenu.wnd", // popup options -}; - -static WindowLayout *overlayLayouts[GSOVERLAY_MAX] = -{ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, -}; - -static void buddyTryReconnect( void ) -{ - BuddyRequest req; - req.buddyRequestType = BuddyRequest::BUDDYREQUEST_RELOGIN; - TheGameSpyBuddyMessageQueue->addRequest( req ); -} - -void GameSpyOpenOverlay( GSOverlayType overlay ) -{ - if (overlay == GSOVERLAY_BUDDY) - { - if (!TheGameSpyBuddyMessageQueue->isConnected()) - { - // not connected - is it because we were disconnected? - if (TheGameSpyBuddyMessageQueue->getLocalProfileID()) - { - // used to be connected - GSMessageBoxYesNo(TheGameText->fetch("GUI:GPErrorTitle"), TheGameText->fetch("GUI:GPDisconnected"), buddyTryReconnect, NULL); - } - else - { - // no profile - GSMessageBoxOk(TheGameText->fetch("GUI:GPErrorTitle"), TheGameText->fetch("GUI:GPNoProfile"), NULL); - } - return; - } - AudioEventRTS buttonClick("GUICommunicatorOpen"); - - if( TheAudio ) - { - TheAudio->addAudioEvent( &buttonClick ); - } // end if - } - if (overlayLayouts[overlay]) - { - overlayLayouts[overlay]->hide( FALSE ); - overlayLayouts[overlay]->bringForward(); - } - else - { - overlayLayouts[overlay] = TheWindowManager->winCreateLayout( AsciiString( gsOverlays[overlay] ) ); - overlayLayouts[overlay]->runInit(); - overlayLayouts[overlay]->hide( FALSE ); - overlayLayouts[overlay]->bringForward(); - } -} - -void GameSpyCloseOverlay( GSOverlayType overlay ) -{ - switch(overlay) - { - case GSOVERLAY_PLAYERINFO: - DEBUG_LOG(("Closing overlay GSOVERLAY_PLAYERINFO\n")); - break; - case GSOVERLAY_MAPSELECT: - DEBUG_LOG(("Closing overlay GSOVERLAY_MAPSELECT\n")); - break; - case GSOVERLAY_BUDDY: - DEBUG_LOG(("Closing overlay GSOVERLAY_BUDDY\n")); - break; - case GSOVERLAY_PAGE: - DEBUG_LOG(("Closing overlay GSOVERLAY_PAGE\n")); - break; - case GSOVERLAY_GAMEOPTIONS: - DEBUG_LOG(("Closing overlay GSOVERLAY_GAMEOPTIONS\n")); - break; - case GSOVERLAY_GAMEPASSWORD: - DEBUG_LOG(("Closing overlay GSOVERLAY_GAMEPASSWORD\n")); - break; - case GSOVERLAY_LADDERSELECT: - DEBUG_LOG(("Closing overlay GSOVERLAY_LADDERSELECT\n")); - break; - case GSOVERLAY_OPTIONS: - DEBUG_LOG(("Closing overlay GSOVERLAY_OPTIONS\n")); - if( overlayLayouts[overlay] ) - { - SignalUIInteraction(SHELL_SCRIPT_HOOK_OPTIONS_CLOSED); - } - break; - } - if( overlayLayouts[overlay] ) - { - overlayLayouts[overlay]->runShutdown(); - overlayLayouts[overlay]->destroyWindows(); - overlayLayouts[overlay]->deleteInstance(); - overlayLayouts[overlay] = NULL; - } -} - -Bool GameSpyIsOverlayOpen( GSOverlayType overlay ) -{ - return (overlayLayouts[overlay] != NULL); -} - -void GameSpyToggleOverlay( GSOverlayType overlay ) -{ - if (GameSpyIsOverlayOpen(overlay)) - GameSpyCloseOverlay(overlay); - else - GameSpyOpenOverlay(overlay); -} - -void raiseOverlays( void ) -{ - for (int i=0; ibringForward(); - } - } -} - -void GameSpyCloseAllOverlays( void ) -{ - for (int i=0; irunUpdate(); - } - } -} - -void ReOpenPlayerInfo( void ) -{ - reOpenPlayerInfoFlag = TRUE; -} -void CheckReOpenPlayerInfo(void ) -{ - if(!reOpenPlayerInfoFlag) - return; - - GameSpyOpenOverlay(GSOVERLAY_PLAYERINFO); - reOpenPlayerInfoFlag = FALSE; - -} diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/NAT.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/NAT.cpp deleted file mode 100644 index 49b57c8c1b5..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/NAT.cpp +++ /dev/null @@ -1,1325 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: NAT.cpp ///////////////////////////////////////////////////////////////////////////////// -// Author: Bryan Cleveland April 2002 -// Props to Steve Tall for figuring all the NAT and Firewall behavior patterns out, making my job -// a LOT easier. -// Desc: Resolves NAT'd IPs and port numbers for the other players in a game. -/////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -#include "GameNetwork/NAT.h" -#include "GameNetwork/Transport.h" -#include "GameNetwork/NetworkDefs.h" -#include "GameClient/EstablishConnectionsMenu.h" -#include "GameNetwork/NetworkInterface.h" -#include "GameNetwork/GameInfo.h" -#include "GameNetwork/GameSpy/PeerThread.h" -#include "GameNetwork/GameSpy/PeerDefs.h" -#include "GameNetwork/GameSpy/PersistentStorageThread.h" -#include "GameNetwork/GameSpy/GSConfig.h" - -#ifdef _INTERNAL -// for occasional debugging... -//#pragma optimize("", off) -//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") -#endif - -/* - * In case you're wondering, we do this weird connection pairing scheme - * to speed up the negotiation process, especially in cases where there - * are 4 or more players (nodes). Take for example an 8 player game... - * In an 8 player game there are 28 connections that need to be negotiated, - * doing this pairing scheme thing, we can make those 28 connections in the - * time it would normally take to make 7 connections. Since each connection - * could potentially take several seconds, this can be a HUGE time savings. - - * Right now you're probably wondering who this Bryan Cleveland guy is. - * He's the network coder that got fired when this didn't work. - - * In case you're wondering, this did end up working and Bryan left by - * his own choice. - */ -// m_connectionPairs[num nodes] [round] [node index] -/* static */ Int NAT::m_connectionPairs[MAX_SLOTS-1][MAX_SLOTS-1][MAX_SLOTS] = -{ - { // 2 nodes - // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7 - { 1, 0, -1, -1, -1, -1, -1, -1}, // round 0 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 1 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 2 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 3 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 4 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 5 - { -1, -1, -1, -1, -1, -1, -1, -1} // round 6 - }, - { // 3 nodes - // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7 - { 1, 0, -1, -1, -1, -1, -1, -1}, // round 0 - { 2, -1, 0, -1, -1, -1, -1, -1}, // round 1 - { -1, 2, 1, -1, -1, -1, -1, -1}, // round 2 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 3 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 4 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 5 - { -1, -1, -1, -1, -1, -1, -1, -1} // round 6 - }, - { // 4 nodes - // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7 - { 1, 0, 3, 2, -1, -1, -1, -1}, // round 0 - { 2, 3, 0, 1, -1, -1, -1, -1}, // round 1 - { 3, 2, 1, 0, -1, -1, -1, -1}, // round 2 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 3 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 4 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 5 - { -1, -1, -1, -1, -1, -1, -1, -1} // round 6 - }, - { // 5 nodes - // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7 - { 2, 4, 0, -1, 1, -1, -1, -1}, // round 0 - { -1, 3, 4, 1, 2, -1, -1, -1}, // round 1 - { 3, 2, 1, 0, -1, -1, -1, -1}, // round 2 - { 4, -1, 3, 2, 0, -1, -1, -1}, // round 3 - { 1, 0, -1, 4, 3, -1, -1, -1}, // round 4 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 5 - { -1, -1, -1, -1, -1, -1, -1, -1} // round 6 - }, - { // 6 nodes - // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7 - { 3, 5, 4, 0, 2, 1, -1, -1}, // round 0 - { 2, 4, 0, 5, 1, 3, -1, -1}, // round 1 - { 4, 3, 5, 1, 0, 2, -1, -1}, // round 2 - { 1, 0, 3, 2, 5, 4, -1, -1}, // round 3 - { 5, 2, 1, 4, 3, 0, -1, -1}, // round 4 - { -1, -1, -1, -1, -1, -1, -1, -1}, // round 5 - { -1, -1, -1, -1, -1, -1, -1, -1} // round 6 - }, - { // 7 nodes - // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7 - { -1, 6, 5, 4, 3, 2, 1, -1}, // round 0 - { 2, -1, 0, 6, 5, 4, 3, -1}, // round 1 - { 4, 3, -1, 1, 0, 6, 5, -1}, // round 2 - { 6, 5, 4, -1, 2, 1, 0, -1}, // round 3 - { 1, 0, 6, 5, -1, 3, 2, -1}, // round 4 - { 3, 2, 1, 0, 6, -1, 4, -1}, // round 5 - { 5, 4, 3, 2, 1, 0, -1, -1} // round 6 - }, - { // 8 nodes - // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7 - { 4, 5, 6, 7, 0, 1, 2, 3}, // round 0 - { 5, 4, 7, 6, 1, 0, 3, 2}, // round 1 - { 3, 6, 5, 0, 7, 2, 1, 4}, // round 2 - { 2, 7, 0, 5, 6, 3, 4, 1}, // round 3 - { 6, 3, 4, 1, 2, 7, 0, 5}, // round 4 - { 1, 0, 3, 2, 5, 4, 7, 6}, // round 5 - { 7, 2, 1, 4, 3, 6, 5, 0} // round 6 - } -}; - -/* static */ Int NAT::m_timeBetweenRetries = 500; // .5 seconds between retries sounds good to me. -/* static */ time_t NAT::m_manglerRetryTimeInterval = 300; // sounds good to me. -/* static */ Int NAT::m_maxAllowedManglerRetries = 25; // works for me. -/* static */ time_t NAT::m_keepaliveInterval = 15000; // 15 seconds between keepalive packets seems good. -/* static */ time_t NAT::m_timeToWaitForPort = 15000; // wait for 15 seconds for the other player's port number. -/* static */ time_t NAT::m_timeForRoundTimeout = 15000; // wait for at most 15 seconds for each connection round to finish. - -NAT *TheNAT = NULL; - -NAT::NAT() -{ - //Added By Sadullah Nader - //Initializations inserted - m_beenProbed = FALSE; - m_connectionPairIndex = 0; - m_connectionRound = 0; - m_localIP = 0; - m_localNodeNumber = 0; - m_manglerAddress = 0; - m_manglerRetries = 0; - m_numNodes = 0; - m_numRetries = 0; - m_previousSourcePort = 0; - for(Int i = 0; i < MAX_SLOTS; i++) - m_sourcePorts[i] = 0; - m_spareSocketPort = 0; - m_startingPortNumber = 0; - m_targetNodeNumber = 0; - // - m_transport = NULL; - m_slotList = NULL; - m_roundTimeout = 0; - - m_maxNumRetriesAllowed = 10; - m_packetID = 0x7f00; -} - -NAT::~NAT() { -} - -// if we're already finished, change to being idle -// if we are negotiating now, check to see if this round is done -// if it is, check to see if we're completely done with all rounds. -// if we are, set state to be done. -// if not go on to the next connection round. -// if we are negotiating still, call the connection update -// check to see if this connection is done for us, or if it has failed. -enum { MS_TO_WAIT_FOR_STATS = 5000 }; -NATStateType NAT::update() { - static UnsignedInt s_startStatWaitTime = 0; - if (m_NATState == NATSTATE_DONE) { - m_NATState = NATSTATE_IDLE; - } else if (m_NATState == NATSTATE_WAITFORSTATS) { - // check for all stats - Bool gotAllStats = TRUE; - Bool timedOut = FALSE; - for (Int i=0; igetGameSpySlot(i); - if (slot && slot->isHuman()) - { - PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(slot->getProfileID()); - if (stats.id == 0) - { - gotAllStats = FALSE; - //DEBUG_LOG(("Failed to find stats for %ls(%d)\n", slot->getName().str(), slot->getProfileID())); - } - } - } - // check for timeout. Timing out is not a fatal error - it just means we didn't get the other - // player's stats. We'll see 0/0 as his record, but we can still play him just fine. - UnsignedInt now = timeGetTime(); - if (now > s_startStatWaitTime + MS_TO_WAIT_FOR_STATS) - { - DEBUG_LOG(("Timed out waiting for stats. Let's just start the dang game.\n")); - timedOut = TRUE; - } - if (gotAllStats || timedOut) - { - m_NATState = NATSTATE_DONE; - TheEstablishConnectionsMenu->endMenu(); - if (TheFirewallHelper != NULL) { - delete TheFirewallHelper; - TheFirewallHelper = NULL; - } - } - } else if (m_NATState == NATSTATE_DOCONNECTIONPATHS) { - if (allConnectionsDoneThisRound() == TRUE) { - // we finished this round, move on to the next one. - ++m_connectionRound; -// m_roundTimeout = timeGetTime() + TheGameSpyConfig->getRoundTimeout(); - m_roundTimeout = timeGetTime() + m_timeForRoundTimeout; - DEBUG_LOG(("NAT::update - done with connection round, moving on to round %d\n", m_connectionRound)); - - // we finished that round, now check to see if we're done, or if there are more rounds to go. - if (allConnectionsDone() == TRUE) { - // we're all done, time to go back home. - m_NATState = NATSTATE_WAITFORSTATS; - - // 2/19/03 BGC - we have successfully negotaited a NAT thingy, so our behavior must be correct - // so therefore we don't need to refresh our NAT even if we previously thought we had to. - TheFirewallHelper->flagNeedToRefresh(FALSE); - - s_startStatWaitTime = timeGetTime(); - DEBUG_LOG(("NAT::update - done with all connections, woohoo!!\n")); - /* - m_NATState = NATSTATE_DONE; - TheEstablishConnectionsMenu->endMenu(); - if (TheFirewallHelper != NULL) { - delete TheFirewallHelper; - TheFirewallHelper = NULL; - } - */ - } else { - doThisConnectionRound(); - } - } - NATConnectionState state = connectionUpdate(); - - if (timeGetTime() > m_roundTimeout) { - DEBUG_LOG(("NAT::update - round timeout expired\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - notifyUsersOfConnectionFailed(m_localNodeNumber); - } - - if (state == NATCONNECTIONSTATE_FAILED) { - // if we fail - m_NATState = NATSTATE_FAILED; - TheEstablishConnectionsMenu->endMenu(); - if (TheFirewallHelper != NULL) { - // we failed NAT negotiation, perhaps we need to redetect our firewall settings. - // We don't trust the user to do it for themselves so we force them to do it next time - // the log in. - // 2/19/03 - ok, we don't want to do this right away, if the user tries to play in another game - // before they log out and log back in the game won't have a chance at working. - // so we need to simply flag it so that when they log out the firewall behavior gets blown away. - TheFirewallHelper->flagNeedToRefresh(TRUE); -// TheWritableGlobalData->m_firewallBehavior = FirewallHelperClass::FIREWALL_TYPE_UNKNOWN; -// TheFirewallHelper->writeFirewallBehavior(); - - delete TheFirewallHelper; - TheFirewallHelper = NULL; - } - // we failed to connect, so we don't have to pass on the transport to the network. - if (m_transport != NULL) { - delete m_transport; - m_transport = NULL; - } - } - } - return m_NATState; -} - - -// update transport, check for PROBE packets from our target. -// check to see if its time to PROBE our target -// MANGLER: -// if we are talking to the mangler, check to see if we got a response -// if we didn't get a response, check to see if its time to send another packet to it -NATConnectionState NAT::connectionUpdate() { - - GameSlot *targetSlot = NULL; - if (m_targetNodeNumber >= 0) { - targetSlot = m_slotList[m_connectionNodes[m_targetNodeNumber].m_slotIndex]; - } else { - return m_connectionStates[m_localNodeNumber]; - } - - if (m_beenProbed == FALSE) { - if (timeGetTime() >= m_nextPortSendTime) { -// sendMangledPortNumberToTarget(m_previousSourcePort, targetSlot); - sendMangledPortNumberToTarget(m_sourcePorts[m_targetNodeNumber], targetSlot); -// m_nextPortSendTime = timeGetTime() + TheGameSpyConfig->getRetryInterval(); - m_nextPortSendTime = timeGetTime() + m_timeBetweenRetries; - } - } - - // check to see if its time to send out our keepalives. - if (timeGetTime() >= m_nextKeepaliveTime) { - for (Int node = 0; node < m_numNodes; ++node) { - if (m_myConnections[node] == TRUE) { - // we've made this connection, send a keepalive. - Int slotIndex = m_connectionNodes[node].m_slotIndex; - GameSlot *slot = m_slotList[slotIndex]; - DEBUG_ASSERTCRASH(slot != NULL, ("Trying to send keepalive to a NULL slot")); - if (slot != NULL) { - UnsignedInt ip = slot->getIP(); - DEBUG_LOG(("NAT::connectionUpdate - sending keep alive to node %d at %d.%d.%d.%d:%d\n", node, - ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff, slot->getPort())); - m_transport->queueSend(ip, slot->getPort(), (const unsigned char *)"KEEPALIVE", strlen("KEEPALIVE") + 1); - } - } - } -// m_nextKeepaliveTime = timeGetTime() + TheGameSpyConfig->getKeepaliveInterval(); - m_nextKeepaliveTime = timeGetTime() + m_keepaliveInterval; - } - - m_transport->update(); - - // check to see if we've been probed. - for (Int i = 0; i < MAX_MESSAGES; ++i) { - if (m_transport->m_inBuffer[i].length > 0) { -#ifdef DEBUG_LOGGING - UnsignedInt ip = m_transport->m_inBuffer[i].addr; -#endif - DEBUG_LOG(("NAT::connectionUpdate - got a packet from %d.%d.%d.%d:%d, length = %d\n", - ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff, m_transport->m_inBuffer[i].port, m_transport->m_inBuffer[i].length)); - UnsignedByte *data = m_transport->m_inBuffer[i].data; - if (memcmp(data, "PROBE", strlen("PROBE")) == 0) { - Int fromNode = atoi((char *)data + strlen("PROBE")); - DEBUG_LOG(("NAT::connectionUpdate - we've been probed by node %d.\n", fromNode)); - - if (fromNode == m_targetNodeNumber) { - DEBUG_LOG(("NAT::connectionUpdate - probe was sent by our target, setting connection state %d to done.\n", m_targetNodeNumber)); - setConnectionState(m_targetNodeNumber, NATCONNECTIONSTATE_DONE); - - if (m_transport->m_inBuffer[i].addr != targetSlot->getIP()) { - UnsignedInt fromIP = m_transport->m_inBuffer[i].addr; -#ifdef DEBUG_LOGGING - UnsignedInt slotIP = targetSlot->getIP(); -#endif - DEBUG_LOG(("NAT::connectionUpdate - incomming packet has different from address than we expected, incoming: %d.%d.%d.%d expected: %d.%d.%d.%d\n", - fromIP >> 24, (fromIP >> 16) & 0xff, (fromIP >> 8) & 0xff, fromIP & 0xff, - slotIP >> 24, (slotIP >> 16) & 0xff, (slotIP >> 8) & 0xff, slotIP & 0xff)); - targetSlot->setIP(fromIP); - } - if (m_transport->m_inBuffer[i].port != targetSlot->getPort()) { - DEBUG_LOG(("NAT::connectionUpdate - incoming packet came from a different port than we expected, incoming: %d expected: %d\n", - m_transport->m_inBuffer[i].port, targetSlot->getPort())); - targetSlot->setPort(m_transport->m_inBuffer[i].port); - m_sourcePorts[m_targetNodeNumber] = m_transport->m_inBuffer[i].port; - } - notifyUsersOfConnectionDone(m_targetNodeNumber); - } - - m_transport->m_inBuffer[i].length = 0; - } - if (memcmp(data, "KEEPALIVE", strlen("KEEPALIVE")) == 0) { - // keep alive packet, just toss it. - DEBUG_LOG(("NAT::connectionUpdate - got keepalive from %d.%d.%d.%d:%d\n", - ip >> 24, (ip >> 16) & 0xff, (ip >> 8) && 0xff, ip & 0xff, m_transport->m_inBuffer[i].port)); - m_transport->m_inBuffer[i].length = 0; - } - } - } - - // we are waiting for our target to tell us that they have received our probe. - if (m_connectionStates[m_localNodeNumber] == NATCONNECTIONSTATE_WAITINGFORRESPONSE) { - // check to see if it's time to probe our target. - if ((m_timeTillNextSend != -1) && (m_timeTillNextSend <= timeGetTime())) { - if (m_numRetries > m_maxNumRetriesAllowed) { - DEBUG_LOG(("NAT::connectionUpdate - too many retries, connection failed.\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - - notifyUsersOfConnectionFailed(m_localNodeNumber); - } else { - DEBUG_LOG(("NAT::connectionUpdate - trying to send another probe (#%d) to our target\n", m_numRetries+1)); - // Send a probe. - sendAProbe(targetSlot->getIP(), targetSlot->getPort(), m_localNodeNumber); -// m_timeTillNextSend = timeGetTime() + TheGameSpyConfig->getRetryInterval(); - m_timeTillNextSend = timeGetTime() + m_timeBetweenRetries; - - // tell the target they've been probed. In other words, our port is open. - notifyTargetOfProbe(targetSlot); - - ++m_numRetries; - } - } - } - - // we are waiting for a response from the mangler to tell us what port we're using. - if (m_connectionStates[m_localNodeNumber] == NATCONNECTIONSTATE_WAITINGFORMANGLERRESPONSE) { - UnsignedShort mangledPort = 0; - if (TheFirewallHelper != NULL) { - mangledPort = TheFirewallHelper->getManglerResponse(m_packetID); - } - if (mangledPort != 0) { - // we got a response. now we need to start probing (unless of course we have a netgear) - processManglerResponse(mangledPort); - - // we know there is a firewall helper if we got here. - TheFirewallHelper->closeSpareSocket(m_spareSocketPort); - m_spareSocketPort = 0; - } else { - if (timeGetTime() >= m_manglerRetryTime) { - ++m_manglerRetries; -// if (m_manglerRetries > TheGameSpyConfig->getMaxManglerRetries()) { - if (m_manglerRetries > m_maxAllowedManglerRetries) { - // we couldn't communicate with the mangler, just use our non-mangled - // port number and hope that works. - DEBUG_LOG(("NAT::connectionUpdate - couldn't talk with the mangler using default port number\n")); - sendMangledPortNumberToTarget(getSlotPort(m_connectionNodes[m_localNodeNumber].m_slotIndex), targetSlot); - m_sourcePorts[m_targetNodeNumber] = getSlotPort(m_connectionNodes[m_localNodeNumber].m_slotIndex); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORRESPONSE); - } else { - if (TheFirewallHelper != NULL) { - DEBUG_LOG(("NAT::connectionUpdate - trying to send to the mangler again. mangler address: %d.%d.%d.%d, from port: %d, packet ID:%d\n", - m_manglerAddress >> 24, (m_manglerAddress >> 16) & 0xff, (m_manglerAddress >> 8) & 0xff, m_manglerAddress & 0xff, m_spareSocketPort, m_packetID)); - TheFirewallHelper->sendToManglerFromPort(m_manglerAddress, m_spareSocketPort, m_packetID); - } -// m_manglerRetryTime = TheGameSpyConfig->getRetryInterval() + timeGetTime(); - m_manglerRetryTime = m_manglerRetryTimeInterval + timeGetTime(); - } - } - } - } - - if (m_connectionStates[m_localNodeNumber] == NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT) { - if (timeGetTime() > m_timeoutTime) { - DEBUG_LOG(("NAT::connectionUpdate - waiting too long to get the other player's port number, failed.\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - - notifyUsersOfConnectionFailed(m_localNodeNumber); - } - } - - return m_connectionStates[m_localNodeNumber]; -} - -// this is the function that starts the NAT/firewall negotiation process. -// after calling this, you should call the update function untill it returns -// NATSTATE_DONE. -void NAT::establishConnectionPaths() { - DEBUG_LOG(("NAT::establishConnectionPaths - entering\n")); - m_NATState = NATSTATE_DOCONNECTIONPATHS; - DEBUG_LOG(("NAT::establishConnectionPaths - using %d as our starting port number\n", m_startingPortNumber)); - if (TheEstablishConnectionsMenu == NULL) { - TheEstablishConnectionsMenu = NEW EstablishConnectionsMenu; - } - TheEstablishConnectionsMenu->initMenu(); - - if (TheFirewallHelper == NULL) { - TheFirewallHelper = createFirewallHelper(); - } - - DEBUG_ASSERTCRASH(m_slotList != NULL, ("NAT::establishConnectionPaths - don't have a slot list")); - if (m_slotList == NULL) { - return; - } - - // determine how many nodes we have. - m_numNodes = 0; - for (Int i = 0; i < MAX_SLOTS; ++i) { - if (m_slotList[i] != NULL) { - if (m_slotList[i]->isHuman()) { - DEBUG_LOG(("NAT::establishConnectionPaths - slot %d is %ls\n", i, m_slotList[i]->getName().str())); - ++m_numNodes; - } - } - } - DEBUG_LOG(("NAT::establishConnectionPaths - number of nodes: %d\n", m_numNodes)); - - if (m_numNodes < 2) - { - // just start the game - there isn't anybody to which to connect. :P - m_NATState = NATSTATE_DONE; - return; - } - - m_connectionRound = 0; - m_connectionPairIndex = m_numNodes - 2; - Bool connectionAssigned[MAX_SLOTS]; - - for (i = 0; i < MAX_SLOTS; ++i) { - m_connectionNodes[i].m_slotIndex = -1; - connectionAssigned[i] = FALSE; - m_sourcePorts[i] = 0; - } - - m_previousSourcePort = 0; - -// check for netgear bug behavior. -// as an aside, if there are more than 2 netgear bug firewall's in the game, -// it probably isn't going to work so well. stupid netgear. - -// nodes with a netgear bug behavior need to be matched up first. This prevents -// the NAT table from being reset for connections to other nodes. This also happens -// to be the reason why I call them "nodes" rather than "slots" or "players" as the -// ordering has to be messed with to get the netgears to make love, not war. - DEBUG_LOG(("NAT::establishConnectionPaths - about to set up the node list\n")); - DEBUG_LOG(("NAT::establishConnectionPaths - doing the netgear stuff\n")); - UnsignedInt otherNetgearNum = -1; - for (i = 0; i < MAX_SLOTS; ++i) { - if ((m_slotList != NULL) && (m_slotList[i] != NULL)) { - if ((m_slotList[i]->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) != 0) { - if (otherNetgearNum == -1) { - // this is the start of a new pair, put it in as the first non -1 node connection pair thing. - Int nodeindex = 0; - while ((m_connectionPairs[m_connectionPairIndex][0][nodeindex] == -1) || (m_connectionNodes[nodeindex].m_slotIndex != -1)) { - ++nodeindex; - } - m_connectionNodes[nodeindex].m_slotIndex = i; - m_connectionNodes[nodeindex].m_behavior = m_slotList[i]->getNATBehavior(); - connectionAssigned[i] = TRUE; - otherNetgearNum = nodeindex; - DEBUG_LOG(("NAT::establishConnectionPaths - first netgear in pair. assigning node %d to slot %d (%ls)\n", nodeindex, i, m_slotList[i]->getName().str())); - } else { - // this is the second in the pair of netgears, pair this up with the other one - // for the first round. - Int nodeindex = 0; - while (m_connectionPairs[m_connectionPairIndex][0][nodeindex] != otherNetgearNum) { - ++nodeindex; - } - m_connectionNodes[nodeindex].m_slotIndex = i; - m_connectionNodes[nodeindex].m_behavior = m_slotList[i]->getNATBehavior(); - connectionAssigned[i] = TRUE; - otherNetgearNum = -1; - DEBUG_LOG(("NAT::establishConnectionPaths - second netgear in pair. assigning node %d to slot %d (%ls)\n", nodeindex, i, m_slotList[i]->getName().str())); - } - } - } - } - - // fill in the rest of the nodes with the remaining slots. - DEBUG_LOG(("NAT::establishConnectionPaths - doing the non-Netgear nodes\n")); - for (i = 0; i < MAX_SLOTS; ++i) { - if (connectionAssigned[i] == TRUE) { - continue; - } - if (m_slotList[i] == NULL) { - continue; - } - if (!(m_slotList[i]->isHuman())) { - continue; - } - // find the first available connection node for this slot. - Int nodeindex = 0; - while (m_connectionNodes[nodeindex].m_slotIndex != -1) { - ++nodeindex; - } - DEBUG_LOG(("NAT::establishConnectionPaths - assigning node %d to slot %d (%ls)\n", nodeindex, i, m_slotList[i]->getName().str())); - m_connectionNodes[nodeindex].m_slotIndex = i; - m_connectionNodes[nodeindex].m_behavior = m_slotList[i]->getNATBehavior(); - connectionAssigned[i] = TRUE; - } - -// sanity check -#if defined(_DEBUG) || defined(_INTERNAL) - for (i = 0; i < m_numNodes; ++i) { - DEBUG_ASSERTCRASH(connectionAssigned[i] == TRUE, ("connection number %d not assigned", i)); - } -#endif - - // find the local node number. - for (i = 0; i < m_numNodes; ++i) { - if (m_connectionNodes[i].m_slotIndex == TheGameSpyGame->getLocalSlotNum()) { - m_localNodeNumber = i; - DEBUG_LOG(("NAT::establishConnectionPaths - local node is %d\n", m_localNodeNumber)); - break; - } - } - - // set up the names in the connection window. - Int playerNum = 0; - for (i = 0; i < MAX_SLOTS; ++i) { - while ((i < MAX_SLOTS) && (m_slotList[i] != NULL) && !(m_slotList[i]->isHuman())) { - ++i; - } - if (i >= MAX_SLOTS) { - break; - } - if (i != TheGameSpyGame->getLocalSlotNum()) { - TheEstablishConnectionsMenu->setPlayerName(playerNum, m_slotList[i]->getName()); - TheEstablishConnectionsMenu->setPlayerStatus(playerNum, NATCONNECTIONSTATE_WAITINGTOBEGIN); - ++playerNum; - } - } - -// m_roundTimeout = timeGetTime() + TheGameSpyConfig->getRoundTimeout(); - m_roundTimeout = timeGetTime() + m_timeForRoundTimeout; - - // make the connections for this round. - // this song is cool. - doThisConnectionRound(); -} - -void NAT::attachSlotList(GameSlot *slotList[], Int localSlot, UnsignedInt localIP) { - m_slotList = slotList; - m_localIP = localIP; - m_transport = new Transport; - DEBUG_LOG(("NAT::attachSlotList - initting the transport socket with address %d.%d.%d.%d:%d\n", - m_localIP >> 24, (m_localIP >> 16) & 0xff, (m_localIP >> 8) & 0xff, m_localIP & 0xff, getSlotPort(localSlot))); - - m_startingPortNumber = NETWORK_BASE_PORT_NUMBER + ((timeGetTime() / 1000) % 20000); - DEBUG_LOG(("NAT::attachSlotList - using %d as the starting port number\n", m_startingPortNumber)); - generatePortNumbers(slotList, localSlot); - m_transport->init(m_localIP, getSlotPort(localSlot)); -} - -Int NAT::getSlotPort(Int slot) { -// return (slot + m_startingPortNumber); - if (m_slotList[slot] != NULL) { - return m_slotList[slot]->getPort(); - } - return 0; -} - -void NAT::generatePortNumbers(GameSlot *slotList[], Int localSlot) { - for (Int i = 0; i < MAX_SLOTS; ++i) { - if (slotList[i] != NULL) { - if ((i == localSlot) && (TheWritableGlobalData->m_firewallPortOverride != 0)) { - slotList[i]->setPort(TheWritableGlobalData->m_firewallPortOverride); - } else { - slotList[i]->setPort(i + m_startingPortNumber); - } - } - } -} - -Transport * NAT::getTransport() { - return m_transport; -} - -// figure out which port I'll be using. -// send the port number to our target for this round. -// init the m_connectionStates for all players. -void NAT::doThisConnectionRound() { - DEBUG_LOG(("NAT::doThisConnectionRound - starting process for connection round %d\n", m_connectionRound)); - // clear out the states from the last round. - m_targetNodeNumber = -1; - - for (Int i = 0; i < MAX_SLOTS; ++i) { - setConnectionState(i, NATCONNECTIONSTATE_NOSTATE); - } - - m_beenProbed = FALSE; - m_numRetries = 0; - - for (i = 0; i < m_numNodes; ++i) { - Int targetNodeNumber = m_connectionPairs[m_connectionPairIndex][m_connectionRound][i]; - DEBUG_LOG(("NAT::doThisConnectionRound - node %d needs to connect to node %d\n", i, targetNodeNumber)); - if (targetNodeNumber != -1) { - if (i == m_localNodeNumber) { - m_targetNodeNumber = targetNodeNumber; - DEBUG_LOG(("NAT::doThisConnectionRound - Local node is connecting to node %d\n", m_targetNodeNumber)); - UnsignedInt targetSlotIndex = m_connectionNodes[(m_connectionPairs[m_connectionPairIndex][m_connectionRound][i])].m_slotIndex; - GameSlot *targetSlot = m_slotList[targetSlotIndex]; - GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]; - - DEBUG_ASSERTCRASH(localSlot != NULL, ("local slot is NULL")); - DEBUG_ASSERTCRASH(targetSlot != NULL, ("trying to negotiate with a NULL target slot, slot is %d", m_connectionPairs[m_connectionPairIndex][m_connectionRound][i])); - DEBUG_LOG(("NAT::doThisConnectionRound - Target slot index = %d (%ls)\n", targetSlotIndex, m_slotList[targetSlotIndex]->getName().str())); - DEBUG_LOG(("NAT::doThisConnectionRound - Target slot has NAT behavior 0x%8X, local slot has NAT behavior 0x%8X\n", targetSlot->getNATBehavior(), localSlot->getNATBehavior())); - -#if defined(DEBUG_LOGGING) - UnsignedInt targetIP = targetSlot->getIP(); - UnsignedInt localIP = localSlot->getIP(); -#endif - - DEBUG_LOG(("NAT::doThisConnectionRound - Target slot has IP %d.%d.%d.%d Local slot has IP %d.%d.%d.%d\n", - targetIP >> 24, (targetIP >> 16) & 0xff, (targetIP >> 8) & 0xff, targetIP & 0xff, - localIP >> 24, (localIP >> 16) & 0xff, (localIP >> 8) & 0xff, localIP & 0xff)); - - if (((targetSlot->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) == 0) && - ((localSlot->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) != 0)) { - - // we have a netgear bug type behavior and the target does not, so we need them to send to us - // first to avoid having our NAT table reset. - - DEBUG_LOG(("NAT::doThisConnectionRound - Local node has a netgear and the target node does not, need to delay our probe.\n")); - m_timeTillNextSend = -1; - } - - // figure out which port number I'm using for this connection - // this merely starts to talk to the mangler server, we have to keep calling - // the update function till we get a response. - DEBUG_LOG(("NAT::doThisConnectionRound - About to attempt to get the next mangled source port\n")); - sendMangledSourcePort(); -// m_nextPortSendTime = timeGetTime() + TheGameSpyConfig->getRetryInterval(); - m_nextPortSendTime = timeGetTime() + m_timeBetweenRetries; -// m_timeoutTime = timeGetTime() + TheGameSpyConfig->getPortTimeout(); - m_timeoutTime = timeGetTime() + m_timeToWaitForPort; - } else { - // this is someone else that needs to connect to someone, so wait till they tell us - // that they're done. - setConnectionState(i, NATCONNECTIONSTATE_WAITINGFORRESPONSE); - } - } else { - // no one to connect to, so this one is done. - DEBUG_LOG(("NAT::doThisConnectionRound - node %d has no one to connect to, so they're done\n", i)); - setConnectionState(i, NATCONNECTIONSTATE_DONE); - } - } -} - -void NAT::sendAProbe(UnsignedInt ip, UnsignedShort port, Int fromNode) { - DEBUG_LOG(("NAT::sendAProbe - sending a probe from port %d to %d.%d.%d.%d:%d\n", getSlotPort(m_connectionNodes[m_localNodeNumber].m_slotIndex), - ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff, port)); - AsciiString str; - str.format("PROBE%d", fromNode); - m_transport->queueSend(ip, port, (unsigned char *)str.str(), str.getLength() + 1); - m_transport->doSend(); -} - -// find the next mangled source port, and then send it to the other player. -// if this requires talking to the mangler, we'll have to wait till a later update -// to send our port out. -void NAT::sendMangledSourcePort() { - UnsignedShort sourcePort = getSlotPort(m_connectionNodes[m_localNodeNumber].m_slotIndex); - - FirewallHelperClass::tFirewallBehaviorType fwType = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]->getNATBehavior(); - GameSlot *targetSlot = m_slotList[m_connectionNodes[m_targetNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(targetSlot != NULL, ("NAT::sendMangledSourcePort - targetSlot is NULL")); - if (targetSlot == NULL) { - DEBUG_LOG(("NAT::sendMangledSourcePort - targetSlot is NULL, failed this connection\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - return; - } - - GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(localSlot != NULL, ("NAT::sendMangledSourcePort - localSlot is NULL, WTF?")); - if (localSlot == NULL) { - DEBUG_LOG(("NAT::sendMangledSourcePort - localSlot is NULL, failed this connection\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - return; - } - - // check to see if the target and I are behind the same NAT - if (targetSlot->getIP() == localSlot->getIP()) { -#if defined(DEBUG_LOGGING) - UnsignedInt localip = localSlot->getIP(); - UnsignedInt targetip = targetSlot->getIP(); -#endif - DEBUG_LOG(("NAT::sendMangledSourcePort - target and I are behind the same NAT, no mangling\n")); - DEBUG_LOG(("NAT::sendMangledSourcePort - I am %ls, target is %ls, my IP is %d.%d.%d.%d, target IP is %d.%d.%d.%d\n", localSlot->getName().str(), targetSlot->getName().str(), - localip >> 24, (localip >> 16) & 0xff, (localip >> 8) & 0xff, localip & 0xff, - targetip >> 24, (targetip >> 16) & 0xff, (targetip >> 8) & 0xff, targetip & 0xff)); - - sendMangledPortNumberToTarget(sourcePort, targetSlot); - m_sourcePorts[m_targetNodeNumber] = sourcePort; - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT); - // In case you're wondering, we don't set the m_previousSourcePort here because this will be a different source - // address than what other nodes will likely see (unless of course there are more than - // two of us behind the same NAT, but we won't worry about that cause theres no mangling - // in that case anyways) - return; - } - - // check to see if we are NAT'd at all. - if ((fwType == 0) || (fwType == FirewallHelperClass::FIREWALL_TYPE_SIMPLE)) { - // no mangling, just return the source port - DEBUG_LOG(("NAT::sendMangledSourcePort - no mangling, just using the source port\n")); - sendMangledPortNumberToTarget(sourcePort, targetSlot); - m_previousSourcePort = sourcePort; - m_sourcePorts[m_targetNodeNumber] = sourcePort; - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT); - return; - } - - // check to see if our NAT keeps the same source port for different destinations. - // if this is the case, and we've already worked out what our mangled port number is - // then we don't have to figure it out again. - if (((fwType & FirewallHelperClass::FIREWALL_TYPE_DESTINATION_PORT_DELTA) == 0) && - ((fwType & FirewallHelperClass::FIREWALL_TYPE_SMART_MANGLING) == 0)) { - DEBUG_LOG(("NAT::sendMangledSourcePort - our firewall doesn't NAT based on destination address, checking for old connections from this address\n")); - if (m_previousSourcePort != 0) { - DEBUG_LOG(("NAT::sendMangledSourcePort - Previous source port was %d, using that one\n", m_previousSourcePort)); - sendMangledPortNumberToTarget(m_previousSourcePort, targetSlot); - m_sourcePorts[m_targetNodeNumber] = m_previousSourcePort; - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT); - return; - } else { - DEBUG_LOG(("NAT::sendMangledSourcePort - Previous source port not found\n")); - } - } - - // At this point we know that our NAT uses some kind of relative port mapping scheme, so we - // need to talk to the mangler to find out where we are now so we can find out where we'll be on the - // next port allocation. - - // get the address of the mangler we need to talk to. - Char manglerName[256]; - FirewallHelperClass::getManglerName(1, manglerName); - DEBUG_LOG(("NAT::sendMangledSourcePort - about to call gethostbyname for mangler at %s\n", manglerName)); - struct hostent *hostInfo = gethostbyname(manglerName); - - if (hostInfo == NULL) { - DEBUG_LOG(("NAT::sendMangledSourcePort - gethostbyname failed for mangler address %s\n", manglerName)); - // can't find the mangler, we're screwed so just send the source port. - sendMangledPortNumberToTarget(sourcePort, targetSlot); - m_sourcePorts[m_targetNodeNumber] = sourcePort; - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT); - return; - } - - memcpy(&m_manglerAddress, &(hostInfo->h_addr_list[0][0]), 4); - m_manglerAddress = ntohl(m_manglerAddress); - DEBUG_LOG(("NAT::sendMangledSourcePort - mangler %s address is %d.%d.%d.%d\n", manglerName, - m_manglerAddress >> 24, (m_manglerAddress >> 16) & 0xff, (m_manglerAddress >> 8) & 0xff, m_manglerAddress & 0xff)); - - DEBUG_LOG(("NAT::sendMangledSourcePort - NAT behavior = 0x%08x\n", fwType)); - -// m_manglerRetryTime = TheGameSpyConfig->getRetryInterval() + timeGetTime(); - m_manglerRetryTime = m_manglerRetryTimeInterval + timeGetTime(); - m_manglerRetries = 0; - - if (TheFirewallHelper != NULL) { - m_spareSocketPort = TheFirewallHelper->getNextTemporarySourcePort(0); - TheFirewallHelper->openSpareSocket(m_spareSocketPort); - TheFirewallHelper->sendToManglerFromPort(m_manglerAddress, m_spareSocketPort, m_packetID); -// m_manglerRetryTime = TheGameSpyConfig->getRetryInterval() + timeGetTime(); - m_manglerRetryTime = m_manglerRetryTimeInterval + timeGetTime(); - } - - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLERRESPONSE); -} - -void NAT::processManglerResponse(UnsignedShort mangledPort) { - DEBUG_LOG(("NAT::processManglerResponse - Work out what my NAT'd port will be\n")); - - GameSlot *targetSlot = m_slotList[m_connectionNodes[m_targetNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(targetSlot != NULL, ("NAT::processManglerResponse - targetSlot is NULL")); - if (targetSlot == NULL) { - DEBUG_LOG(("NAT::processManglerResponse - targetSlot is NULL, failed this connection\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - return; - } - - Short delta = TheGlobalData->m_firewallPortAllocationDelta; - UnsignedShort sourcePort = getSlotPort(m_connectionNodes[m_localNodeNumber].m_slotIndex); - UnsignedShort returnPort = 0; - - FirewallHelperClass::tFirewallBehaviorType fwType = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]->getNATBehavior(); - - if ((fwType & FirewallHelperClass::FIREWALL_TYPE_SIMPLE_PORT_ALLOCATION) != 0) { - returnPort = mangledPort + delta; - } else { - // to steal a line from Steve Tall... - // Rats. It's a relative mangler. This is much harder. Damn NAT32 guy. - if (delta == 100) { - // Special NAT32 section. - // NAT32 mangles source UDP port by ading 1700 + 100*NAT table index. - returnPort = mangledPort - m_spareSocketPort; - returnPort -= 1700; - - returnPort += delta; - returnPort += sourcePort; - returnPort += 1700; - - } else if (delta == 0) { - returnPort = sourcePort; - } else { - returnPort = mangledPort / delta; - returnPort = returnPort * delta; - - returnPort += (sourcePort % delta); - returnPort += delta; - } - } - - // This bit is probably doomed. - if (returnPort > 65535) { - returnPort -= 65535; - } - if (returnPort < 1024) { - returnPort += 1024; - } - - DEBUG_LOG(("NAT::processManglerResponse - mangled port is %d\n", returnPort)); - m_previousSourcePort = returnPort; - - sendMangledPortNumberToTarget(returnPort, targetSlot); - m_sourcePorts[m_targetNodeNumber] = returnPort; - if (targetSlot->getPort() == 0) { - // we haven't got the target's mangled port number yet, wait for it. - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT); - } else { - // in this case we should have already sent a PROBE, so we'll just change the state - // and leave it at that. - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORRESPONSE); - } -} - -// check to see if we've completed all the rounds -// this is kind of a cheesy way to check, but it works. -Bool NAT::allConnectionsDone() { - if (m_numNodes == 2) { - if (m_connectionRound >= 1) { - return TRUE; - } - } else if (m_numNodes == 3) { - if (m_connectionRound >= 3) { - return TRUE; - } - } else if (m_numNodes == 4) { - if (m_connectionRound >= 3) { - return TRUE; - } - } else if (m_numNodes == 5) { - if (m_connectionRound >= 5) { - return TRUE; - } - } else if (m_numNodes == 6) { - if (m_connectionRound >= 5) { - return TRUE; - } - } else if (m_numNodes == 7) { - if (m_connectionRound >= 7) { - return TRUE; - } - } else if (m_numNodes == 8) { - if (m_connectionRound >= 7) { - return TRUE; - } - } - return FALSE; -} - -Bool NAT::allConnectionsDoneThisRound() { - Bool retval = TRUE; - for (Int i = 0; (i < m_numNodes) && (retval == TRUE); ++i) { - if ((m_connectionStates[i] != NATCONNECTIONSTATE_DONE) && (m_connectionStates[i] != NATCONNECTIONSTATE_FAILED)) { - retval = FALSE; - } - } - return retval; -} - -// this node's connection for this round has been completed. -void NAT::connectionComplete(Int slotIndex) { -} - -// this node's connection for this round has failed. -void NAT::connectionFailed(Int slotIndex) { -} - -// I have been probed by the target. -void NAT::probed(Int nodeNumber) { - GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(localSlot != NULL, ("NAT::probed - localSlot is NULL, WTF?")); - if (localSlot == NULL) { - DEBUG_LOG(("NAT::probed - localSlot is NULL, failed this connection\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - return; - } - - if (m_beenProbed == FALSE) { - m_beenProbed = TRUE; - DEBUG_LOG(("NAT::probed - just got probed for the first time.\n")); - if ((localSlot->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) != 0) { - DEBUG_LOG(("NAT::probed - we have a NETGEAR and we were just probed for the first time\n")); - GameSlot *targetSlot = m_slotList[m_connectionNodes[m_targetNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(targetSlot != NULL, ("NAT::probed - targetSlot is NULL")); - if (targetSlot == NULL) { - DEBUG_LOG(("NAT::probed - targetSlot is NULL, failed this connection\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - return; - } - - if (targetSlot->getPort() == 0) { - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT); - DEBUG_LOG(("NAT::probed - still waiting for mangled port\n")); - } else { - DEBUG_LOG(("NAT::probed - sending a probe to %ls\n", targetSlot->getName().str())); - sendAProbe(targetSlot->getIP(), targetSlot->getPort(), m_localNodeNumber); - notifyTargetOfProbe(targetSlot); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORRESPONSE); - } - } - } -} - -// got the mangled port for our target for this round. -void NAT::gotMangledPort(Int nodeNumber, UnsignedShort mangledPort) { - - // if we've already finished the connection, then we don't need to process this. - if (m_connectionStates[m_localNodeNumber] == NATCONNECTIONSTATE_DONE) { - DEBUG_LOG(("NAT::gotMangledPort - got a mangled port, but we've already finished this connection, ignoring.\n")); - return; - } - - GameSlot *targetSlot = m_slotList[m_connectionNodes[m_targetNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(targetSlot != NULL, ("NAT::gotMangledPort - targetSlot is NULL")); - if (targetSlot == NULL) { - DEBUG_LOG(("NAT::gotMangledPort - targetSlot is NULL, failed this connection\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - return; - } - - GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(localSlot != NULL, ("NAT::gotMangledPort - localSlot is NULL, WTF?")); - if (localSlot == NULL) { - DEBUG_LOG(("NAT::gotMangledPort - localSlot is NULL, failed this connection\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - return; - } - - if (nodeNumber != m_targetNodeNumber) { - DEBUG_LOG(("NAT::gotMangledPort - got a mangled port number for someone that isn't my target. node = %d, target node = %d\n", nodeNumber, m_targetNodeNumber)); - return; - } - - targetSlot->setPort(mangledPort); - DEBUG_LOG(("NAT::gotMangledPort - got mangled port number %d from our target node (%ls)\n", mangledPort, targetSlot->getName().str())); - if (((localSlot->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) == 0) || (m_beenProbed == TRUE) || - (((localSlot->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) != 0) && ((targetSlot->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) != 0))) { -#ifdef DEBUG_LOGGING - UnsignedInt ip = targetSlot->getIP(); -#endif - DEBUG_LOG(("NAT::gotMangledPort - don't have a netgear or we have already been probed, or both my target and I have a netgear, send a PROBE. Sending to %d.%d.%d.%d:%d\n", - ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff, targetSlot->getPort())); - - sendAProbe(targetSlot->getIP(), targetSlot->getPort(), m_localNodeNumber); - notifyTargetOfProbe(targetSlot); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORRESPONSE); - } else { - DEBUG_LOG(("NAT::gotMangledPort - we are a netgear, not sending a PROBE yet.\n")); - } -} - -void NAT::gotInternalAddress(Int nodeNumber, UnsignedInt address) { - GameSlot *targetSlot = m_slotList[m_connectionNodes[nodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(targetSlot != NULL, ("NAT::gotInternalAddress - targetSlot is NULL")); - if (targetSlot == NULL) { - return; - } - - GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(localSlot != NULL, ("NAT::gotInternalAddress - localSlot is NULL, WTF?")); - if (localSlot == NULL) { - return; - } - - if (nodeNumber != m_targetNodeNumber) { - DEBUG_LOG(("NAT::gotInternalAddress - got a internal address for someone that isn't my target. node = %d, target node = %d\n", nodeNumber, m_targetNodeNumber)); - return; - } - - if (localSlot->getIP() == targetSlot->getIP()) { - // we have the same IP address, i.e. we are behind the same NAT. - // I need to talk directly to his internal address. - DEBUG_LOG(("NAT::gotInternalAddress - target and local players have same external address, using internal address.\n")); - targetSlot->setIP(address); // use the slot's internal address from now on - } -} - -void NAT::notifyTargetOfProbe(GameSlot *targetSlot) { - PeerRequest req; - AsciiString options; - options.format("PROBED%d", m_localNodeNumber); - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "NAT/"; - AsciiString hostName; - hostName.translate(targetSlot->getName()); - req.nick = hostName.str(); - req.options = options.str(); - TheGameSpyPeerMessageQueue->addRequest(req); - DEBUG_LOG(("NAT::notifyTargetOfProbe - notifying %ls that we have probed them.\n", targetSlot->getName().str())); -} - -void NAT::notifyUsersOfConnectionDone(Int nodeIndex) { - GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(localSlot != NULL, ("NAT::notifyUsersOfConnectionDone - localSlot is NULL, WTF?")); - if (localSlot == NULL) { - DEBUG_LOG(("NAT::notifyUsersOfConnectionDone - localSlot is NULL, failed this connection\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - return; - } - - PeerRequest req; - AsciiString options; - options.format("CONNDONE%d %d", nodeIndex, m_localNodeNumber); - - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "NAT"; - AsciiString names; - for (Int i=0; iisHuman() == FALSE)) { - continue; - } - - AsciiString name; - name.translate(m_slotList[i]->getName()); - if (names.isNotEmpty()) - { - names.concat(','); - } - names.concat(name); - } - req.nick = names.str(); - req.options = options.str(); - - DEBUG_LOG(("NAT::notifyUsersOfConnectionDone - sending %s to %s\n", options.str(), names.str())); - TheGameSpyPeerMessageQueue->addRequest(req); -} - -void NAT::notifyUsersOfConnectionFailed(Int nodeIndex) { - GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]; - DEBUG_ASSERTCRASH(localSlot != NULL, ("NAT::notifyUsersOfConnectionFailed - localSlot is NULL, WTF?")); - if (localSlot == NULL) { - DEBUG_LOG(("NAT::notifyUsersOfConnectionFailed - localSlot is NULL, failed this connection\n")); - setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED); - return; - } - - PeerRequest req; - AsciiString options; - options.format("CONNFAILED%d", nodeIndex); -/* - req.peerRequestType = PeerRequest::PEERREQUEST_UTMROOM; - req.UTM.isStagingRoom = TRUE; - req.id = "NAT/"; - req.options = options.str(); - - DEBUG_LOG(("NAT::notifyUsersOfConnectionFailed - sending %s to room\n", options.str())); -*/ - - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "NAT"; - AsciiString names; - for (Int i=0; iisHuman() == FALSE)) { - continue; - } - - AsciiString name; - name.translate(m_slotList[i]->getName()); - if (names.isNotEmpty()) - { - names.concat(','); - } - names.concat(name); - } - req.nick = names.str(); - req.options = options.str(); - - DEBUG_LOG(("NAT::notifyUsersOfConnectionFailed - sending %s to %s\n", options.str(), names.str())); - - TheGameSpyPeerMessageQueue->addRequest(req); -} - -void NAT::sendMangledPortNumberToTarget(UnsignedShort mangledPort, GameSlot *targetSlot) { - PeerRequest req; - AsciiString options; - options.format("PORT%d %d %08X", m_localNodeNumber, mangledPort, m_localIP); - - req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER; - req.UTM.isStagingRoom = TRUE; - req.id = "NAT/"; - AsciiString hostName; - hostName.translate(targetSlot->getName()); - req.nick = hostName.str(); - req.options = options.str(); - DEBUG_LOG(("NAT::sendMangledPortNumberToTarget - sending \"%s\" to %s\n", options.str(), hostName.str())); - TheGameSpyPeerMessageQueue->addRequest(req); -} - -void NAT::processGlobalMessage(Int slotNum, const char *options) { - const char *ptr = options; - // skip preceding whitespace. - while (isspace(*ptr)) { - ++ptr; - } - DEBUG_LOG(("NAT::processGlobalMessage - got message from slot %d, message is \"%s\"\n", slotNum, ptr)); - if (!strncmp(ptr, "PROBED", strlen("PROBED"))) { - // format: PROBED - // a probe has been sent at us, if we are waiting because of a netgear or something, we - // should start sending our own probes. - Int node = atoi(ptr + strlen("PROBED")); - if (node == m_targetNodeNumber) { - // make sure we're being probed by who we're supposed to be probed by. - probed(node); - } else { - DEBUG_LOG(("NAT::processGlobalMessage - probed by node %d, not our target\n", node)); - } - } else if (!strncmp(ptr, "CONNDONE", strlen("CONNDONE"))) { - // format: CONNDONE - // we should get the node number of the player who's connection is done from the options - // and mark that down as part of the connectionStates. - const char *c = ptr + strlen("CONNDONE"); -/* while (*c != ' ') { - ++c; - } - while (*c == ' ') { - ++c; - } -*/ Int node; - Int sendingNode; - sscanf(c, "%d %d\n", &node, &sendingNode); - - if (m_connectionPairs[m_connectionPairIndex][m_connectionRound][node] == sendingNode) { -// Int node = atoi(ptr + strlen("CONNDONE")); - DEBUG_LOG(("NAT::processGlobalMessage - got a CONNDONE message for node %d\n", node)); - if ((node >= 0) && (node <= m_numNodes)) { - DEBUG_LOG(("NAT::processGlobalMessage - node %d's connection is complete, setting connection state to done\n", node)); - setConnectionState(node, NATCONNECTIONSTATE_DONE); - } - } else { - DEBUG_LOG(("NAT::processGlobalMessage - got a connection done message that isn't from this round. node: %d sending node: %d\n", node, sendingNode)); - } - } else if (!strncmp(ptr, "CONNFAILED", strlen("CONNFAILED"))) { - // format: CONNFAILED - // we should get the node number of the player who's connection failed from the options - // and mark that down as part of the connectionStates. - Int node = atoi(ptr + strlen("CONNFAILED")); - if ((node >= 0) && (node < m_numNodes)) { - DEBUG_LOG(("NAT::processGlobalMessage - node %d's connection failed, setting connection state to failed\n", node)); - setConnectionState(node, NATCONNECTIONSTATE_FAILED); - } - } else if (!strncmp(ptr, "PORT", strlen("PORT"))) { - // format: PORT - // we should get the node number and the mangled port number of the client we - // are supposed to be communicating with and start probing them. No, that was not - // meant to be a phallic reference, you sicko. - const char *c = ptr + strlen("PORT"); - Int node = atoi(c); - while (*c != ' ') { - ++c; - } - while (*c == ' ') { - ++c; - } - UnsignedInt intport = 0; - UnsignedInt addr = 0; - sscanf(c, "%d %X", &intport, &addr); - UnsignedShort port = (UnsignedShort)intport; - - DEBUG_LOG(("NAT::processGlobalMessage - got port message from node %d, port: %d, internal address: %d.%d.%d.%d\n", node, port, - addr >> 24, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff)); - - if ((node >= 0) && (node < m_numNodes)) { - if (port < 1024) { - // it has to be less than 65535 cause its a short duh. - DEBUG_ASSERTCRASH(port >= 1024, ("Was passed an invalid port number")); - port += 1024; - } - gotInternalAddress(node, addr); - gotMangledPort(node, port); - } - } -} - -void NAT::setConnectionState(Int nodeNumber, NATConnectionState state) { - m_connectionStates[nodeNumber] = state; - - if (nodeNumber != m_localNodeNumber) { - return; - } - - // if this is the case we are starting a new round and we don't know - // who we're connecting to yet. - if (m_localNodeNumber == m_targetNodeNumber) { - return; - } - - // if this is the start of a new connection round we don't have a - // target yet. - if (m_targetNodeNumber == -1) { - return; - } - - // find the menu slot of the target node. - Int slotIndex = m_connectionNodes[m_targetNodeNumber].m_slotIndex; - Int slot = 0; - for (Int i = 0; i < MAX_SLOTS; ++i) { - if (m_slotList[i] != NULL) { - if (m_slotList[i]->isHuman()) { - if (i != m_connectionNodes[m_localNodeNumber].m_slotIndex) { - if (i == slotIndex) { - break; - } - ++slot; - } - } - } - } - if (i == MAX_SLOTS) { - DEBUG_ASSERTCRASH(i < MAX_SLOTS, ("Didn't find the node number in the slot list")); - return; - } - TheEstablishConnectionsMenu->setPlayerStatus(slot, state); -} diff --git a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DMainMenu.cpp b/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DMainMenu.cpp index 30464c897fc..2da2534fe69 100644 --- a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DMainMenu.cpp +++ b/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DMainMenu.cpp @@ -916,17 +916,11 @@ void W3DMainMenuInit( WindowLayout *layout, void *userData ) NameKeyType buttonUSAID = TheNameKeyGenerator->nameToKey( "MainMenu.wnd:ButtonUSA" ); NameKeyType buttonGLAID = TheNameKeyGenerator->nameToKey( "MainMenu.wnd:ButtonGLA" ); NameKeyType buttonChinaID = TheNameKeyGenerator->nameToKey( "MainMenu.wnd:ButtonChina" ); - NameKeyType skirmishID = TheNameKeyGenerator->nameToKey( AsciiString("MainMenu.wnd:ButtonSkirmish") ); - NameKeyType onlineID = TheNameKeyGenerator->nameToKey( AsciiString("MainMenu.wnd:ButtonOnline") ); - NameKeyType networkID = TheNameKeyGenerator->nameToKey( AsciiString("MainMenu.wnd:ButtonNetwork") ); + NameKeyType skirmishID = TheNameKeyGenerator->nameToKey( AsciiString("MainMenu.wnd:ButtonSkirmish") ); NameKeyType networkID = TheNameKeyGenerator->nameToKey( AsciiString("MainMenu.wnd:ButtonNetwork") ); GameWindow *button = TheWindowManager->winGetWindowFromId( parent, skirmishID ); if (button) - button->winSetDrawFunc(W3DMainMenuButtonDropShadowDraw); - button = TheWindowManager->winGetWindowFromId( parent, onlineID ); - if (button) - button->winSetDrawFunc(W3DMainMenuButtonDropShadowDraw); - button = TheWindowManager->winGetWindowFromId( parent, networkID ); + button->winSetDrawFunc(W3DMainMenuButtonDropShadowDraw); button = TheWindowManager->winGetWindowFromId( parent, networkID ); if (button) button->winSetDrawFunc(W3DMainMenuButtonDropShadowDraw);