This commit is contained in:
nephacks
2025-06-04 03:22:50 +02:00
parent f234f23848
commit f12416cffd
14243 changed files with 6446499 additions and 26 deletions

View File

@ -0,0 +1,351 @@
//===== Copyright <20> 1996-2009, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include "mm_title.h"
#include "mm_title_richpresence.h"
#include "fmtstr.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
CMatchTitle::CMatchTitle()
{
;
}
CMatchTitle::~CMatchTitle()
{
;
}
//
// Init / shutdown
//
InitReturnVal_t CMatchTitle::Init()
{
if ( IGameEventManager2 *mgr = g_pMatchExtensions->GetIGameEventManager2() )
{
mgr->AddListener( this, "server_pre_shutdown", false );
mgr->AddListener( this, "game_newmap", false );
mgr->AddListener( this, "finale_start", false );
mgr->AddListener( this, "round_start", false );
mgr->AddListener( this, "round_end", false );
mgr->AddListener( this, "difficulty_changed", false );
}
return INIT_OK;
}
void CMatchTitle::Shutdown()
{
if ( IGameEventManager2 *mgr = g_pMatchExtensions->GetIGameEventManager2() )
{
mgr->RemoveListener( this );
}
}
//
// Implementation
//
uint64 CMatchTitle::GetTitleID()
{
#ifdef _X360
return 0xFFFFFFFFFFFFFFFF;
#elif !defined( SWDS )
static uint64 uiAppID = 0ull;
if ( !uiAppID && steamapicontext && steamapicontext->SteamUtils() )
{
uiAppID = steamapicontext->SteamUtils()->GetAppID();
}
return uiAppID;
#else
return 0ull;
#endif
}
uint64 CMatchTitle::GetTitleServiceID()
{
#ifdef _X360
return 0x45410880ull; // Left 4 Dead 1 Service ID
#else
return 0ull;
#endif
}
bool CMatchTitle::IsMultiplayer()
{
return true;
}
void CMatchTitle::PrepareNetStartupParams( void *pNetStartupParams )
{
#ifdef _X360
XNetStartupParams &xnsp = *( XNetStartupParams * ) pNetStartupParams;
xnsp.cfgQosDataLimitDiv4 = 64; // 256 bytes
xnsp.cfgSockDefaultRecvBufsizeInK = 64; // Increase receive size for UDP to 64k
xnsp.cfgSockDefaultSendBufsizeInK = 64; // Keep send size at 64k too
int numGamePlayersMax = GetTotalNumPlayersSupported();
int numConnections = 4 * ( numGamePlayersMax - 1 );
// - the max number of connections to members of your game party
// - the max number of connections to members of your social party
// - the max number of connections to a pending game party (if you are joining a new one ).
// - matchmakings client info structure also creates a connection per client for the lobby.
// 1 - the main game session
int numTotalConnections = 1 + numConnections;
// 29 - total Connections (XNADDR/XNKID pairs) ,using 5 sessions (XNKID/XNKEY pairs).
xnsp.cfgKeyRegMax = 16; //adding some extra room because of lazy dealocation of these pairs.
xnsp.cfgSecRegMax = MAX( 64, numTotalConnections ); //adding some extra room because of lazy dealocation of these pairs.
xnsp.cfgSockMaxDgramSockets = xnsp.cfgSecRegMax;
xnsp.cfgSockMaxStreamSockets = xnsp.cfgSecRegMax;
#endif
}
int CMatchTitle::GetTotalNumPlayersSupported()
{
return 1;
}
// Get a guest player name
char const * CMatchTitle::GetGuestPlayerName( int iUserIndex )
{
if ( vgui::ILocalize *pLocalize = g_pMatchExtensions->GetILocalize() )
{
if ( wchar_t* wStringTableEntry = pLocalize->Find( "#L4D360UI_Character_Guest" ) )
{
static char szName[ MAX_PLAYER_NAME_LENGTH ] = {0};
pLocalize->ConvertUnicodeToANSI( wStringTableEntry, szName, ARRAYSIZE( szName ) );
return szName;
}
}
return "";
}
// Sets up all necessary client-side convars and user info before
// connecting to server
void CMatchTitle::PrepareClientForConnect( KeyValues *pSettings )
{
#ifndef SWDS
int numPlayers = 1;
#ifdef _X360
numPlayers = XBX_GetNumGameUsers();
#endif
//
// Now we set the convars
//
for ( int k = 0; k < numPlayers; ++ k )
{
int iController = k;
#ifdef _X360
iController = XBX_GetUserId( k );
#endif
IPlayerLocal *pPlayerLocal = g_pPlayerManager->GetLocalPlayer( iController );
if ( !pPlayerLocal )
continue;
// Set "name"
static SplitScreenConVarRef s_cl_name( "name" );
char const *szName = pPlayerLocal->GetName();
s_cl_name.SetValue( k, szName );
// Set "networkid_force"
if ( IsX360() )
{
static SplitScreenConVarRef s_networkid_force( "networkid_force" );
uint64 xid = pPlayerLocal->GetXUID();
s_networkid_force.SetValue( k, CFmtStr( "%08X:%08X:", uint32( xid >> 32 ), uint32( xid ) ) );
}
}
#endif
}
bool CMatchTitle::StartServerMap( KeyValues *pSettings )
{
int numPlayers = 1;
#ifdef _X360
numPlayers = XBX_GetNumGameUsers();
#endif
char const *szMap = pSettings->GetString( "game/bspname", NULL );
if ( !szMap )
return false;
// Check that we have the server interface and that the map is valid
if ( !g_pMatchExtensions->GetIVEngineServer() )
return false;
if ( !g_pMatchExtensions->GetIVEngineServer()->IsMapValid( szMap ) )
return false;
//
// Prepare game dll reservation package
//
KeyValues *pGameDllReserve = g_pMatchFramework->GetMatchNetworkMsgController()->PackageGameDetailsForReservation( pSettings );
KeyValues::AutoDelete autodelete( pGameDllReserve );
pGameDllReserve->SetString( "map/mapcommand", ( numPlayers <= 1 ) ? "map" : "ss_map" );
if ( !Q_stricmp( "commentary", pSettings->GetString( "options/play", "" ) ) )
pGameDllReserve->SetString( "map/mapcommand", "map_commentary" );
// Run map based off the faked reservation packet
g_pMatchExtensions->GetIServerGameDLL()->ApplyGameSettings( pGameDllReserve );
return true;
}
static KeyValues * GetCurrentMatchSessionSettings()
{
IMatchSession *pIMatchSession = g_pMatchFramework->GetMatchSession();
return pIMatchSession ? pIMatchSession->GetSessionSettings() : NULL;
}
void CMatchTitle::OnEvent( KeyValues *pEvent )
{
char const *szEvent = pEvent->GetName();
if ( !Q_stricmp( "OnPlayerRemoved", szEvent ) ||
!Q_stricmp( "OnPlayerUpdated", szEvent ) )
{
MM_Title_RichPresence_PlayersChanged( GetCurrentMatchSessionSettings() );
}
else if ( !Q_stricmp( "OnMatchSessionUpdate", szEvent ) )
{
if ( !Q_stricmp( pEvent->GetString( "state" ), "updated" ) )
{
if ( KeyValues *kvUpdate = pEvent->FindKey( "update" ) )
{
MM_Title_RichPresence_Update( GetCurrentMatchSessionSettings(), kvUpdate );
}
}
else if ( !Q_stricmp( pEvent->GetString( "state" ), "created" ) ||
!Q_stricmp( pEvent->GetString( "state" ), "ready" ) )
{
MM_Title_RichPresence_Update( GetCurrentMatchSessionSettings(), NULL );
}
else if ( !Q_stricmp( pEvent->GetString( "state" ), "closed" ) )
{
MM_Title_RichPresence_Update( NULL, NULL );
}
}
}
//
//
//
int CMatchTitle::GetEventDebugID( void )
{
return EVENT_DEBUG_ID_INIT;
}
void CMatchTitle::FireGameEvent( IGameEvent *pIGameEvent )
{
// Check if the current match session is on an active game server
IMatchSession *pMatchSession = g_pMatchFramework->GetMatchSession();
if ( !pMatchSession )
return;
KeyValues *pSessionSettings = pMatchSession->GetSessionSettings();
char const *szGameServer = pSessionSettings->GetString( "server/server", "" );
char const *szSystemLock = pSessionSettings->GetString( "system/lock", "" );
if ( ( !szGameServer || !*szGameServer ) &&
( !szSystemLock || !*szSystemLock ) )
return;
// Also don't run on the client when there's a host
char const *szSessionType = pMatchSession->GetSessionSystemData()->GetString( "type", NULL );
if ( szSessionType && !Q_stricmp( szSessionType, "client" ) )
return;
// Parse the game event
char const *szGameEvent = pIGameEvent->GetName();
if ( !szGameEvent || !*szGameEvent )
return;
if ( !Q_stricmp( "round_start", szGameEvent ) )
{
pMatchSession->UpdateSessionSettings( KeyValues::AutoDeleteInline( KeyValues::FromString(
"update",
" update { "
" game { "
" state game "
" } "
" } "
) ) );
}
else if ( !Q_stricmp( "finale_start", szGameEvent ) )
{
pMatchSession->UpdateSessionSettings( KeyValues::AutoDeleteInline( KeyValues::FromString(
"update",
" update { "
" game { "
" state finale "
" } "
" } "
) ) );
}
else if ( !Q_stricmp( "game_newmap", szGameEvent ) )
{
KeyValues *kvUpdate = KeyValues::FromString(
"update",
" update { "
" game { "
" state game "
" } "
" } "
);
KeyValues::AutoDelete autodelete( kvUpdate );
pMatchSession->UpdateSessionSettings( kvUpdate );
}
else if ( !Q_stricmp( "difficulty_changed", szGameEvent ) )
{
char const *szDifficulty = pIGameEvent->GetString( "strDifficulty", "normal" );
KeyValues *kvUpdate = KeyValues::FromString(
"update",
" update { "
" game { "
" difficulty = "
" } "
" } "
);
KeyValues::AutoDelete autodelete( kvUpdate );
kvUpdate->SetString( "update/game/difficulty", szDifficulty );
pMatchSession->UpdateSessionSettings( kvUpdate );
}
else if ( !Q_stricmp( "server_pre_shutdown", szGameEvent ) )
{
char const *szReason = pIGameEvent->GetString( "reason", "quit" );
if ( !Q_stricmp( szReason, "quit" ) )
{
DevMsg( "Received server_pre_shutdown notification - server is shutting down...\n" );
// Transform the server shutdown event into game end event
g_pMatchFramework->GetEventsSubscription()->BroadcastEvent( new KeyValues(
"OnEngineDisconnectReason", "reason", "Server shutting down"
) );
}
}
}

