/* ** 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__