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.

247 lines
7.7 KiB

  1. //===== Copyright � 1996-2009, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "mm_title_richpresence.h"
  7. #include "portal2.spa.h"
  8. // memdbgon must be the last include file in a .cpp file!!!
  9. #include "tier0/memdbgon.h"
  10. //
  11. // Mapping of context values
  12. //
  13. ContextValue_t g_pcv_CONTEXT_GAME_MODE[] = {
  14. #define CFG( gamemode ) { #gamemode, CONTEXT_GAME_MODE_##gamemode },
  15. #include "inc_gamemode.inc"
  16. #undef CFG
  17. { NULL, 0xFFFF },
  18. };
  19. struct MpCoopMapRichPresence_t
  20. {
  21. char const *szMapName;
  22. DWORD dwCtxValue;
  23. int idxChapter;
  24. int numChapters;
  25. }
  26. g_pcv_CONTEXT_COOP_PRESENCE_TRACK[] = {
  27. #define CFG( mpcoopmap, ctxval, idx, num ) { #mpcoopmap, ctxval, idx, num },
  28. #include "inc_coop_maps.inc"
  29. #undef CFG
  30. { NULL, 0, 0, 0 },
  31. };
  32. ContextValue_t g_pcv_CONTEXT_SP_PRESENCE_TEXT[] = {
  33. #define CFG( spmapname, chapternum, subchapter ) { #spmapname, CONTEXT_SP_PRESENCE_TEXT_CH##chapternum },
  34. #include "inc_sp_maps.inc"
  35. #undef CFG
  36. { NULL, CONTEXT_SP_PRESENCE_TEXT_DEFAULT },
  37. };
  38. static MpCoopMapRichPresence_t const * FindMpCoopMapRichPresence( char const *szMapName )
  39. {
  40. MpCoopMapRichPresence_t const *p = g_pcv_CONTEXT_COOP_PRESENCE_TRACK;
  41. for ( ; p->szMapName; ++ p )
  42. {
  43. if ( !Q_stricmp( p->szMapName, szMapName ) )
  44. return p;
  45. }
  46. return p;
  47. }
  48. //
  49. // User context and property setting
  50. //
  51. static void SetAllUsersContext( DWORD dwContextId, DWORD dwValue, bool bAsync = true )
  52. {
  53. #ifdef _X360
  54. for ( int k = 0; k < ( int ) XBX_GetNumGameUsers(); ++ k )
  55. {
  56. if ( XBX_GetUserIsGuest( k ) )
  57. continue;
  58. int iCtrlr = XBX_GetUserId( k );
  59. if ( bAsync )
  60. XUserSetContextEx( iCtrlr, dwContextId, dwValue, MMX360_NewOverlappedDormant() );
  61. else
  62. XUserSetContext( iCtrlr, dwContextId, dwValue );
  63. }
  64. #endif
  65. }
  66. static void SetAllUsersProperty( DWORD dwPropertyId, DWORD cbValue, void const *pvValue )
  67. {
  68. #ifdef _X360
  69. for ( int k = 0; k < ( int ) XBX_GetNumGameUsers(); ++ k )
  70. {
  71. if ( XBX_GetUserIsGuest( k ) )
  72. continue;
  73. int iCtrlr = XBX_GetUserId( k );
  74. XUserSetPropertyEx( iCtrlr, dwPropertyId, cbValue, pvValue, MMX360_NewOverlappedDormant() );
  75. }
  76. #endif
  77. }
  78. KeyValues * MM_Title_RichPresence_PrepareForSessionCreate( KeyValues *pSettings )
  79. {
  80. if ( char const *szValue = pSettings->GetString( "game/mode", NULL ) )
  81. {
  82. SetAllUsersContext( X_CONTEXT_GAME_MODE, g_pcv_CONTEXT_GAME_MODE->ScanValues( szValue ), false );
  83. }
  84. // matchmaking version
  85. {
  86. static int val; // must be valid for the async call
  87. extern ConVar mm_matchmaking_version;
  88. val = mm_matchmaking_version.GetInt();
  89. SetAllUsersProperty( PROPERTY_MMVERSION, sizeof( val ), &val );
  90. DevMsg( "PrepareForSessionCreate: matchmaking version %d\n", val );
  91. }
  92. return NULL;
  93. }
  94. void MM_Title_RichPresence_Update( KeyValues *pFullSettings, KeyValues *pUpdatedSettings )
  95. {
  96. if ( !pFullSettings )
  97. {
  98. SetAllUsersContext( X_CONTEXT_PRESENCE, 1 ); // main menu
  99. return;
  100. }
  101. // Also set players information during initial rich presence update
  102. if ( !pUpdatedSettings && pFullSettings )
  103. {
  104. MM_Title_RichPresence_PlayersChanged( pFullSettings );
  105. }
  106. // pUpdatedSettings = NULL when the session is created and all contexts need to be set
  107. KeyValues *pNewSettings = pUpdatedSettings ? pUpdatedSettings : pFullSettings;
  108. if ( char const *szValue = pNewSettings->GetString( "game/mode", NULL ) )
  109. {
  110. SetAllUsersContext( X_CONTEXT_GAME_MODE, g_pcv_CONTEXT_GAME_MODE->ScanValues( szValue ) );
  111. }
  112. if ( KeyValues *kvVal = pNewSettings->FindKey( "game/dlcrequired" ) )
  113. {
  114. static int val[10]; // must be valid for the async call
  115. uint64 uiDlcRequired = kvVal->GetUint64();
  116. extern ConVar mm_matchmaking_dlcsquery;
  117. for ( int k = 1; k <= mm_matchmaking_dlcsquery.GetInt(); ++ k )
  118. {
  119. val[k] = !!( uiDlcRequired & ( 1ull << k ) );
  120. DevMsg( "DLC%d required: %d\n", k, val[k] );
  121. SetAllUsersProperty( PROPERTY_REQUIRED_DLC1 - 1 + k, sizeof( val ), &val );
  122. }
  123. }
  124. //
  125. // Determine Rich Presence Display
  126. //
  127. if ( char const *szGameModeForRichPresence = pFullSettings->GetString( "game/mode", NULL ) )
  128. {
  129. unsigned int dwLevelPresence = CONTEXT_PRESENCE_MAINMENU;
  130. if ( !Q_stricmp( szGameModeForRichPresence, "sp" ) )
  131. {
  132. //
  133. // Game chapter
  134. //
  135. static char s_chLastMapNameSet[128] = {0};
  136. char const *szMap = pFullSettings->GetString( "Game/map" );
  137. if ( Q_stricmp( szMap, s_chLastMapNameSet ) )
  138. {
  139. Q_strncpy( s_chLastMapNameSet, szMap, sizeof( s_chLastMapNameSet ) );
  140. SetAllUsersContext( CONTEXT_SP_PRESENCE_TEXT, g_pcv_CONTEXT_SP_PRESENCE_TEXT->ScanValues( s_chLastMapNameSet ) );
  141. }
  142. dwLevelPresence = CONTEXT_PRESENCE_SP;
  143. }
  144. else if ( !Q_stricmp( szGameModeForRichPresence, "coop" ) || !Q_stricmp( szGameModeForRichPresence, "coop_challenge" ) )
  145. {
  146. //
  147. // Game type: splitscreen / friends /quickmatch
  148. //
  149. DWORD dwGameType = CONTEXT_COOP_PRESENCE_TAGLINE_DEFAULT;
  150. if ( XBX_GetNumGameUsers() > 1 )
  151. dwGameType = CONTEXT_COOP_PRESENCE_TAGLINE_SPLITSCREEN;
  152. else if ( !Q_stricmp( "lan", pFullSettings->GetString( "system/network" ) ) )
  153. dwGameType = CONTEXT_COOP_PRESENCE_TAGLINE_SYSTEMLINK;
  154. else if ( !Q_stricmp( "friends", pFullSettings->GetString( "game/type" ) ) )
  155. dwGameType = CONTEXT_COOP_PRESENCE_TAGLINE_FRIEND;
  156. else if ( !Q_stricmp( "quickmatch", pFullSettings->GetString( "game/type" ) ) )
  157. dwGameType = CONTEXT_COOP_PRESENCE_TAGLINE_QUICKMATCH;
  158. static DWORD s_dwLastGameTypeSet = CONTEXT_COOP_PRESENCE_TAGLINE_DEFAULT;
  159. if ( s_dwLastGameTypeSet != dwGameType )
  160. {
  161. s_dwLastGameTypeSet = dwGameType;
  162. SetAllUsersContext( CONTEXT_COOP_PRESENCE_WAITING, dwGameType );
  163. SetAllUsersContext( CONTEXT_COOP_PRESENCE_TAGLINE, dwGameType );
  164. }
  165. //
  166. // Game track
  167. //
  168. static int nNumChapters = 0;
  169. static int nIdxChapter = 0;
  170. static char s_chLastMapNameSet[128] = {0};
  171. char const *szMap = pFullSettings->GetString( "Game/map" );
  172. if ( Q_stricmp( szMap, s_chLastMapNameSet ) )
  173. {
  174. Q_strncpy( s_chLastMapNameSet, szMap, sizeof( s_chLastMapNameSet ) );
  175. // Determine the track
  176. MpCoopMapRichPresence_t const *pMP = FindMpCoopMapRichPresence( szMap );
  177. SetAllUsersContext( CONTEXT_COOP_PRESENCE_TRACK, pMP->dwCtxValue );
  178. nIdxChapter = pMP->idxChapter;
  179. SetAllUsersProperty( PROPERTY_COOP_TRACK_CHAPTER, sizeof( nIdxChapter ), &nIdxChapter );
  180. nNumChapters = pMP->numChapters;
  181. SetAllUsersProperty( PROPERTY_COOP_TRACK_NUMCHAPTERS, sizeof( nNumChapters ), &nNumChapters );
  182. }
  183. // Presence
  184. if ( !Q_stricmp( "game", pFullSettings->GetString( "game/state" ) ) )
  185. {
  186. dwLevelPresence = ( nNumChapters > 0 ) ? CONTEXT_PRESENCE_COOPGAME_TRACK : CONTEXT_PRESENCE_COOPGAME;
  187. }
  188. else
  189. {
  190. dwLevelPresence = CONTEXT_PRESENCE_COOPMENU;
  191. }
  192. }
  193. SetAllUsersContext( X_CONTEXT_PRESENCE, dwLevelPresence );
  194. }
  195. }
  196. void MM_Title_RichPresence_PlayersChanged( KeyValues *pFullSettings )
  197. {
  198. /*
  199. if ( int numPlayers = pFullSettings->GetInt( "members/numPlayers" ) )
  200. {
  201. static int val; // must be valid for the async call
  202. val = numPlayers;
  203. SetAllUsersProperty( PROPERTY_NUMPLAYERS, sizeof( val ), &val );
  204. }
  205. */
  206. #ifdef _X360
  207. // Set the installed DLCs masks
  208. static int val[10]; // must be valid for the async call
  209. uint64 uiDlcInstalled = g_pMatchFramework->GetMatchSystem()->GetDlcManager()->GetDataInfo()->GetUint64( "@info/installed" );
  210. extern ConVar mm_matchmaking_dlcsquery;
  211. for ( int k = 1; k <= mm_matchmaking_dlcsquery.GetInt(); ++ k )
  212. {
  213. val[k] = !!( uiDlcInstalled & ( 1ull << k ) );
  214. DevMsg( "DLC%d installed: %d\n", k, val[k] );
  215. SetAllUsersProperty( PROPERTY_INSTALLED_DLC1 - 1 + k, sizeof( val[k] ), &val[k] );
  216. }
  217. #endif
  218. }