View File

@ -0,0 +1,83 @@
//===== Copyright <20> 1996-2009, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#ifndef MM_TITLE_H
#define MM_TITLE_H
#ifdef _WIN32
#pragma once
#endif
#include "../mm_framework.h"
class CMatchTitle :
public IMatchTitle,
public IMatchEventsSink,
public IGameEventListener2
{
// Methods exposed for the framework
public:
virtual InitReturnVal_t Init();
virtual void Shutdown();
// Methods of IMatchTitle
public:
// Title ID
virtual uint64 GetTitleID();
// Service ID for XLSP
virtual uint64 GetTitleServiceID();
// Whether we are a single-player title or multi-player title
virtual bool IsMultiplayer();
// Prepare network startup params for the title
virtual void PrepareNetStartupParams( void *pNetStartupParams );
// Get total number of players supported by the title
virtual int GetTotalNumPlayersSupported();
// Get a guest player name
virtual char const * GetGuestPlayerName( int iUserIndex );
// Decipher title data fields
virtual TitleDataFieldsDescription_t const * DescribeTitleDataStorage();
// Title achievements
virtual TitleAchievementsDescription_t const * DescribeTitleAchievements();
// Title avatar awards
virtual TitleAvatarAwardsDescription_t const * DescribeTitleAvatarAwards();
// Title leaderboards
virtual KeyValues * DescribeTitleLeaderboard( char const *szLeaderboardView );
// Sets up all necessary client-side convars and user info before
// connecting to server
virtual void PrepareClientForConnect( KeyValues *pSettings );
// Start up a listen server with the given settings
virtual bool StartServerMap( KeyValues *pSettings );
// Methods of IMatchEventsSink
public:
virtual void OnEvent( KeyValues *pEvent );
// Methods of IGameEventListener2
public:
// FireEvent is called by EventManager if event just occured
// KeyValue memory will be freed by manager if not needed anymore
virtual void FireGameEvent( IGameEvent *event );
virtual int GetEventDebugID( void );
public:
CMatchTitle();
~CMatchTitle();
};
// Match title singleton
extern CMatchTitle *g_pMatchTitle;
#endif // MM_TITLE_H

