Counter Strike : Global Offensive Source Code
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.

351 lines
9.3 KiB

  1. //===== Copyright � 1996-2009, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "mm_title.h"
  7. #include "mm_title_richpresence.h"
  8. #include "fmtstr.h"
  9. // memdbgon must be the last include file in a .cpp file!!!
  10. #include "tier0/memdbgon.h"
  11. CMatchTitle::CMatchTitle()
  12. {
  13. ;
  14. }
  15. CMatchTitle::~CMatchTitle()
  16. {
  17. ;
  18. }
  19. //
  20. // Init / shutdown
  21. //
  22. InitReturnVal_t CMatchTitle::Init()
  23. {
  24. if ( IGameEventManager2 *mgr = g_pMatchExtensions->GetIGameEventManager2() )
  25. {
  26. mgr->AddListener( this, "server_pre_shutdown", false );
  27. mgr->AddListener( this, "game_newmap", false );
  28. mgr->AddListener( this, "finale_start", false );
  29. mgr->AddListener( this, "round_start", false );
  30. mgr->AddListener( this, "round_end", false );
  31. mgr->AddListener( this, "difficulty_changed", false );
  32. }
  33. return INIT_OK;
  34. }
  35. void CMatchTitle::Shutdown()
  36. {
  37. if ( IGameEventManager2 *mgr = g_pMatchExtensions->GetIGameEventManager2() )
  38. {
  39. mgr->RemoveListener( this );
  40. }
  41. }
  42. //
  43. // Implementation
  44. //
  45. uint64 CMatchTitle::GetTitleID()
  46. {
  47. #ifdef _X360
  48. return 0xFFFFFFFFFFFFFFFF;
  49. #elif !defined( SWDS )
  50. static uint64 uiAppID = 0ull;
  51. if ( !uiAppID && steamapicontext && steamapicontext->SteamUtils() )
  52. {
  53. uiAppID = steamapicontext->SteamUtils()->GetAppID();
  54. }
  55. return uiAppID;
  56. #else
  57. return 0ull;
  58. #endif
  59. }
  60. uint64 CMatchTitle::GetTitleServiceID()
  61. {
  62. #ifdef _X360
  63. return 0x45410880ull; // Left 4 Dead 1 Service ID
  64. #else
  65. return 0ull;
  66. #endif
  67. }
  68. bool CMatchTitle::IsMultiplayer()
  69. {
  70. return true;
  71. }
  72. void CMatchTitle::PrepareNetStartupParams( void *pNetStartupParams )
  73. {
  74. #ifdef _X360
  75. XNetStartupParams &xnsp = *( XNetStartupParams * ) pNetStartupParams;
  76. xnsp.cfgQosDataLimitDiv4 = 64; // 256 bytes
  77. xnsp.cfgSockDefaultRecvBufsizeInK = 64; // Increase receive size for UDP to 64k
  78. xnsp.cfgSockDefaultSendBufsizeInK = 64; // Keep send size at 64k too
  79. int numGamePlayersMax = GetTotalNumPlayersSupported();
  80. int numConnections = 4 * ( numGamePlayersMax - 1 );
  81. // - the max number of connections to members of your game party
  82. // - the max number of connections to members of your social party
  83. // - the max number of connections to a pending game party (if you are joining a new one ).
  84. // - matchmakings client info structure also creates a connection per client for the lobby.
  85. // 1 - the main game session
  86. int numTotalConnections = 1 + numConnections;
  87. // 29 - total Connections (XNADDR/XNKID pairs) ,using 5 sessions (XNKID/XNKEY pairs).
  88. xnsp.cfgKeyRegMax = 16; //adding some extra room because of lazy dealocation of these pairs.
  89. xnsp.cfgSecRegMax = MAX( 64, numTotalConnections ); //adding some extra room because of lazy dealocation of these pairs.
  90. xnsp.cfgSockMaxDgramSockets = xnsp.cfgSecRegMax;
  91. xnsp.cfgSockMaxStreamSockets = xnsp.cfgSecRegMax;
  92. #endif
  93. }
  94. int CMatchTitle::GetTotalNumPlayersSupported()
  95. {
  96. return 1;
  97. }
  98. // Get a guest player name
  99. char const * CMatchTitle::GetGuestPlayerName( int iUserIndex )
  100. {
  101. if ( vgui::ILocalize *pLocalize = g_pMatchExtensions->GetILocalize() )
  102. {
  103. if ( wchar_t* wStringTableEntry = pLocalize->Find( "#L4D360UI_Character_Guest" ) )
  104. {
  105. static char szName[ MAX_PLAYER_NAME_LENGTH ] = {0};
  106. pLocalize->ConvertUnicodeToANSI( wStringTableEntry, szName, ARRAYSIZE( szName ) );
  107. return szName;
  108. }
  109. }
  110. return "";
  111. }
  112. // Sets up all necessary client-side convars and user info before
  113. // connecting to server
  114. void CMatchTitle::PrepareClientForConnect( KeyValues *pSettings )
  115. {
  116. #ifndef SWDS
  117. int numPlayers = 1;
  118. #ifdef _X360
  119. numPlayers = XBX_GetNumGameUsers();
  120. #endif
  121. //
  122. // Now we set the convars
  123. //
  124. for ( int k = 0; k < numPlayers; ++ k )
  125. {
  126. int iController = k;
  127. #ifdef _X360
  128. iController = XBX_GetUserId( k );
  129. #endif
  130. IPlayerLocal *pPlayerLocal = g_pPlayerManager->GetLocalPlayer( iController );
  131. if ( !pPlayerLocal )
  132. continue;
  133. // Set "name"
  134. static SplitScreenConVarRef s_cl_name( "name" );
  135. char const *szName = pPlayerLocal->GetName();
  136. s_cl_name.SetValue( k, szName );
  137. // Set "networkid_force"
  138. if ( IsX360() )
  139. {
  140. static SplitScreenConVarRef s_networkid_force( "networkid_force" );
  141. uint64 xid = pPlayerLocal->GetXUID();
  142. s_networkid_force.SetValue( k, CFmtStr( "%08X:%08X:", uint32( xid >> 32 ), uint32( xid ) ) );
  143. }
  144. }
  145. #endif
  146. }
  147. bool CMatchTitle::StartServerMap( KeyValues *pSettings )
  148. {
  149. int numPlayers = 1;
  150. #ifdef _X360
  151. numPlayers = XBX_GetNumGameUsers();
  152. #endif
  153. char const *szMap = pSettings->GetString( "game/bspname", NULL );
  154. if ( !szMap )
  155. return false;
  156. // Check that we have the server interface and that the map is valid
  157. if ( !g_pMatchExtensions->GetIVEngineServer() )
  158. return false;
  159. if ( !g_pMatchExtensions->GetIVEngineServer()->IsMapValid( szMap ) )
  160. return false;
  161. //
  162. // Prepare game dll reservation package
  163. //
  164. KeyValues *pGameDllReserve = g_pMatchFramework->GetMatchNetworkMsgController()->PackageGameDetailsForReservation( pSettings );
  165. KeyValues::AutoDelete autodelete( pGameDllReserve );
  166. pGameDllReserve->SetString( "map/mapcommand", ( numPlayers <= 1 ) ? "map" : "ss_map" );
  167. if ( !Q_stricmp( "commentary", pSettings->GetString( "options/play", "" ) ) )
  168. pGameDllReserve->SetString( "map/mapcommand", "map_commentary" );
  169. // Run map based off the faked reservation packet
  170. g_pMatchExtensions->GetIServerGameDLL()->ApplyGameSettings( pGameDllReserve );
  171. return true;
  172. }
  173. static KeyValues * GetCurrentMatchSessionSettings()
  174. {
  175. IMatchSession *pIMatchSession = g_pMatchFramework->GetMatchSession();
  176. return pIMatchSession ? pIMatchSession->GetSessionSettings() : NULL;
  177. }
  178. void CMatchTitle::OnEvent( KeyValues *pEvent )
  179. {
  180. char const *szEvent = pEvent->GetName();
  181. if ( !Q_stricmp( "OnPlayerRemoved", szEvent ) ||
  182. !Q_stricmp( "OnPlayerUpdated", szEvent ) )
  183. {
  184. MM_Title_RichPresence_PlayersChanged( GetCurrentMatchSessionSettings() );
  185. }
  186. else if ( !Q_stricmp( "OnMatchSessionUpdate", szEvent ) )
  187. {
  188. if ( !Q_stricmp( pEvent->GetString( "state" ), "updated" ) )
  189. {
  190. if ( KeyValues *kvUpdate = pEvent->FindKey( "update" ) )
  191. {
  192. MM_Title_RichPresence_Update( GetCurrentMatchSessionSettings(), kvUpdate );
  193. }
  194. }
  195. else if ( !Q_stricmp( pEvent->GetString( "state" ), "created" ) ||
  196. !Q_stricmp( pEvent->GetString( "state" ), "ready" ) )
  197. {
  198. MM_Title_RichPresence_Update( GetCurrentMatchSessionSettings(), NULL );
  199. }
  200. else if ( !Q_stricmp( pEvent->GetString( "state" ), "closed" ) )
  201. {
  202. MM_Title_RichPresence_Update( NULL, NULL );
  203. }
  204. }
  205. }
  206. //
  207. //
  208. //
  209. int CMatchTitle::GetEventDebugID( void )
  210. {
  211. return EVENT_DEBUG_ID_INIT;
  212. }
  213. void CMatchTitle::FireGameEvent( IGameEvent *pIGameEvent )
  214. {
  215. // Check if the current match session is on an active game server
  216. IMatchSession *pMatchSession = g_pMatchFramework->GetMatchSession();
  217. if ( !pMatchSession )
  218. return;
  219. KeyValues *pSessionSettings = pMatchSession->GetSessionSettings();
  220. char const *szGameServer = pSessionSettings->GetString( "server/server", "" );
  221. char const *szSystemLock = pSessionSettings->GetString( "system/lock", "" );
  222. if ( ( !szGameServer || !*szGameServer ) &&
  223. ( !szSystemLock || !*szSystemLock ) )
  224. return;
  225. // Also don't run on the client when there's a host
  226. char const *szSessionType = pMatchSession->GetSessionSystemData()->GetString( "type", NULL );
  227. if ( szSessionType && !Q_stricmp( szSessionType, "client" ) )
  228. return;
  229. // Parse the game event
  230. char const *szGameEvent = pIGameEvent->GetName();
  231. if ( !szGameEvent || !*szGameEvent )
  232. return;
  233. if ( !Q_stricmp( "round_start", szGameEvent ) )
  234. {
  235. pMatchSession->UpdateSessionSettings( KeyValues::AutoDeleteInline( KeyValues::FromString(
  236. "update",
  237. " update { "
  238. " game { "
  239. " state game "
  240. " } "
  241. " } "
  242. ) ) );
  243. }
  244. else if ( !Q_stricmp( "finale_start", szGameEvent ) )
  245. {
  246. pMatchSession->UpdateSessionSettings( KeyValues::AutoDeleteInline( KeyValues::FromString(
  247. "update",
  248. " update { "
  249. " game { "
  250. " state finale "
  251. " } "
  252. " } "
  253. ) ) );
  254. }
  255. else if ( !Q_stricmp( "game_newmap", szGameEvent ) )
  256. {
  257. KeyValues *kvUpdate = KeyValues::FromString(
  258. "update",
  259. " update { "
  260. " game { "
  261. " state game "
  262. " } "
  263. " } "
  264. );
  265. KeyValues::AutoDelete autodelete( kvUpdate );
  266. pMatchSession->UpdateSessionSettings( kvUpdate );
  267. }
  268. else if ( !Q_stricmp( "difficulty_changed", szGameEvent ) )
  269. {
  270. char const *szDifficulty = pIGameEvent->GetString( "strDifficulty", "normal" );
  271. KeyValues *kvUpdate = KeyValues::FromString(
  272. "update",
  273. " update { "
  274. " game { "
  275. " difficulty = "
  276. " } "
  277. " } "
  278. );
  279. KeyValues::AutoDelete autodelete( kvUpdate );
  280. kvUpdate->SetString( "update/game/difficulty", szDifficulty );
  281. pMatchSession->UpdateSessionSettings( kvUpdate );
  282. }
  283. else if ( !Q_stricmp( "server_pre_shutdown", szGameEvent ) )
  284. {
  285. char const *szReason = pIGameEvent->GetString( "reason", "quit" );
  286. if ( !Q_stricmp( szReason, "quit" ) )
  287. {
  288. DevMsg( "Received server_pre_shutdown notification - server is shutting down...\n" );
  289. // Transform the server shutdown event into game end event
  290. g_pMatchFramework->GetEventsSubscription()->BroadcastEvent( new KeyValues(
  291. "OnEngineDisconnectReason", "reason", "Server shutting down"
  292. ) );
  293. }
  294. }
  295. }