1
This commit is contained in:
398
engine/matchmaking.h
Normal file
398
engine/matchmaking.h
Normal file
@ -0,0 +1,398 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
#ifndef MATCHMAKING_H
|
||||
#define MATCHMAKING_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "winerror.h"
|
||||
#endif
|
||||
#include "utlmap.h"
|
||||
#include "inetmsghandler.h"
|
||||
#include "netmessages.h"
|
||||
#include "Session.h"
|
||||
#include "engine/imatchmaking.h"
|
||||
|
||||
enum MMPACKETS
|
||||
{
|
||||
PTH_CONNECT,
|
||||
PTH_SYSTEMLINK_SEARCH,
|
||||
HTP_SYSTEMLINK_REPLY
|
||||
};
|
||||
|
||||
enum MMSTATE
|
||||
{
|
||||
MMSTATE_INITIAL,
|
||||
MMSTATE_IDLE,
|
||||
MMSTATE_CREATING,
|
||||
MMSTATE_MODIFYING,
|
||||
MMSTATE_ACCEPTING_CONNECTIONS,
|
||||
MMSTATE_SEARCHING,
|
||||
MMSTATE_WAITING_QOS,
|
||||
MMSTATE_BROWSING,
|
||||
MMSTATE_SESSION_CONNECTING,
|
||||
MMSTATE_SESSION_CONNECTED,
|
||||
MMSTATE_SESSION_DISCONNECTING,
|
||||
|
||||
MMSTATE_HOSTMIGRATE_STARTINGMIGRATION,
|
||||
MMSTATE_HOSTMIGRATE_MIGRATING,
|
||||
MMSTATE_HOSTMIGRATE_WAITINGFORCLIENTS,
|
||||
MMSTATE_HOSTMIGRATE_WAITINGFORHOST,
|
||||
|
||||
MMSTATE_GAME_LOCKED, // in ranked games, clients can't join after this point
|
||||
|
||||
MMSTATE_PREGAME,
|
||||
MMSTATE_REPORTING_STATS,
|
||||
MMSTATE_POSTGAME,
|
||||
|
||||
MMSTATE_GAME_ACTIVE, // clients are no longer in the lobby
|
||||
|
||||
MMSTATE_LOADING,
|
||||
MMSTATE_CONNECTED_TO_SERVER,
|
||||
MMSTATE_INGAME,
|
||||
};
|
||||
|
||||
// For sending host data back in search results
|
||||
enum eGameState
|
||||
{
|
||||
GAMESTATE_INLOBBY,
|
||||
GAMESTATE_INPROGRESS
|
||||
};
|
||||
|
||||
#define HEARTBEAT_INTERVAL_LONG 1.0 // send a heartbeat every second during gameplay
|
||||
#define HEARTBEAT_INTERVAL_SHORT 0.1 // send a heartbeat ten times a second in the lobby
|
||||
#define HEARTBEAT_TIMEOUT 10.0 // time out if a heartbeat isn't recieved for ten seconds
|
||||
#if defined( _DEBUG )
|
||||
#define HEARTBEAT_TIMEOUT_LOADING 300 // in debug loads take much longer
|
||||
#else
|
||||
#define HEARTBEAT_TIMEOUT_LOADING 100 // allow for longer communication gaps during map load
|
||||
#endif
|
||||
|
||||
#define STARTGAME_COUNTDOWN 15.0 // start game countdown timer
|
||||
#define DISCONNECT_WAITTIME 1.0 // wait for the server to reply to our disconnect notification
|
||||
#define QOSLOOKUP_WAITTIME 20.0 // wait to get quality of service data about session hosts
|
||||
#define JOINREPLY_WAITTIME 15.0 // time to wait for the host to reply to our join request
|
||||
#define REPORTSTATS_WAITTIME 20.0 // time to wait for clients to report their stats to live
|
||||
|
||||
// 360 TCR's require system link searches complete in less than 3 seconds
|
||||
#define SYSTEMLINK_RETRYINTERVAL 1.f // in seconds
|
||||
#define SYSTEMLINK_MAXRETRIES 3 // number of tries before giving up
|
||||
|
||||
#define SESSIONMODIRY_MAXWAITTIME 10 // max time for clients to update their session properties
|
||||
#define REGISTRATION_MAXWAITTIME 10 // max time for clients to register
|
||||
|
||||
#define HOSTMIGRATION_RETRYINTERVAL 1.0 // in seconds
|
||||
#define HOSTMIGRATION_MAXRETRIES 10 // max migrate sends to clients
|
||||
#define HOSTMIGRATION_MAXWAITTIME 10 // time to wait for a new host to contact us
|
||||
|
||||
#define MAX_SEARCHRESULTS 20 // Maximum number of results when searching for a session.
|
||||
|
||||
#define PING_MAX_GREEN 70
|
||||
#define PING_MAX_YELLOW 140
|
||||
#define PING_MAX_RED 250
|
||||
|
||||
#define VOICE_STATUS_OFF 0
|
||||
#define VOICE_STATUS_IDLE 1
|
||||
#define VOICE_STATUS_TALKING 2
|
||||
|
||||
// HACK: For simplicity, we know TF has two teams plus spectator.
|
||||
#define MAX_TEAMS 3
|
||||
#define MAX_PLAYERS 16
|
||||
|
||||
#define VOICE_ICON_BLINK_TIME 0.5
|
||||
|
||||
class CMatchmaking : public IMatchmaking, public IMatchmakingMessageHandler, public IClientMessageHandler, public INetChannelHandler, public IConnectionlessPacketHandler
|
||||
{
|
||||
public:
|
||||
CMatchmaking();
|
||||
~CMatchmaking();
|
||||
|
||||
// IMatchmaking implementation
|
||||
virtual void SessionNotification( const SESSION_NOTIFY notification, const int param = 0 );
|
||||
virtual void AddSessionProperty( const uint nType, const char *pID, const char *pValue, const char *pValueType );
|
||||
virtual void SetSessionProperties( KeyValues *pPropertyKeys );
|
||||
virtual void SelectSession( uint sessionIdx );
|
||||
virtual void ModifySession();
|
||||
virtual void UpdateMuteList();
|
||||
virtual void StartHost( bool bSystemLink = false );
|
||||
virtual void StartClient( bool bSystemLink = false );
|
||||
virtual bool StartGame();
|
||||
virtual bool CancelStartGame();
|
||||
virtual void ChangeTeam( const char *pTeamName );
|
||||
virtual void TellClientsToConnect();
|
||||
virtual void CancelCurrentOperation();
|
||||
virtual void EndStatsReporting();
|
||||
|
||||
virtual void JoinInviteSessionByID( XNKID nSessionID );
|
||||
virtual void JoinInviteSession( XSESSION_INFO *pHostInfo );
|
||||
virtual void KickPlayerFromSession( uint64 id );
|
||||
|
||||
// For GameUI
|
||||
virtual KeyValues *GetSessionProperties();
|
||||
|
||||
// For voice chat
|
||||
virtual uint64 PlayerIdToXuid( int playerId );
|
||||
virtual bool IsPlayerMuted( int iUserId, XUID id );
|
||||
|
||||
// To determine host Quality-of-Service
|
||||
virtual MM_QOS_t GetQosWithLIVE();
|
||||
|
||||
virtual bool PreventFullServerStartup();
|
||||
|
||||
// IConnectionlessPacketHandler implementation (Host/Client shared)
|
||||
virtual bool ProcessConnectionlessPacket( netpacket_t * packet );
|
||||
|
||||
// INetChannelHandler implementation
|
||||
virtual void ConnectionStart(INetChannel *chan); // called first time network channel is established
|
||||
virtual void PacketEnd(); // all messages have been parsed
|
||||
|
||||
// NetChannel message handlers
|
||||
PROCESS_NET_MESSAGE( Tick ) { return true; }
|
||||
PROCESS_NET_MESSAGE( SetConVar ) { return true; }
|
||||
PROCESS_NET_MESSAGE( StringCmd ) { return true; }
|
||||
PROCESS_NET_MESSAGE( SignonState ) { return true; }
|
||||
|
||||
PROCESS_CLC_MESSAGE( VoiceData );
|
||||
PROCESS_CLC_MESSAGE( ClientInfo ) { return true; }
|
||||
PROCESS_CLC_MESSAGE( Move ) { return true; }
|
||||
PROCESS_CLC_MESSAGE( BaselineAck ) { return true; }
|
||||
PROCESS_CLC_MESSAGE( ListenEvents ) { return true; }
|
||||
PROCESS_CLC_MESSAGE( RespondCvarValue ) { return true; }
|
||||
PROCESS_CLC_MESSAGE( FileCRCCheck ) { return true; }
|
||||
PROCESS_CLC_MESSAGE( FileMD5Check ) { return true; }
|
||||
PROCESS_CLC_MESSAGE( SaveReplay ) { return true; }
|
||||
PROCESS_CLC_MESSAGE( CmdKeyValues ) { return true; }
|
||||
|
||||
|
||||
PROCESS_MM_MESSAGE( JoinResponse );
|
||||
PROCESS_MM_MESSAGE( ClientInfo );
|
||||
PROCESS_MM_MESSAGE( RegisterResponse );
|
||||
PROCESS_MM_MESSAGE( Migrate );
|
||||
PROCESS_MM_MESSAGE( Mutelist );
|
||||
PROCESS_MM_MESSAGE( Checkpoint );
|
||||
PROCESS_MM_MESSAGE( Heartbeat ) { return true; }
|
||||
|
||||
// (Not used)
|
||||
virtual void ConnectionClosing(const char *reason) {}; // network channel is being closed by remote site
|
||||
virtual void ConnectionCrashed(const char *reason) {}; // network error occurred
|
||||
virtual void PacketStart(int incoming_sequence, int outgoing_acknowledged) {}; // called each time a new packet arrived
|
||||
virtual void FileRequested(const char *fileName, unsigned int transferID ) {}; // other side request a file for download
|
||||
virtual void FileReceived(const char *fileName, unsigned int transferID ) {}; // we received a file
|
||||
virtual void FileDenied(const char *fileName, unsigned int transferID ) {}; // a file request was denied by other side
|
||||
virtual void FileSent(const char *fileName, unsigned int transferID ) {}; // a file was sent
|
||||
|
||||
// Debugging helpers
|
||||
void ShowSessionInfo();
|
||||
void SendDevMessage( const char *message );
|
||||
|
||||
void SetSessionSlots( const uint nSlotsTotal, const uint nSlotsPrivate );
|
||||
void RunFrame();
|
||||
void EndGame();
|
||||
|
||||
void AddLocalPlayersToTeams();
|
||||
void OnLevelLoadingFinished();
|
||||
|
||||
void TestSendMessage();
|
||||
void TestStats();
|
||||
|
||||
bool GameIsActive();
|
||||
|
||||
void PrintVoiceStatus( void );
|
||||
|
||||
private:
|
||||
// NetChannel send
|
||||
void SendMessage( INetMessage *msg, netadr_t *adr, bool bVoice = false );
|
||||
void SendMessage( INetMessage *msg, CClientInfo *pClient, bool bVoice = false );
|
||||
void SendToRemoteClients( INetMessage *msg, bool bVoice = false, XUID excludeXUID = -1 );
|
||||
|
||||
// Session Host
|
||||
void OnHostSessionCreated();
|
||||
void UpdateAcceptingConnections();
|
||||
void SendModifySessionMessage();
|
||||
void EndSessionModify();
|
||||
bool IsAcceptingConnections();
|
||||
void HandleSystemLinkSearch( netpacket_t *pPacket );
|
||||
void HandleJoinRequest( netpacket_t *pPacket );
|
||||
void StartCountdown();
|
||||
void CancelCountdown();
|
||||
void UpdatePregame();
|
||||
void UpdateRegistration();
|
||||
void UpdateSessionModify();
|
||||
void ProcessRegistrationResults();
|
||||
void UpdateServerNegotiation();
|
||||
void UpdateSessionReplyData( uint flags );
|
||||
void SwitchToNextOpenTeam( CClientInfo *pClient );
|
||||
void SetupTeams();
|
||||
int ChooseTeam();
|
||||
int GetPlayersNeeded();
|
||||
|
||||
// Session Client
|
||||
bool StartSystemLinkSearch();
|
||||
void HandleSystemLinkReply( netpacket_t *pPacket );
|
||||
bool SearchForSession();
|
||||
void UpdateSearch();
|
||||
void UpdateQosLookup();
|
||||
void CancelSearch();
|
||||
void CancelQosLookup();
|
||||
void ClearSearchResults();
|
||||
void SendJoinRequest( netadr_t *adr );
|
||||
bool ConnectToHost();
|
||||
void UpdateConnecting();
|
||||
void ApplySessionProperties( int numContexts, int numProperties, XUSER_CONTEXT *pContexts, XUSER_PROPERTY *pProperties );
|
||||
|
||||
// Host/Client shared
|
||||
bool InitializeLocalClient( bool bIsHost );
|
||||
void AddPlayersToSession( CClientInfo *pClient );
|
||||
void SendPlayerInfoToLobby( CClientInfo *pClient, int iHostIdx = -1 );
|
||||
void RemovePlayersFromSession( CClientInfo *pClient );
|
||||
void ClientDropped( CClientInfo *pClient );
|
||||
void PerformDisconnect();
|
||||
void GenerateMutelist( MM_Mutelist *pMsg );
|
||||
int FindOrCreateContext( const uint id );
|
||||
int FindOrCreateProperty( const uint id );
|
||||
void AddSessionPropertyInternal( KeyValues *pProperty );
|
||||
|
||||
// Host Migration
|
||||
CClientInfo *SelectNewHost();
|
||||
void StartHostMigration();
|
||||
void BeginHosting();
|
||||
void TellClientsToMigrate();
|
||||
void SwitchToNewHost();
|
||||
void EndMigration();
|
||||
|
||||
// General utility functions
|
||||
void Cleanup();
|
||||
void SwitchToState( int newState );
|
||||
double GetTime();
|
||||
void SendHeartbeat();
|
||||
bool SendHeartbeat( CClientInfo *pClient );
|
||||
void ClientInfoToNetMessage( MM_ClientInfo *pInfo, const CClientInfo *pClient );
|
||||
void NetMessageToClientInfo( CClientInfo *pClient, const MM_ClientInfo *pInfo );
|
||||
bool GameIsLocked();
|
||||
bool IsInMigration();
|
||||
bool IsServer();
|
||||
bool ConnectedToServer();
|
||||
|
||||
// Netchannel handling
|
||||
INetChannel *CreateNetChannel( netadr_t *adr );
|
||||
INetChannel *AddRemoteChannel( netadr_t *adr );
|
||||
INetChannel *FindChannel( const unsigned int ip );
|
||||
CClientInfo *FindClient( netadr_t *adr );
|
||||
CClientInfo *FindClientByXUID( XUID xuid );
|
||||
void SetChannelTimeout( netadr_t *adr, int timeout );
|
||||
void RemoveRemoteChannel( netadr_t *adr, const char *pReason );
|
||||
void MarkChannelForRemoval( netadr_t *adr );
|
||||
void CleanupMarkedChannels();
|
||||
|
||||
void UpdateVoiceStatus( void );
|
||||
|
||||
void SetPreventFullServerStartup( bool bState, PRINTF_FORMAT_STRING char const *fmt, ... );
|
||||
|
||||
private:
|
||||
|
||||
// Used by a systemlink host to reply to broadcast searches
|
||||
struct systemLinkInfo_s
|
||||
{
|
||||
char szHostName[MAX_PLAYER_NAME_LENGTH];
|
||||
char szScenario[MAX_MAP_NAME];
|
||||
int gameState;
|
||||
int gameTime;
|
||||
int iScenarioIndex;
|
||||
XUID xuid;
|
||||
XSESSION_SEARCHRESULT Result;
|
||||
};
|
||||
|
||||
hostData_s m_HostData; // pass host info back to searching clients
|
||||
CClientInfo m_Host; // the session host
|
||||
CClientInfo m_Local; // the local client
|
||||
CClientInfo *m_pNewHost; // new host when migrating the session
|
||||
CClientInfo *m_pGameServer; // the client that will act as the game server
|
||||
CUtlVector< CClientInfo* > m_Remote; // remote clients
|
||||
CUtlVector< char* > m_pSystemLinkResults; // results from a system link search
|
||||
XSESSION_SEARCHRESULT_HEADER *m_pSearchResults; // dynamic buffer to hold session search results
|
||||
|
||||
// Arbitration registration
|
||||
XSESSION_REGISTRATION_RESULTS *m_pRegistrationResults;
|
||||
|
||||
// QoS Data
|
||||
BOOL m_bQoSTesting;
|
||||
XNQOS m_QoSResult;
|
||||
XNQOS* m_pQoSResult;
|
||||
const XNADDR* m_QoSxnaddr[MAX_SEARCHRESULTS];
|
||||
const XNKID* m_QoSxnkid[MAX_SEARCHRESULTS];
|
||||
const XNKEY* m_QoSxnkey[MAX_SEARCHRESULTS];
|
||||
|
||||
CUtlMap< unsigned int, INetChannel* >m_Channels;
|
||||
CUtlVector< unsigned int > m_ChannelsToRemove;
|
||||
|
||||
AsyncHandle_t m_hSearchHandle;
|
||||
CSession m_Session;
|
||||
int m_CurrentState;
|
||||
int m_PreMigrateState;
|
||||
double m_fNextHeartbeatTime;
|
||||
double m_fCountdownStartTime;
|
||||
double m_fRegistrationTimer;
|
||||
bool m_bCreatedLocalTalker;
|
||||
bool m_bInitialized;
|
||||
bool m_bCleanup;
|
||||
bool m_bPreventFullServerStartup;
|
||||
bool m_bEnteredLobby;
|
||||
int m_nHostOwnerId;
|
||||
int m_nGameSize;
|
||||
int m_nTotalTeams;
|
||||
int m_nPrivateSlots;
|
||||
int m_nQOSProbeCount;
|
||||
double m_fQOSProbeTimer;
|
||||
int m_nSendCount;
|
||||
double m_fSendTimer;
|
||||
double m_fWaitTimer;
|
||||
double m_fHeartbeatInterval;
|
||||
uint64 m_Nonce; // used in system link queries
|
||||
|
||||
int CountPlayersOnTeam( int idxTeam ); // players on each team
|
||||
|
||||
XUID m_Mutelist[MAX_PLAYERS_PER_CLIENT][MAX_PLAYERS];
|
||||
CUtlVector< XUID > m_MutedBy[MAX_PLAYERS_PER_CLIENT];
|
||||
|
||||
// Contexts and properties
|
||||
CUtlVector< XUSER_CONTEXT > m_SessionContexts; // for session creation
|
||||
CUtlVector< XUSER_PROPERTY > m_SessionProperties; // for session creation
|
||||
CUtlVector< XUSER_PROPERTY > m_PlayerStats;
|
||||
KeyValues *m_pSessionKeys; // for GameUI lobby setup
|
||||
|
||||
double m_flVoiceBlinkTime;
|
||||
|
||||
XSESSION_INFO m_InviteSessionInfo;
|
||||
|
||||
enum InviteState_t
|
||||
{
|
||||
INVITE_NONE,
|
||||
INVITE_PENDING,
|
||||
INVITE_VALIDATING,
|
||||
INVITE_AWAITING_STORAGE,
|
||||
INVITE_ACCEPTING
|
||||
} m_InviteState;
|
||||
|
||||
struct InviteWaitingInfo_t
|
||||
{
|
||||
DWORD m_UserIdx;
|
||||
#if defined( _X360 )
|
||||
XUSER_SIGNIN_INFO m_SignInInfo;
|
||||
#endif
|
||||
DWORD m_SignInState;
|
||||
BOOL m_PrivilegeMultiplayer;
|
||||
int m_InviteStorageDeviceSelected;
|
||||
int m_bAcceptingInvite;
|
||||
} m_InviteWaitingInfo;
|
||||
|
||||
void RunFrameInvite();
|
||||
void InviteCancel();
|
||||
};
|
||||
extern CMatchmaking *g_pMatchmaking;
|
||||
|
||||
#endif // MATCHMAKING_H
|
Reference in New Issue
Block a user