View File

@ -0,0 +1,312 @@
//===== Copyright <20> 1996-2009, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include "mm_title.h"
#include "mm_title_richpresence.h"
#include "vstdlib/random.h"
#include "fmtstr.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class CMatchTitleGameSettingsMgr : public IMatchTitleGameSettingsMgr
{
public:
// Extends server game details
virtual void ExtendServerDetails( KeyValues *pDetails, KeyValues *pRequest );
// Adds the essential part of game details to be broadcast
virtual void ExtendLobbyDetailsTemplate( KeyValues *pDetails, char const *szReason, KeyValues *pFullSettings );
// Extends game settings update packet for lobby transition,
// either due to a migration or due to an endgame condition
virtual void ExtendGameSettingsForLobbyTransition( KeyValues *pSettings, KeyValues *pSettingsUpdate, bool bEndGame );
// Rolls up game details for matches grouping
virtual KeyValues * RollupGameDetails( KeyValues *pDetails, KeyValues *pRollup, KeyValues *pQuery );
// Defines session search keys for matchmaking
virtual KeyValues * DefineSessionSearchKeys( KeyValues *pSettings );
// Defines dedicated server search key
virtual KeyValues * DefineDedicatedSearchKeys( KeyValues *pSettings );
// Initializes full game settings from potentially abbreviated game settings
virtual void InitializeGameSettings( KeyValues *pSettings );
// Extends game settings update packet before it gets merged with
// session settings and networked to remote clients
virtual void ExtendGameSettingsUpdateKeys( KeyValues *pSettings, KeyValues *pUpdateDeleteKeys );
// Prepares system for session creation
virtual KeyValues * PrepareForSessionCreate( KeyValues *pSettings );
// Executes the command on the session settings, this function on host
// is allowed to modify Members/Game subkeys and has to fill in modified players KeyValues
// When running on a remote client "ppPlayersUpdated" is NULL and players cannot
// be modified
virtual void ExecuteCommand( KeyValues *pCommand, KeyValues *pSessionSystemData, KeyValues *pSettings, KeyValues **ppPlayersUpdated );
// Prepares the lobby for game or adjust settings of new players who
// join a game in progress, this function is allowed to modify
// Members/Game subkeys and has to fill in modified players KeyValues
virtual void PrepareLobbyForGame( KeyValues *pSettings, KeyValues **ppPlayersUpdated );
// Prepares the host team lobby for game adjusting the game settings
// this function is allowed to prepare modification package to update
// Game subkeys.
// Returns the update/delete package to be applied to session settings
// and pushed to dependent two sesssion of the two teams.
virtual KeyValues * PrepareTeamLinkForGame( KeyValues *pSettingsLocal, KeyValues *pSettingsRemote );
};
CMatchTitleGameSettingsMgr g_MatchTitleGameSettingsMgr;
IMatchTitleGameSettingsMgr *g_pIMatchTitleGameSettingsMgr = &g_MatchTitleGameSettingsMgr;
//
// Implementation of CMatchTitleGameSettingsMgr
//
// Extends server game details
void CMatchTitleGameSettingsMgr::ExtendServerDetails( KeyValues *pDetails, KeyValues *pRequest )
{
// Query server info
INetSupport::ServerInfo_t si;
g_pMatchExtensions->GetINetSupport()->GetServerInfo( &si );
// Server is always in game
pDetails->SetString( "game/state", "game" );
//
// Determine map info
//
{
pDetails->SetString( "game/bspname", CFmtStr( "%s", si.m_szMapName ) );
}
}
// Adds the essential part of game details to be broadcast
void CMatchTitleGameSettingsMgr::ExtendLobbyDetailsTemplate( KeyValues *pDetails, char const *szReason, KeyValues *pFullSettings )
{
static KeyValues *pkvExt = KeyValues::FromString(
"settings",
" game { "
" bspname #empty# "
" } "
);
pDetails->MergeFrom( pkvExt, KeyValues::MERGE_KV_UPDATE );
}
// Extends game settings update packet for lobby transition,
// either due to a migration or due to an endgame condition
void CMatchTitleGameSettingsMgr::ExtendGameSettingsForLobbyTransition( KeyValues *pSettings, KeyValues *pSettingsUpdate, bool bEndGame )
{
pSettingsUpdate->SetString( "game/state", "lobby" );
}
// Rolls up game details for matches grouping
KeyValues * CMatchTitleGameSettingsMgr::RollupGameDetails( KeyValues *pDetails, KeyValues *pRollup, KeyValues *pQuery )
{
return NULL;
}
// Defines dedicated server search key
KeyValues * CMatchTitleGameSettingsMgr::DefineDedicatedSearchKeys( KeyValues *pSettings )
{
if ( IsPC() )
{
static ConVarRef sv_search_key( "sv_search_key" );
KeyValues *pKeys = new KeyValues( "SearchKeys" );
pKeys->SetString( "gametype", CFmtStr( "%s,sv_search_key_%s%d",
"empty",
sv_search_key.GetString(),
g_pMatchExtensions->GetINetSupport()->GetEngineBuildNumber() ) );
return pKeys;
}
else
{
return NULL;
}
}
// Defines session search keys for matchmaking
KeyValues * CMatchTitleGameSettingsMgr::DefineSessionSearchKeys( KeyValues *pSettings )
{
MEM_ALLOC_CREDIT();
KeyValues *pResult = new KeyValues( "SessionSearch" );
pResult->SetInt( "numPlayers", pSettings->GetInt( "members/numPlayers", XBX_GetNumGameUsers() ) );
/*
char const *szGameMode = pSettings->GetString( "game/mode", "" );
if ( IsX360() )
{
if ( char const *szValue = pSettings->GetString( "game/mode", NULL ) )
{
static ContextValue_t values[] = {
{ "versus", SESSION_MATCH_QUERY_PUBLIC_STATE_C___SORT___CHAPTER },
{ "teamversus", SESSION_MATCH_QUERY_TEAM_STATE_C_CHAPTER },
{ "scavenge", SESSION_MATCH_QUERY_PUBLIC_STATE_C_CHAPTER___SORT___ROUNDS },
{ "teamscavenge", SESSION_MATCH_QUERY_TEAM_STATE_C_CHAPTER_ROUNDS },
{ "survival", SESSION_MATCH_QUERY_PUBLIC_STATE_C_CHAPTER },
{ "coop", SESSION_MATCH_QUERY_PUBLIC_STATE_C_DIFF___SORT___CHAPTER },
{ "realism", SESSION_MATCH_QUERY_PUBLIC_STATE_C_DIFF___SORT___CHAPTER },
{ NULL, 0xFFFF },
};
pResult->SetInt( "rule", values->ScanValues( szValue ) );
}
// Set the matchmaking version
pResult->SetInt( CFmtStr( "Properties/%d", PROPERTY_MMVERSION ), mm_matchmaking_version.GetInt() );
#ifdef _X360
// Set the installed DLCs masks
uint64 uiDlcsMask = MatchSession_GetDlcInstalledMask();
for ( int k = 1; k <= mm_matchmaking_dlcsquery.GetInt(); ++ k )
{
pResult->SetInt( CFmtStr( "Properties/%d", PROPERTY_MMVERSION + k ), !!( uiDlcsMask & ( 1ull << k ) ) );
}
pResult->SetInt( "dlc1", PROPERTY_MMVERSION + 1 );
pResult->SetInt( "dlcN", PROPERTY_MMVERSION + mm_matchmaking_dlcsquery.GetInt() );
#endif
// X_CONTEXT_GAME_TYPE
pResult->SetInt( CFmtStr( "Contexts/%d", X_CONTEXT_GAME_TYPE ), X_CONTEXT_GAME_TYPE_STANDARD );
// X_CONTEXT_GAME_MODE
if ( char const *szValue = pSettings->GetString( "game/mode", NULL ) )
{
pResult->SetInt( CFmtStr( "Contexts/%d", X_CONTEXT_GAME_MODE ), g_pcv_CONTEXT_GAME_MODE->ScanValues( szValue ) );
}
if ( char const *szValue = pSettings->GetString( "game/state", NULL ) )
{
pResult->SetInt( CFmtStr( "Contexts/%d", CONTEXT_STATE ), g_pcv_CONTEXT_STATE->ScanValues( szValue ) );
}
if ( char const *szValue = pSettings->GetString( "game/difficulty", NULL ) )
{
if ( !Q_stricmp( "coop", szGameMode ) || !Q_stricmp( "realism", szGameMode ) )
{
pResult->SetInt( CFmtStr( "Contexts/%d", CONTEXT_DIFFICULTY ), g_pcv_CONTEXT_DIFFICULTY->ScanValues( szValue ) );
}
}
if ( int val = pSettings->GetInt( "game/maxrounds" ) )
{
if ( !Q_stricmp( "scavenge", szGameMode ) || !Q_stricmp( "teamscavenge", szGameMode ) )
{
pResult->SetInt( CFmtStr( "Properties/%d", PROPERTY_MAXROUNDS ), val );
}
}
char const *szCampaign = pSettings->GetString( "game/campaign" );
if ( *szCampaign )
{
DWORD dwContext = CONTEXT_CAMPAIGN_UNKNOWN;
if ( KeyValues *pAllMissions = g_pMatchExtL4D->GetAllMissions() )
{
if ( KeyValues *pMission = pAllMissions->FindKey( szCampaign ) )
{
dwContext = pMission->GetInt( "x360ctx", dwContext );
}
}
if ( dwContext != CONTEXT_CAMPAIGN_UNKNOWN )
{
pResult->SetInt( CFmtStr( "Contexts/%d", CONTEXT_CAMPAIGN ), dwContext );
}
}
if ( int val = pSettings->GetInt( "game/chapter" ) )
{
pResult->SetInt( CFmtStr( "Properties/%d", PROPERTY_CHAPTER ), val );
}
}
else
*/
{
if ( char const *szValue = pSettings->GetString( "game/bspname", NULL ) )
{
pResult->SetString( "Filter=/game:bspname", szValue );
}
}
return pResult;
}
// Initializes full game settings from potentially abbreviated game settings
void CMatchTitleGameSettingsMgr::InitializeGameSettings( KeyValues *pSettings )
{
char const *szNetwork = pSettings->GetString( "system/network", "LIVE" );
if ( KeyValues *kv = pSettings->FindKey( "game", true ) )
{
kv->SetString( "state", "lobby" );
}
// Offline games don't need slots and player setup
if ( !Q_stricmp( "offline", szNetwork ) )
return;
//
// Set the number of slots
//
int numSlots = 2;
pSettings->SetInt( "members/numSlots", numSlots );
}
// Extends game settings update packet before it gets merged with
// session settings and networked to remote clients
void CMatchTitleGameSettingsMgr::ExtendGameSettingsUpdateKeys( KeyValues *pSettings, KeyValues *pUpdateDeleteKeys )
{
}
// Prepares system for session creation
KeyValues * CMatchTitleGameSettingsMgr::PrepareForSessionCreate( KeyValues *pSettings )
{
return MM_Title_RichPresence_PrepareForSessionCreate( pSettings );
}
// Prepares the lobby for game or adjust settings of new players who
// join a game in progress, this function is allowed to modify
// Members/Game subkeys and has to write modified players XUIDs
void CMatchTitleGameSettingsMgr::PrepareLobbyForGame( KeyValues *pSettings, KeyValues **ppPlayersUpdated )
{
// set player avatar/teams, etc
}
// Prepares the host team lobby for game adjusting the game settings
// this function is allowed to prepare modification package to update
// Game subkeys.
// Returns the update/delete package to be applied to session settings
// and pushed to dependent two sesssion of the two teams.
KeyValues * CMatchTitleGameSettingsMgr::PrepareTeamLinkForGame( KeyValues *pSettingsLocal, KeyValues *pSettingsRemote )
{
return NULL;
}
// Executes the command on the session settings, this function on host
// is allowed to modify Members/Game subkeys and has to fill in modified players KeyValues
// When running on a remote client "ppPlayersUpdated" is NULL and players cannot
// be modified
void CMatchTitleGameSettingsMgr::ExecuteCommand( KeyValues *pCommand, KeyValues *pSessionSystemData, KeyValues *pSettings, KeyValues **ppPlayersUpdated )
{
//char const *szCommand = pCommand->GetName();
}

