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