Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

539 lines
20 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. #ifndef TF_GC_SERVER_H
  3. #define TF_GC_SERVER_H
  4. #ifdef _WIN32
  5. #pragma once
  6. #endif
  7. #if !defined( _X360 ) && !defined( NO_STEAM )
  8. #include "steam/steam_api.h"
  9. #include "steam/steam_gameserver.h"
  10. #endif
  11. //#include "tf_gc_common.h"
  12. #include "gcsdk/gcclientsdk.h"
  13. #include "playergroup.h"
  14. //#include "dota_gamerules.h"
  15. #include "gc_clientsystem.h"
  16. #include "tf_gcmessages.h"
  17. #include "GameEventListener.h"
  18. #include "rtime.h"
  19. #include "tf_shareddefs.h"
  20. class CTFGSLobby;
  21. class CTFParty;
  22. //enum EDOTA_Uploading_Match_Stats
  23. //{
  24. // EDOTA_MATCH_STATS_IDLE,
  25. // EDOTA_MATCH_STATS_UPLOADING,
  26. // EDOTA_MATCH_STATS_UPLOAD_COMPLETE
  27. //};
  28. #ifdef ENABLE_GC_MATCHMAKING
  29. class CMvMVictoryInfo
  30. {
  31. public:
  32. int m_nLobbyId;
  33. CUtlString m_sChallengeName;
  34. #ifdef USE_MVM_TOUR
  35. CUtlString m_sMannUpTourOfDuty;
  36. #endif // USE_MVM_TOUR
  37. CUtlVector<uint64> m_vPlayerIds;
  38. CUtlVector<bool> m_vSquadSurplus;
  39. RTime32 m_tEventTime;
  40. void Init ( CTFGSLobby *pLobby );
  41. };
  42. class CMatchInfo
  43. {
  44. friend class CTFGCServerSystem;
  45. public:
  46. CMatchInfo( const CTFGSLobby *pLobby );
  47. ~CMatchInfo();
  48. uint64 m_nMatchID;
  49. uint64 m_nLobbyID;
  50. EMatchGroup m_eMatchGroup;
  51. uint32 m_uLobbyFlags;
  52. uint32 m_uAverageRank;
  53. RTime32 m_rtMatchCreated;
  54. uint32 m_unEventTeamStatus;
  55. bool m_bFirstPersonActive;
  56. int m_nBotsAdded;
  57. bool m_bServerCreated;
  58. struct DailyStatsRankBucket_t
  59. {
  60. uint32 nRank;
  61. uint32 nRecords;
  62. uint32 nAvgScore;
  63. uint32 nStDevScore;
  64. uint32 nAvgKills;
  65. uint32 nStDevKills;
  66. uint32 nAvgDamage;
  67. uint32 nStDevDamage;
  68. uint32 nAvgHealing;
  69. uint32 nStDevHealing;
  70. uint32 nAvgSupport;
  71. uint32 nStDevSupport;
  72. };
  73. struct PlayerMatchData_t
  74. {
  75. friend class CTFGCServerSystem;
  76. friend class CMatchInfo;
  77. PlayerMatchData_t( CSteamID steamID, const CTFLobbyMember *pMemberData )
  78. : steamID( steamID )
  79. , uPartyID( pMemberData->party_id() )
  80. , eGCTeam( pMemberData->team() )
  81. , bDropped( false )
  82. , bConnected( false )
  83. , rtJoinedMatch( CRTime::RTime32TimeCur() )
  84. , nVoteKickAttempts( 0 )
  85. , nDisconnectedSeconds( 0 )
  86. , nScoreMedal( 0 )
  87. , nKillsMedal( 0 )
  88. , nDamageMedal( 0 )
  89. , nHealingMedal( 0 )
  90. , nSupportMedal( 0 )
  91. , bLateJoin( false )
  92. , nScore( 0 )
  93. , bPlayed( false )
  94. , unMMSkillRating( 0u )
  95. , nDrilloRatingDelta( 0 )
  96. , unClassesPlayed( 0u )
  97. , rtLastActiveEvent( CRTime::RTime32TimeCur() )
  98. , bAlwaysSafeToLeave( false )
  99. , bEverConnected( false )
  100. , bDropWasAbandon( false )
  101. , eDropReason( TFMatchLeaveReason_UNSPECIFIED )
  102. , nConnectingButNotActiveIndex( 0 )
  103. , m_mapXPAccumulation( DefLessFunc( CMsgTFXPSource::XPSourceType ) )
  104. {}
  105. PlayerMatchData_t( const PlayerMatchData_t& rhs );
  106. CSteamID steamID;
  107. uint64 uPartyID;
  108. TF_GC_TEAM eGCTeam;
  109. // If true, this player was dropped from the match and is not part of the active lobby. This is important for
  110. // cases where the GC connection is lost and the lobby state is stale.
  111. bool bDropped;
  112. bool bConnected;
  113. // Timestamp player joined the match at. Not guaranteed to be the same instant the match was created, depending
  114. // on how the GC does things.
  115. RTime32 rtJoinedMatch;
  116. uint32 nVoteKickAttempts;
  117. // Number of cumulative seconds the player has been absent, *not* including the initial connect timeout. Used
  118. // to determine when to award an abandon. We may do odd things like "comp" you some seconds on a second, later,
  119. // disconnect, so this shouldn't be used for stats purposes.
  120. int nDisconnectedSeconds;
  121. int nScoreMedal;
  122. int nKillsMedal;
  123. int nDamageMedal;
  124. int nHealingMedal;
  125. int nSupportMedal;
  126. bool bLateJoin;
  127. int nScore;
  128. bool bPlayed;
  129. // This is a single-value skill rating given to each player by the GC
  130. uint32 unMMSkillRating;
  131. // This is the older drillo rating system that was done on the server. It is still sent up to the GC as the
  132. // input to the drillo backend there. If we want to keep this long-term it should be moved to be a fully-gc
  133. // backend like glicko
  134. int nDrilloRatingDelta;
  135. uint32 unClassesPlayed;
  136. const CMsgTFXPSourceBreakdown& GetXPSources() const { return m_XPBreakdown; }
  137. // Override releasing this player from obligation to this match beyond the normal abandon rules. Used by MvM mode
  138. // for marking everyone who completes a wave as allowed to drop without penalty, for instance.
  139. void MarkAlwaysSafeToLeave() { bAlwaysSafeToLeave = true; }
  140. bool BDropWasAbandon() { return bDropped && bDropWasAbandon; }
  141. TFMatchLeaveReason GetDropReason() { return bDropped ? eDropReason : TFMatchLeaveReason_UNSPECIFIED; }
  142. RTime32 GetLastActiveEventTime( void ) { return rtLastActiveEvent; }
  143. MM_PlayerConnectionState_t GetConnectionState() const;
  144. void UpdateClassesPlayed( int nClass );
  145. struct XPBonusPool_t
  146. {
  147. XPBonusPool_t()
  148. : m_flMultiplier( 1.f )
  149. , m_nBonusPoolRemaining( 0 )
  150. {}
  151. CMsgTFXPSource_XPSourceType m_eType;
  152. // Only give up to this amount
  153. int m_nBonusPoolRemaining;
  154. // Give at this rate
  155. float m_flMultiplier;
  156. };
  157. private:
  158. void OnConnected( int nEntindex );
  159. void OnActive();
  160. // Last time the player changed between active (fully loaded in) and not-active. A player is active if
  161. // ( bConnected && !nConnectingButNotActiveIndex )
  162. RTime32 rtLastActiveEvent;
  163. bool bAlwaysSafeToLeave;
  164. bool bEverConnected;
  165. // If dropped - was it an abandon and what was the reason.
  166. bool bDropWasAbandon;
  167. TFMatchLeaveReason eDropReason;
  168. // Track the janky source-engine state between ClientConnect (when we allow them in) and ClientActive
  169. int nConnectingButNotActiveIndex;
  170. // XP accumulation for a player
  171. CMsgTFXPSourceBreakdown m_XPBreakdown;
  172. // The breakdown stores ints, but we need float precision or else we're going to round off a
  173. // significant amount of XP as the match plays on.
  174. CUtlMap< CMsgTFXPSource::XPSourceType, float > m_mapXPAccumulation;
  175. CUtlVector< XPBonusPool_t > m_vecXPBonusPools;
  176. };
  177. enum RankStatType_t
  178. {
  179. RankStat_Invalid = -1,
  180. RankStat_Score = 0,
  181. RankStat_Kills,
  182. RankStat_Damage,
  183. RankStat_Healing,
  184. RankStat_Support,
  185. };
  186. void SetDailyRankData( DailyStatsRankBucket_t vecRankData );
  187. bool RequestGCRankData( void );
  188. bool CalculatePlayerMatchRankData( void );
  189. bool CalculateMatchSkillRatingAdjustments( int iWinningTeam );
  190. const CMatchInfo::PlayerMatchData_t* GetMatchDataForPlayer( CSteamID steamID ) const;
  191. CMatchInfo::PlayerMatchData_t* GetMatchDataForPlayer( CSteamID steamID );
  192. // For iterating over all players. Index is relative to GetNumTotalMatchPlayers
  193. CMatchInfo::PlayerMatchData_t* GetMatchDataForPlayer( int nPlayer );
  194. // This is the total number of players we have match data for -- it may include dropped players not part of the
  195. // match any longer.
  196. int GetNumTotalMatchPlayers() const;
  197. // Number of players still active in the match.
  198. int GetNumActiveMatchPlayers() const;
  199. // Number of players still active in the match for a specific team
  200. int GetNumActiveMatchPlayersForTeam( int nTeam ) const;
  201. // Total skill rating for a team
  202. int GetTotalSkillRatingForTeam( int nTeam ) const;
  203. // Subset of active match players who are currently connected
  204. int GetNumConnectedMatchPlayers() const;
  205. // Indicates that this is a stale match that is ending. In cases such as rolling matches, we never "end" a match,
  206. // just roll into the next one, since "ended" matches indicate that we've terminated our relationship with the
  207. // players/GC.
  208. bool BMatchTerminated() const { return m_bMatchEnded; }
  209. // Indicates we've sent a result for this match. The match may still be active if we're intending to use it to start
  210. // a rolling match or other post-game activities.
  211. bool BSentResult() const { return m_bSentResult; }
  212. // The canonical size of this type of match. Can be passed from the GC and override the match description size.
  213. uint32 GetCanonicalMatchSize() const;
  214. const char *GetMatchMap() const { return m_strMapName.Length() ? m_strMapName.Get() : NULL; }
  215. // Rewards the player with XP based on the count scaled by the XP per unit of that type.
  216. // nCount here is the raw occurances of the action (ie. Points scored, Gold Medals Scored)
  217. void GiveXPRewardToPlayerForAction( CSteamID steamID, CMsgTFXPSource::XPSourceType eType, int nCount );
  218. // Directly assign the value
  219. void GiveXPDirectly( CSteamID steamID, CMsgTFXPSource::XPSourceType eType, int nAmount, bool bCanAwardBonusXP = true );
  220. // Give an XP bonus that increases
  221. void GiveXPBonus( CSteamID steamID,
  222. CMsgTFXPSource_XPSourceType eType,
  223. float flMultipler,
  224. int nBonusPool );
  225. // Is this player allowed to leave the match without incurring an abandon right now
  226. // TODO(JohnS): This should not go from true to false due to race conditions (players clicks DC, sees no warning,
  227. // races with server deciding its unsafe again), but does for MvM late join. The GS-initiated late
  228. // join rework would make it possible to fix that (once it enters too-low-to-latejoin state it stays
  229. // there)
  230. bool BPlayerSafeToLeaveMatch( CSteamID steamID );
  231. protected:
  232. int GetRankForStat( RankStatType_t statType, int nRankIndex, uint32 nValue );
  233. float NormalDistributionCDF( float flValue, float flMu, float flSigma );
  234. private:
  235. CMatchInfo();
  236. CMatchInfo( const CMatchInfo &otherinfo );
  237. // Track a new player participating in our match
  238. void AddPlayer( CSteamID steamID, const CTFLobbyMember *pMemberData, bool bIsLateJoin, int nEntindex, bool bActive );
  239. // Or with an existing player to copy from (e.g. old match)
  240. void AddPlayer( const PlayerMatchData_t &oldPlayer, int nEntIndex, bool bActive );
  241. // Mark a player as dropped from the match
  242. void DropPlayer( CSteamID steamID, TFMatchLeaveReason eReason, bool bWasAbandon );
  243. void SetEnded() { m_bMatchEnded = true; }
  244. CUtlVector < DailyStatsRankBucket_t > m_vDailyStatsRankData;
  245. CUtlVector < PlayerMatchData_t* > m_vMatchRankData;
  246. CUtlString m_strMapName;
  247. bool m_bMatchEnded;
  248. bool m_bSentResult;
  249. // Canonical size for this match type, override passed from GC.
  250. uint32 m_nGCMatchSize;
  251. float m_flBronzePercentile;
  252. float m_flSilverPercentile;
  253. float m_flGoldPercentile;
  254. };
  255. class CTFGCServerSystem : public CGCClientSystem, public GCSDK::ISharedObjectListener, public IServerGCLobby, public CGameEventListener
  256. {
  257. DECLARE_CLASS_GAMEROOT( CTFGCServerSystem, CGCClientSystem );
  258. // Messages that need to do callbacks
  259. friend class ReliableMsgNewMatchForLobby;
  260. friend class ReliableMsgChangeMatchPlayerTeams;
  261. public:
  262. CTFGCServerSystem( void );
  263. ~CTFGCServerSystem( void );
  264. // CAutoGameSystemPerFrame
  265. virtual bool Init() OVERRIDE;
  266. virtual void LevelInitPreEntity() OVERRIDE;
  267. virtual void LevelShutdownPostEntity() OVERRIDE;
  268. virtual void Shutdown() OVERRIDE;
  269. virtual void PreClientUpdate() OVERRIDE;
  270. // uint8 FindItemID( CTF_Item *pItem );
  271. void MatchSignOut();
  272. // const char *GetMatchStartTimeString();
  273. // void GameRules_State_Enter( DOTA_GameState newState );
  274. void SetHibernation( bool bHibernating );
  275. bool ShouldHideServer();
  276. // ISharedObjectListener
  277. virtual void SOCreated( const CSteamID & steamIDOwner, const GCSDK::CSharedObject *pObject, GCSDK::ESOCacheEvent eEvent ) OVERRIDE;
  278. virtual void PreSOUpdate( const CSteamID & steamIDOwner, GCSDK::ESOCacheEvent eEvent ) OVERRIDE { /* do nothing */ }
  279. virtual void SOUpdated( const CSteamID & steamIDOwner, const GCSDK::CSharedObject *pObject, GCSDK::ESOCacheEvent eEvent ) OVERRIDE;
  280. virtual void PostSOUpdate( const CSteamID & steamIDOwner, GCSDK::ESOCacheEvent eEvent ) OVERRIDE { /* do nothing */ }
  281. virtual void SODestroyed( const CSteamID & steamIDOwner, const GCSDK::CSharedObject *pObject, GCSDK::ESOCacheEvent eEvent ) OVERRIDE;
  282. virtual void SOCacheSubscribed( const CSteamID & steamIDOwner, GCSDK::ESOCacheEvent eEvent ) OVERRIDE { }
  283. virtual void SOCacheUnsubscribed( const CSteamID & steamIDOwner, GCSDK::ESOCacheEvent eEvent ) OVERRIDE { }
  284. void DumpLobby();
  285. // IServerGCLobby methods
  286. virtual bool HasLobby() const;
  287. virtual bool SteamIDAllowedToConnect(const CSteamID &steamId) const;
  288. virtual void UpdateServerDetails(void);
  289. virtual bool ShouldHibernate();
  290. // IGameEventListener2
  291. virtual void FireGameEvent( IGameEvent *event ) OVERRIDE;
  292. CTFParty* GetPartyForPlayer( CSteamID steamID ) const;
  293. CMatchInfo *GetMatch() { return m_pMatchInfo; }
  294. const CMatchInfo *GetMatch() const { return m_pMatchInfo; }
  295. // Verbose accessor helpers
  296. //
  297. // Get match only if it is live
  298. CMatchInfo *GetLiveMatch() { return ( m_pMatchInfo && !m_pMatchInfo->m_bMatchEnded ) ? m_pMatchInfo : NULL; }
  299. const CMatchInfo *GetLiveMatch() const { return const_cast<CTFGCServerSystem*>(this)->GetLiveMatch(); }
  300. // Get a player only if there is a live match and they are still in the match (not dropped)
  301. CMatchInfo::PlayerMatchData_t *GetLiveMatchPlayer( CSteamID steamID );
  302. const CMatchInfo::PlayerMatchData_t *GetLiveMatchPlayer( CSteamID steamID ) const ;
  303. int GetTeamForLobbyMember( const CSteamID &steamId ) const;
  304. // bool IsLobbyMemberBroadcaster( const CSteamID &steamId ) const;
  305. // ELanguage GetBroadcasterLanguage( const CSteamID &steamId ) const;
  306. float GetFirstConnectTimeForLobbyMember( const CSteamID &steamId ) const;
  307. int GetVoteKickAttemptsByLobbyMember( const CSteamID &steamID ) const;
  308. void IncrementVoteKickAttemptsByLobbyMember( const CSteamID &steamID );
  309. //
  310. // EDOTA_Uploading_Match_Stats UploadingMatchStats() { return m_nUploadingMatchStats; }
  311. // void OnStatsSubmitted( uint32 unMatchID, int32 nReplaySalt );
  312. // uint32 GetLastMatchID() { return m_unLastMatchID; }
  313. // int32 GetLastReplaySalt() { return m_nLastReplaySalt; }
  314. void ClientActive( CSteamID steamIDClient );
  315. void ClientConnected( CSteamID steamIDPlayer, edict_t *pEntity );
  316. void ClientDisconnected( CSteamID steamIDClient );
  317. inline bool IsMMServerModeActive() const { return m_bMMServerMode; }
  318. void MMServerModeChanged();
  319. // void SetRelayedGameServerSteamID( const CSteamID &steamID ) { m_relayedGameServerSteamID = steamID; }
  320. // void SetParentRelayCount( int nParentRelayCount ) { m_nParentRelayCount = nParentRelayCount; }
  321. float GetTimeLastConnectedToGC( void ) { return m_timeLastConnectedToGC; }
  322. void EndManagedMatch( bool bKickPlayersToParties = false );
  323. // Sends match results. Expects the managed match be ended.
  324. /// MvM game rules processing lets us the players have won
  325. void SendMvMVictoryResult();
  326. // Takes ownership of matchResultMsg
  327. void SendCompetitiveMatchResult( GCSDK::CProtoBufMsg< CMsgGC_Match_Result > *matchResultMsg );
  328. // If the GC has confirmed we are in the pool for late joins. GetTimeRequestedLateJoin() can be compared with
  329. // BLateJoinEligible() to reason about delays in the GC making us available for late join.
  330. bool BLateJoinEligible();
  331. double GetTimeRequestedLateJoin() { return m_flTimeRequestedLateJoin; }
  332. // Eject a player from the match, kicking them if they are still present, with given reason.
  333. bool EjectMatchPlayer( CSteamID steamID, TFMatchLeaveReason eReason );
  334. void MatchPlayerVoteKicked( CSteamID steamID );
  335. const MapDef_t* GetNextMapVoteByIndex( int nIndex ) const;
  336. // Changing Match Player Teams
  337. //
  338. // Is game logic allowed to perform team reassignments for this match mode?
  339. bool CanChangeMatchPlayerTeams();
  340. // When game logic changes the team of a match player, this should be called immediately. It is invalid to call this
  341. // if CanChangeMatchPlayerTeams is false.
  342. void ChangeMatchPlayerTeam( CSteamID steamID, TF_GC_TEAM eTeam );
  343. // Multi-player version of the above, less GC traffic when multiple reassignments occur at once.
  344. struct PlayerTeamPair_t { CSteamID steamID; TF_GC_TEAM eTeam; };
  345. template< typename ANY_ALLOCATOR >
  346. void ChangeMatchPlayerTeams( const CUtlVector< PlayerTeamPair_t, ANY_ALLOCATOR > &vecNewTeams );
  347. // Rolling Matches
  348. //
  349. // Some match types let us keep a lobby and roll into a new match. This may not always be allowed depending on GC
  350. // state.
  351. //
  352. // Upon calling RequestNewMatchForLobby, a timer starts, after which the new match is launched in
  353. // LaunchNewMatchForLobby. During this period our match object is the old match, but the lobby may have been updated
  354. // to reflect the new match.
  355. //
  356. // !! Currently if the GC is out of contact, we will speculatively continue with a new match. There are rare cases
  357. // where the GC will return and decline this request, in which case the resulting match will be unofficial and
  358. // not recorded. It should be trivial to add a bool to prevent such speculative matches should it be necessary.
  359. bool CanRequestNewMatchForLobby();
  360. void RequestNewMatchForLobby( const MapDef_t* pNewMap );
  361. // If the match is in a bogus state and has no useful resolution, terminate it and submit a minidump. This usually
  362. // just means reboot the match server.
  363. void AbortInvalidMatchState();
  364. protected:
  365. // CGCClientSystem
  366. virtual void PreInitGC() OVERRIDE;
  367. virtual void PostInitGC() OVERRIDE;
  368. private:
  369. void SendPlayerLeftMatch( CSteamID steamID, TFMatchLeaveReason eReason, bool bAbandoned );
  370. // Send a kick-lobby message for a stale or unexpected lobby
  371. void SendRejectLobby();
  372. // Kick a player that is no longer present in the match and should not be here.
  373. // Returns true if they were present
  374. bool KickRemovedMatchPlayer( CSteamID steamIDClient );
  375. // The lobby object should only be looked at by this class and may be out of date when the GC reboots and similar --
  376. // most users should use the canonical match state in GetMatch()
  377. const CTFGSLobby *GetLobby() const;
  378. CTFGSLobby *GetLobby();
  379. // Accepts a reservation request from the GC, adding this player to our reserved list, and, for MM mode, to the
  380. // match.
  381. void AcceptGCReservation( CSteamID steamID, const CTFLobbyMember *pMemberData, bool bIsLateJoin, int nEntindex, bool bActive );
  382. // Rolling Matches (private)
  383. //
  384. // If we requested a new match for our existing lobby. We don't actually launch the new match for this timer, but
  385. // the GC may get back to us before (or after!) that period, so this tracks that we're not currently in sync with
  386. // our lobby object. See RequestNewMatchForLobby / LaunchNewMatchForLobby and the "Team Assignments" section of the
  387. // big comment at the top of tf_gc_server.cpp
  388. bool BPendingNewMatch() const { return m_flWaitingForNewMatchTime != 0.f; }
  389. // Called at the end of the m_flWaitingForNewMatchTime period to actually create the new match. We could let the
  390. // caller finish the launch process by changing this timer to a bool and making this public.
  391. void LaunchNewMatchForLobby();
  392. // Callbacks from the GC
  393. void ChangeMatchPlayerTeamsResponse( bool bSuccess );
  394. void NewMatchForLobbyResponse( bool bSuccess );
  395. // Static callbacks that are just forwarding to us
  396. static void ChangeMatchPlayerTeamsResponseCallback( GCSDK::CProtoBufMsg<CMsgGCChangeMatchPlayerTeamsResponse>& msg );
  397. static void NewMatchForLobbyResponseCallback( GCSDK::CProtoBufMsg<CMsgGCNewMatchForLobbyResponse>& msg );
  398. bool m_bSetupSchema;
  399. RTime32 m_unGameStartTime;
  400. float m_timeLastSendGameServerInfoAndConnectedPlayers;
  401. ServerMatchmakingState m_eLastGameServerUpdateState;
  402. TF_MatchmakingMode m_eLastGameServerUpdateMatchmakingMode;
  403. CUtlString m_sLastGameServerUpdateMap;
  404. CUtlString m_sLastGameServerUpdateTags;
  405. int m_nLastGameServerUpdateBotCount;
  406. int m_nLastGameServerUpdateMaxHumans;
  407. int m_nLastGameServerUpdateSlotsFree;
  408. uint32 m_nLastGameServerUpdateLobbyMMVersion;
  409. // EDOTA_Uploading_Match_Stats m_nUploadingMatchStats;
  410. // uint32 m_unLastMatchID;
  411. // int32 m_nLastReplaySalt;
  412. CSteamID m_ourSteamID;
  413. CSteamID m_relayedGameServerSteamID;
  414. int m_nParentRelayCount;
  415. bool m_bMMServerMode;
  416. double m_flTimeBecameEmptyWithLobby;
  417. double m_flTimeRequestedLateJoin;
  418. bool m_bLateJoinEligible;
  419. int m_iSavedVisibleMaxPlayers;
  420. bool m_bOverridingVisibleMaxPlayers;
  421. bool m_bWaitingForNewMatchID;
  422. float m_flWaitingForNewMatchTime;
  423. CMvMVictoryInfo m_mvmVictoryInfo;
  424. // Check for match players who have been disconnected for long enough to warrant an abandon and do so.
  425. void MatchPlayerAbandonThink();
  426. void SetMatchPlayerDropped( CSteamID steamID, TFMatchLeaveReason eReason );
  427. void UpdateConnectedPlayersAndServerInfo( CMsgGameServerMatchmakingStatus_Event event, bool bForceSendServerInfo );
  428. CMatchInfo *m_pMatchInfo;
  429. float m_timeLastConnectedToGC;
  430. // DOTAGameVersion m_GameVersion;
  431. };
  432. CTFGCServerSystem *GTFGCClientSystem();
  433. #endif // #ifdef ENABLE_GC_MATCHMAKING
  434. #endif // TF_GC_SERVER_H