View File

@ -0,0 +1,39 @@
//===== Copyright <20> 1996-2009, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include "mm_title.h"
#include "../mm_title_main.h"
#include "fmtstr.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
LINK_MATCHMAKING_LIB();
static CMatchTitle g_MatchTitle;
CMatchTitle *g_pMatchTitle = &g_MatchTitle;
IMatchTitle *g_pIMatchTitle = g_pMatchTitle;
IMatchEventsSink *g_pIMatchTitleEventsSink = g_pMatchTitle;
//
// Init / shutdown
//
InitReturnVal_t MM_Title_Init()
{
return g_pMatchTitle->Init();
}
void MM_Title_Shutdown()
{
if ( g_pMatchTitle )
g_pMatchTitle->Shutdown();
}

View File

@ -0,0 +1,52 @@
//===== Copyright <20> 1996-2009, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include "mm_title_richpresence.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static void SetAllUsersContext( DWORD dwContextId, DWORD dwValue, bool bAsync = true )
{
#ifdef _X360
for ( int k = 0; k < ( int ) XBX_GetNumGameUsers(); ++ k )
{
if ( XBX_GetUserIsGuest( k ) )
continue;
int iCtrlr = XBX_GetUserId( k );
if ( bAsync )
XUserSetContextEx( iCtrlr, dwContextId, dwValue, MMX360_NewOverlappedDormant() );
else
XUserSetContext( iCtrlr, dwContextId, dwValue );
}
#endif
}
static void SetAllUsersProperty( DWORD dwPropertyId, DWORD cbValue, void const *pvValue )
{
#ifdef _X360
for ( int k = 0; k < ( int ) XBX_GetNumGameUsers(); ++ k )
{
if ( XBX_GetUserIsGuest( k ) )
continue;
int iCtrlr = XBX_GetUserId( k );
XUserSetPropertyEx( iCtrlr, dwPropertyId, cbValue, pvValue, MMX360_NewOverlappedDormant() );
}
#endif
}
KeyValues * MM_Title_RichPresence_PrepareForSessionCreate( KeyValues *pSettings )
{
return NULL;
}
void MM_Title_RichPresence_Update( KeyValues *pFullSettings, KeyValues *pUpdatedSettings )
{
}
void MM_Title_RichPresence_PlayersChanged( KeyValues *pFullSettings )
{
}

View File

@ -0,0 +1,20 @@
//===== Copyright <20> 1996-2009, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#ifndef MM_TITLE_RICHPRESENCE_H
#define MM_TITLE_RICHPRESENCE_H
#ifdef _WIN32
#pragma once
#endif
#include "mm_title.h"
void MM_Title_RichPresence_Update( KeyValues *pFullSettings, KeyValues *pUpdatedSettings );
void MM_Title_RichPresence_PlayersChanged( KeyValues *pFullSettings );
KeyValues * MM_Title_RichPresence_PrepareForSessionCreate( KeyValues *pSettings );
#endif // MM_TITLE_H

View File

@ -0,0 +1,113 @@
//===== Copyright <20> 1996-2009, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include "mm_title.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
TitleDataFieldsDescription_t const * CMatchTitle::DescribeTitleDataStorage()
{
#define TD_ENTRY( szName, nTD, eDataType, numBytesOffset ) \
{ szName, TitleDataFieldsDescription_t::nTD, TitleDataFieldsDescription_t::eDataType, numBytesOffset }
static TitleDataFieldsDescription_t tdfd[] =
{
#if 0
TD_ENTRY( "TD1.Easy.Games.Total", DB_TD1, DT_U64, offsetof( TitleData1, mGames[0] ) ),
TD_ENTRY( "TD1.Normal.Games.Total", DB_TD1, DT_U64, offsetof( TitleData1, mGames[1] ) ),
TD_ENTRY( "TD1.Advanced.Games.Total", DB_TD1, DT_U64, offsetof( TitleData1, mGames[2] ) ),
TD_ENTRY( "TD1.Expert.Games.Total", DB_TD1, DT_U64, offsetof( TitleData1, mGames[3] ) ),
#endif
TD_ENTRY( NULL, DB_TD1, DT_U8, 0 )
};
#undef TD_ENTRY
return tdfd;
}
TitleAchievementsDescription_t const * CMatchTitle::DescribeTitleAchievements()
{
static TitleAchievementsDescription_t tad[] =
{
//#include "left4dead2.xhelp.achtitledesc.txt"
// END MARKER
{ NULL, 0 }
};
return tad;
}
TitleAvatarAwardsDescription_t const * CMatchTitle::DescribeTitleAvatarAwards()
{
static TitleAvatarAwardsDescription_t taad[] =
{
//#include "left4dead2.xhelp.avawtitledesc.txt"
// END MARKER
{ NULL, 0 }
};
return taad;
}
// Title leaderboards
KeyValues * CMatchTitle::DescribeTitleLeaderboard( char const *szLeaderboardView )
{
/*
// Check if this is a survival leaderboard
if ( char const *szSurvivalMap = StringAfterPrefix( szLeaderboardView, "survival_" ) )
{
if ( IsX360() )
{
// Find the corresponding record in the mission script
KeyValues *pSettings = new KeyValues( "settings" );
KeyValues::AutoDelete autodelete_pSettings( pSettings );
pSettings->SetString( "game/mode", "survival" );
KeyValues *pMissionInfo = NULL;
KeyValues *pMapInfo = g_pMatchExtL4D->GetMapInfoByBspName( pSettings, szSurvivalMap, &pMissionInfo );
if ( !pMapInfo || !pMissionInfo )
return NULL;
// Find the leaderboard description in the map info
KeyValues *pLbDesc = pMapInfo->FindKey( "x360leaderboard" );
if ( !pLbDesc )
return NULL;
// Insert the required keys
pLbDesc = pLbDesc->MakeCopy();
static KeyValues *s_pRatingKey = KeyValues::FromString( ":rating", // X360 leaderboards are rated
" name besttime " // game name of the rating field is "besttime"
" type uint64 " // type is uint64
" rule max" // rated field must be greater than cached value so that it can be written
);
pLbDesc->AddSubKey( s_pRatingKey->MakeCopy() );
pLbDesc->SetString( "besttime/type", "uint64" );
return pLbDesc;
}
if ( IsPC() )
{
KeyValues *pSettings = KeyValues::FromString( "SteamLeaderboard",
" :score besttime " // :score is the leaderboard value mapped to game name "besttime"
);
pSettings->SetInt( ":sort", k_ELeaderboardSortMethodDescending ); // Sort order when fetching and displaying leaderboard data
pSettings->SetInt( ":format", k_ELeaderboardDisplayTypeTimeMilliSeconds ); // Note: this is actually 1/100th seconds type, Steam change pending
pSettings->SetInt( ":upload", k_ELeaderboardUploadScoreMethodKeepBest ); // Upload method when writing to leaderboard
return pSettings;
}
}
*/
return NULL;
}