|
|
//===== Copyright � 1996-2009, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include "mm_framework.h"
#include "mm_netmsgcontroller.h"
#include "matchsystem.h"
#include "mm_title_main.h"
#include "x360_lobbyapi.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// Stress testing events listeners every frame
ConVar mm_events_listeners_validation( "mm_events_listeners_validation", "0", FCVAR_DEVELOPMENTONLY );
//
// Implementation of Steam invite listener
//
uint64 g_uiLastInviteFlags = 0ull; #if !defined( _X360 ) && !defined( NO_STEAM ) && !defined( SWDS )
class CMatchSteamInviteListener { public: void RunFrame(); void Register(); STEAM_CALLBACK_MANUAL( CMatchSteamInviteListener, Steam_OnGameLobbyJoinRequested, GameLobbyJoinRequested_t, m_CallbackOnGameLobbyJoinRequested ); #ifdef _PS3
STEAM_CALLBACK_MANUAL( CMatchSteamInviteListener, Steam_OnPSNGameBootInviteResult, PSNGameBootInviteResult_t, m_CallbackOnPSNGameBootInviteResult ); #endif
protected: GameLobbyJoinRequested_t m_msgPending; } g_MatchSteamInviteListener;
void CMatchSteamInviteListener::Register() { m_CallbackOnGameLobbyJoinRequested.Register( this, &CMatchSteamInviteListener::Steam_OnGameLobbyJoinRequested ); #ifdef _PS3
m_CallbackOnPSNGameBootInviteResult.Register( this, &CMatchSteamInviteListener::Steam_OnPSNGameBootInviteResult ); #endif
} #else
class CMatchSteamInviteListener { public: void RunFrame() {} void Register() {} } g_MatchSteamInviteListener; #endif
//
// Implementation
//
CMatchFramework::CMatchFramework() : m_pMatchSession( NULL ), m_bJoinTeamSession( false ), m_pTeamSessionSettings( NULL ) { }
CMatchFramework::~CMatchFramework() { ; }
InitReturnVal_t CMatchFramework::Init() { InitReturnVal_t ret = INIT_OK;
ret = MM_Title_Init(); if ( ret != INIT_OK ) return ret;
g_MatchSteamInviteListener.Register();
return INIT_OK; }
void CMatchFramework::Shutdown() { // Shutdown event system
g_pMatchEventsSubscription->Shutdown();
// Shutdown the title
MM_Title_Shutdown();
// Cancel any pending server updates before shutdown
g_pServerManager->EnableServersUpdate( false );
// Cancel any pending datacenter queries
g_pDatacenter->EnableUpdate( false ); }
void CMatchFramework::RunFrame() { // Run frame listeners validation if requested
if ( mm_events_listeners_validation.GetBool() ) { g_pMatchEventsSubscription->BroadcastEvent( new KeyValues( "mm_events_listeners_validation" ) ); }
#ifdef _X360
if ( IXOnline *pIXOnline = g_pMatchExtensions->GetIXOnline() ) pIXOnline->RunFrame();
MMX360_UpdateDormantOperations();
SysSession360_UpdatePending(); #endif
RunFrame_Invite(); g_MatchSteamInviteListener.RunFrame();
#ifdef _X360
// Pump rate adjustments
MatchSession_RateAdjustmentUpdate(); #endif
// Let the network mgr run
g_pConnectionlessLanMgr->Update();
// Let the matchsystem run
g_pMatchSystem->Update();
// Let the match session run
if ( m_pMatchSession ) m_pMatchSession->Update();
// Let the match title run frame
g_pIMatchTitle->RunFrame();
if ( m_bJoinTeamSession ) { m_bJoinTeamSession = false; MatchSession( m_pTeamSessionSettings ); m_pTeamSessionSettings->deleteThis(); m_pTeamSessionSettings = NULL; } }
IMatchExtensions * CMatchFramework::GetMatchExtensions() { return g_pMatchExtensions; }
IMatchEventsSubscription * CMatchFramework::GetEventsSubscription() { return g_pMatchEventsSubscription; }
IMatchTitle * CMatchFramework::GetMatchTitle() { return g_pIMatchTitle; }
IMatchTitleGameSettingsMgr * CMatchFramework::GetMatchTitleGameSettingsMgr() { return g_pIMatchTitleGameSettingsMgr; }
IMatchNetworkMsgController * CMatchFramework::GetMatchNetworkMsgController() { return g_pMatchNetMsgControllerBase; }
IMatchSystem * CMatchFramework::GetMatchSystem() { return g_pMatchSystem; }
void CMatchFramework::ApplySettings( KeyValues* keyValues ) { g_pMatchExtensions->GetIServerGameDLL()->ApplyGameSettings( keyValues ); }
#ifdef _X360
static XINVITE_INFO s_InviteInfo; #else
static uint64 s_InviteInfo; #endif
static bool s_bInviteSessionDelayedJoin; static int s_nInviteConfirmed;
template < int datasize > static bool IsZeroData( void const *pvData ) { static char s_zerodata[ datasize ]; return !memcmp( s_zerodata, pvData, datasize ); }
static bool ValidateInviteController( int iController ) { #ifdef _X360
XUSER_SIGNIN_STATE eSignInState = XUserGetSigninState( iController ); XUSER_SIGNIN_INFO xsi = {0}; if ( ( eSignInState != eXUserSigninState_SignedInToLive ) || ( ERROR_SUCCESS != XUserGetSigninInfo( iController, XUSER_GET_SIGNIN_INFO_ONLINE_XUID_ONLY, &xsi ) ) || ! ( xsi.dwInfoFlags & XUSER_INFO_FLAG_LIVE_ENABLED ) ) { DevWarning( "ValidateInviteController: ctrl%d check1 failed (state=%d, flags=0x%X, xuid=%llx)!\n", eSignInState, xsi.dwInfoFlags, xsi.xuid ); if ( KeyValues *notify = new KeyValues( "OnInvite", "action", "error", "error", "NotOnline" ) ) { notify->SetInt( "user", iController ); g_pMatchEventsSubscription->BroadcastEvent( notify ); } return false; }
BOOL bMultiplayer = FALSE; if ( ( ERROR_SUCCESS != XUserCheckPrivilege( iController, XPRIVILEGE_MULTIPLAYER_SESSIONS, &bMultiplayer ) ) || ( !bMultiplayer ) ) { DevWarning( "ValidateInviteController: ctrl%d check2 failed (state=%d, flags=0x%X, xuid=%llx) - on multiplayer priv!\n", eSignInState, xsi.dwInfoFlags, xsi.xuid );
if ( KeyValues *notify = new KeyValues( "OnInvite", "action", "error", "error", "NoMultiplayer" ) ) { notify->SetInt( "user", iController ); g_pMatchEventsSubscription->BroadcastEvent( notify ); }
return false; } #endif
return true; }
static bool ValidateInviteControllers() { for ( DWORD k = 0; k < XBX_GetNumGameUsers(); ++ k ) { if ( !ValidateInviteController( XBX_GetUserId( k ) ) ) return false; } return true; }
static bool VerifyInviteEligibility() { #ifdef _X360
// Make sure that the inviter is not signed in
for ( int k = 0; k < XUSER_MAX_COUNT; ++ k ) { XUID xuid; if ( ERROR_SUCCESS == XUserGetXUID( k, &xuid ) && xuid == s_InviteInfo.xuidInviter ) { g_pMatchEventsSubscription->BroadcastEvent( new KeyValues( "OnInvite", "action", "error", "error", "SameConsole" ) ); return false; } }
// Check if the user is currently inactive
bool bExistingUser = false; for ( DWORD k = 0; k < XBX_GetNumGameUsers(); ++ k ) { if ( XBX_GetInvitedUserId() == (DWORD) XBX_GetUserId( k ) && !XBX_GetUserIsGuest( k ) ) { bExistingUser = true; break; } }
// Check if this is the existing user that the invite is for a different session
// than the session they are currently in (e.g. they are in a lobby and do
// "Join Party and Game" with another user who is in the same lobby)
char chInviteSessionInfo[ XSESSION_INFO_STRING_LENGTH ] = {0}; MMX360_SessionInfoToString( s_InviteInfo.hostInfo, chInviteSessionInfo ); if ( IMatchSession *pIMatchSession = g_pMatchFramework->GetMatchSession() ) { bool bJoinable = ( ( IMatchSessionInternal * ) pIMatchSession )->IsAnotherSessionJoinable( chInviteSessionInfo ); if ( !bJoinable && bExistingUser ) { Warning( "VerifyInviteEligibility: declined invite due to local session!\n" ); return false; } }
// New user is eligible since otherwise he shouldn't be able to accept an invite
if ( !bExistingUser || ( XBX_GetNumGameUsers() < 2 ) || ( g_pMMF->GetMatchTitle()->GetTitleSettingsFlags() & MATCHTITLE_INVITE_ONLY_SINGLE_USER ) ) { if ( !ValidateInviteController( XBX_GetInvitedUserId() ) ) return false; else return true; } #endif
// Check that every user is valid
return ValidateInviteControllers(); }
static void JoinInviteSession() { s_bInviteSessionDelayedJoin = false;
#ifdef _X360
if ( 0ull == ( uint64 const & ) s_InviteInfo.hostInfo.sessionID ) #else
if ( !s_InviteInfo ) #endif
return; if ( g_pMatchExtensions->GetIVEngineClient()->IsDrawingLoadingImage() ) { s_bInviteSessionDelayedJoin = true; return; }
// Invites cannot be accepted from inside an event broadcast
// internally used events must be top-level events since they
// operate on signed in / active users, trigger playermanager,
// account access and other events
// Wait until next frame in such case
if ( g_pMatchEventsSubscription && g_pMatchEventsSubscription->IsBroacasting() ) { s_bInviteSessionDelayedJoin = true; return; }
#if !defined( NO_STEAM ) && !defined( _GAMECONSOLE ) && !defined( SWDS )
extern bool g_bSteamStatsReceived; if ( !g_bSteamStatsReceived && ( g_uiLastInviteFlags & MM_INVITE_FLAG_PCBOOT ) ) { s_bInviteSessionDelayedJoin = true; return; } #endif
#ifdef _X360
DevMsg( "JoinInviteSession: sessionid = %llx, xuid = %llx\n", ( uint64 const & ) s_InviteInfo.hostInfo.sessionID, s_InviteInfo.xuidInvitee ); #else
DevMsg( "JoinInviteSession: sessionid = %llx\n", s_InviteInfo ); #endif
//
// Validate the user accepting the invite
//
#ifdef _GAMECONSOLE
if ( XBX_GetInvitedUserId() == INVALID_USER_ID ) { DevWarning( "JoinInviteSession: no invited user!\n" ); return; } #endif
#ifdef _X360
XUSER_SIGNIN_STATE eSignInState = XUserGetSigninState( XBX_GetInvitedUserId() ); XUSER_SIGNIN_INFO xsi = {0}; if ( ( eSignInState != eXUserSigninState_SignedInToLive ) || ( ERROR_SUCCESS != XUserGetSigninInfo( XBX_GetInvitedUserId(), XUSER_GET_SIGNIN_INFO_ONLINE_XUID_ONLY, &xsi ) ) || ! ( xsi.dwInfoFlags & XUSER_INFO_FLAG_LIVE_ENABLED ) || ( xsi.dwInfoFlags & XUSER_INFO_FLAG_GUEST ) || !IsEqualXUID( xsi.xuid, s_InviteInfo.xuidInvitee ) ) { DevWarning( "JoinInviteSession: invited user signin information validation failed (state=%d, flags=0x%X, xuid=%llx)!\n", eSignInState, xsi.dwInfoFlags, xsi.xuid ); return; } BOOL bMultiplayer = FALSE; if ( ( ERROR_SUCCESS != XUserCheckPrivilege( XBX_GetInvitedUserId(), XPRIVILEGE_MULTIPLAYER_SESSIONS, &bMultiplayer ) ) || ( !bMultiplayer ) ) { DevWarning( "JoinInviteSession: no multiplayer priv!\n" ); return; } #endif
//
// Check if the currently-involved user is accepting the invite
//
#ifdef _GAMECONSOLE
bool bExistingUser = false; for ( DWORD k = 0; k < XBX_GetNumGameUsers(); ++ k ) { if ( XBX_GetInvitedUserId() == (DWORD) XBX_GetUserId( k ) && !XBX_GetUserIsGuest( k ) ) { bExistingUser = true; break; } } if ( !bExistingUser || ( ( XBX_GetNumGameUsers() > 1 ) && ( g_pMMF->GetMatchTitle()->GetTitleSettingsFlags() & MATCHTITLE_INVITE_ONLY_SINGLE_USER ) ) ) { // Another controller is accepting the invite or guest status
// has changed.
// then we need to reset all our XBX core state:
DevMsg( "JoinInviteSession: activating inactive controller%d\n", XBX_GetInvitedUserId() );
g_pMatchEventsSubscription->BroadcastEvent( new KeyValues( "OnProfilesWriteOpportunity", "reason", "deactivation" ) );
XBX_ClearUserIdSlots();
XBX_SetPrimaryUserId( XBX_GetInvitedUserId() ); XBX_SetPrimaryUserIsGuest( 0 );
XBX_SetUserId( 0, XBX_GetInvitedUserId() ); XBX_SetUserIsGuest( 0, 0 );
XBX_SetNumGameUsers( 1 ); g_pMatchEventsSubscription->BroadcastEvent( new KeyValues( "OnProfilesChanged", "numProfiles", int(1) ) );
IPlayerLocal *pPlayer = g_pPlayerManager->GetLocalPlayer( XBX_GetPrimaryUserId() ); if ( !pPlayer ) { g_pMatchEventsSubscription->BroadcastEvent( new KeyValues( "OnInvite", "action", "error", "error", "" ) ); return; } ( ( PlayerLocal * ) pPlayer )->SetFlag_AwaitingTitleData();
// Since we have activated a new profile, we need to wait until title data gets loaded
DevMsg( "JoinInviteSession: activated inactive controller%d, waiting for title data...\n", XBX_GetInvitedUserId() ); return; } #endif
// Validate storage device
s_nInviteConfirmed = -1; if ( KeyValues *notify = new KeyValues( "OnInvite" ) ) { #ifdef _X360
char chSessionInfo[ XSESSION_INFO_STRING_LENGTH ] = {0}; MMX360_SessionInfoToString( s_InviteInfo.hostInfo, chSessionInfo ); notify->SetInt( "user", XBX_GetInvitedUserId() ); notify->SetString( "sessioninfo", chSessionInfo ); #else
notify->SetUint64( "sessionid", s_InviteInfo ); #endif
notify->SetString( "action", "storage" ); notify->SetPtr( "confirmed", &s_nInviteConfirmed );
g_pMatchEventsSubscription->BroadcastEvent( notify );
// If handlers decided they need to confirm storage devices, etc.
if ( s_nInviteConfirmed != -1 ) { DevMsg( "JoinInviteSession: waiting for storage device selection...\n" ); return; } }
// Verify eligibility
DevMsg( "JoinInviteSession: verifying eligibility...\n" ); if ( !VerifyInviteEligibility() ) return; DevMsg( "JoinInviteSession: connecting...\n" );
//
// Argument validation
//
#ifdef _GAMECONSOLE
Assert( XBX_GetInvitedUserId() >= 0 ); Assert( XBX_GetInvitedUserId() < XUSER_MAX_COUNT ); Assert( XBX_GetSlotByUserId( XBX_GetInvitedUserId() ) < ( int ) XBX_GetNumGameUsers() ); Assert( XBX_GetNumGameUsers() < MAX_SPLITSCREEN_CLIENTS ); #endif
// Requesting to join the stored off session
KeyValues *pSettings = KeyValues::FromString( "settings", " system { " " network LIVE " " } " " options { " " action joinsession " " } " ); #ifdef _X360
pSettings->SetUint64( "options/sessionid", ( const uint64 & ) s_InviteInfo.hostInfo.sessionID );
if ( !IsZeroData< sizeof( s_InviteInfo.hostInfo.keyExchangeKey ) >( &s_InviteInfo.hostInfo.keyExchangeKey ) ) { // Missing sessioninfo will cause the session info to be discovered during session
// creation time
char chSessionInfoBuffer[ XSESSION_INFO_STRING_LENGTH ] = {0}; MMX360_SessionInfoToString( s_InviteInfo.hostInfo, chSessionInfoBuffer ); pSettings->SetString( "options/sessioninfo", chSessionInfoBuffer ); } #else
pSettings->SetUint64( "options/sessionid", s_InviteInfo ); #endif
KeyValues::AutoDelete autodelete( pSettings ); Q_memset( &s_InviteInfo, 0, sizeof( s_InviteInfo ) );
g_pMatchFramework->MatchSession( pSettings ); }
static void OnInviteAccepted() { // Verify eligibility
DevMsg( "OnInviteAccepted: verifying eligibility...\n" ); if ( !VerifyInviteEligibility() ) return; DevMsg( "OnInviteAccepted: confirming...\n" );
// Make sure the user confirms the invite
s_nInviteConfirmed = -1; if ( KeyValues *notify = new KeyValues( "OnInvite" ) ) { #ifdef _X360
char chSessionInfo[ XSESSION_INFO_STRING_LENGTH ] = {0}; MMX360_SessionInfoToString( s_InviteInfo.hostInfo, chSessionInfo ); notify->SetInt( "user", XBX_GetInvitedUserId() ); notify->SetString( "sessioninfo", chSessionInfo ); #else
notify->SetUint64( "sessionid", s_InviteInfo ); #endif
notify->SetString( "action", "accepted" ); notify->SetPtr( "confirmed", &s_nInviteConfirmed );
g_pMatchEventsSubscription->BroadcastEvent( notify );
// If handlers decided they need to confirm destructive actions or
// select storage devices, etc.
if ( s_nInviteConfirmed != -1 ) { DevMsg( "OnInviteAccepted: waiting for confirmation...\n" ); return; } } DevMsg( "OnInviteAccepted: accepting...\n" );
// Otherwise, launch depending on our current MOD
// if ( !Q_stricmp( GetCurrentMod(), "left4dead2" ) ) <-- for multi-game package
{ // Kick off our join
JoinInviteSession(); } // else <-- for multi-game package supporting cross-game invites
// {
// // Save off our session ID for later retrieval
// // NOTE: We may need to actually save off the inviter's XID and search for them later on if we took too long or the
// // session they were a part of went away
//
// XBX_SetInviteSessionId( inviteInfo.hostInfo.sessionID );
//
// // Quit via the menu path "QuitNoConfirm"
// EngineVGui()->SystemNotification( SYSTEMNOTIFY_INVITE_SHUTDOWN, NULL );
// }
}
void CMatchFramework::RunFrame_Invite() { if ( s_bInviteSessionDelayedJoin ) JoinInviteSession(); }
void CMatchFramework::AcceptInvite( int iController ) { #ifdef _X360
s_bInviteSessionDelayedJoin = false;
// Grab our invite info
DWORD dwError = g_pMatchExtensions->GetIXOnline()->XInviteGetAcceptedInfo( iController, &s_InviteInfo ); if ( dwError != ERROR_SUCCESS ) { ZeroMemory( &s_InviteInfo, sizeof( s_InviteInfo ) ); return; }
// We only care if we're asked to join this title's session
if ( s_InviteInfo.dwTitleID != GetMatchTitle()->GetTitleID() ) { ZeroMemory( &s_InviteInfo, sizeof( s_InviteInfo ) ); return; }
// We just mark the invited user and let the matchmaking handle profile changes
XBX_SetInvitedUserId( iController );
// Invite accepted logic after globals have been setup
OnInviteAccepted(); #endif
}
#if !defined( _X360 ) && !defined( NO_STEAM ) && !defined( SWDS )
void CMatchSteamInviteListener::Steam_OnGameLobbyJoinRequested( GameLobbyJoinRequested_t *pJoinInvite ) { #ifdef _PS3
if ( pJoinInvite->m_steamIDFriend.ConvertToUint64() != ~0ull ) { g_uiLastInviteFlags = ( pJoinInvite->m_steamIDFriend.BConsoleUserAccount() ? MM_INVITE_FLAG_CONSOLE : 0 ); } #endif
#if !defined( _GAMECONSOLE )
g_uiLastInviteFlags = ( pJoinInvite->m_steamIDFriend.ConvertToUint64() == ~0ull ) ? MM_INVITE_FLAG_PCBOOT : 0; #endif
m_msgPending = GameLobbyJoinRequested_t(); s_bInviteSessionDelayedJoin = false; s_InviteInfo = pJoinInvite->m_steamIDLobby.ConvertToUint64(); if ( !s_InviteInfo ) return; #ifdef _GAMECONSOLE
// We just mark the invited user and let the matchmaking handle profile changes
XBX_SetInvitedUserId( XBX_GetPrimaryUserId() ); #endif
// Whether we have to make invite go pending
char chBuffer[2] = {}; if ( g_pMatchExtensions->GetIVEngineClient()->IsDrawingLoadingImage() || ( g_pMatchEventsSubscription && g_pMatchEventsSubscription->IsBroacasting() ) || ( g_pMatchExtensions->GetIBaseClientDLL()->GetStatus( chBuffer, 2 ), ( chBuffer[0] != '+' ) ) ) { m_msgPending = *pJoinInvite; return; }
// Invite accepted logic after globals have been setup
OnInviteAccepted(); }
#ifdef _PS3
void CMatchSteamInviteListener::Steam_OnPSNGameBootInviteResult( PSNGameBootInviteResult_t *pParam ) { if ( pParam->m_bGameBootInviteExists && pParam->m_steamIDLobby.IsValid() ) { g_uiLastInviteFlags = MM_INVITE_FLAG_CONSOLE; } } #endif
void CMatchSteamInviteListener::RunFrame() { if ( m_msgPending.m_steamIDLobby.IsValid() ) { GameLobbyJoinRequested_t msgRequest = m_msgPending; Steam_OnGameLobbyJoinRequested( &msgRequest ); } } #endif
IMatchSession *CMatchFramework::GetMatchSession() { return m_pMatchSession; }
void CMatchFramework::CreateSession( KeyValues *pSettings ) { DevMsg( "CreateSession: \n"); KeyValuesDumpAsDevMsg( pSettings );
#ifndef SWDS
if ( !pSettings ) return;
IMatchSessionInternal *pMatchSessionNew = NULL;
//
// Analyze the type of session requested to create
//
char const *szNetwork = pSettings->GetString( "system/network", "offline" );
#ifdef _X360
if ( !Q_stricmp( "LIVE", szNetwork ) && !ValidateInviteControllers() ) return; #endif
// Recompute XUIDs for the session type that we are creating
g_pPlayerManager->RecomputePlayerXUIDs( szNetwork );
//
// Process create session request
//
if ( !Q_stricmp( "offline", szNetwork ) ) { CMatchSessionOfflineCustom *pSession = new CMatchSessionOfflineCustom( pSettings ); pMatchSessionNew = pSession; } else { CMatchSessionOnlineHost *pSession = new CMatchSessionOnlineHost( pSettings ); pMatchSessionNew = pSession; }
if ( pMatchSessionNew ) { CloseSession(); m_pMatchSession = pMatchSessionNew; } #endif
}
void CMatchFramework::MatchSession( KeyValues *pSettings ) { #ifndef SWDS
if ( !pSettings ) return;
DevMsg( "MatchSession: \n"); KeyValuesDumpAsDevMsg( pSettings );
IMatchSessionInternal *pMatchSessionNew = NULL;
//
// Analyze what kind of client-side matchmaking
// needs to happen.
//
char const *szNetwork = pSettings->GetString( "system/network", "LIVE" ); char const *szAction = pSettings->GetString( "options/action", "" );
// Recompute XUIDs for the session type that we are creating
g_pPlayerManager->RecomputePlayerXUIDs( szNetwork );
//
// Process match session request
//
if ( !Q_stricmp( "joinsession", szAction ) ) { #ifdef _X360
// For LIVE sessions we need to be eligible
if ( !Q_stricmp( "LIVE", szNetwork ) && !ValidateInviteControllers() ) return; #endif
// We have an explicit session to join
CMatchSessionOnlineClient *pSession = new CMatchSessionOnlineClient( pSettings ); pMatchSessionNew = pSession; } else if ( !Q_stricmp( "joininvitesession", szAction ) ) { #ifdef _X360
ZeroMemory( &s_InviteInfo, sizeof( s_InviteInfo ) ); XUSER_SIGNIN_INFO xsi; if ( ERROR_SUCCESS == XUserGetSigninInfo( XBX_GetInvitedUserId(), XUSER_GET_SIGNIN_INFO_ONLINE_XUID_ONLY, &xsi ) ) s_InviteInfo.xuidInvitee = xsi.xuid;
uint64 uiSessionID = pSettings->GetUint64( "options/sessionid", 0ull ); s_InviteInfo.hostInfo.sessionID = ( XNKID & ) uiSessionID;
OnInviteAccepted(); #endif
} else // "quickmatch" or "custommatch"
{ #ifdef _X360
// For LIVE sessions we need to be eligible
if ( !Q_stricmp( "LIVE", szNetwork ) && !ValidateInviteControllers() ) return; #endif
CMatchSessionOnlineSearch *pSession = new CMatchSessionOnlineSearch( pSettings ); pMatchSessionNew = pSession; }
if ( pMatchSessionNew ) { CloseSession(); m_pMatchSession = pMatchSessionNew; } #endif
}
void CMatchFramework::CloseSession() { // Destroy the session
if ( m_pMatchSession ) { IMatchSessionInternal *pMatchSession = m_pMatchSession; m_pMatchSession = NULL; pMatchSession->Destroy();
g_pMatchEventsSubscription->BroadcastEvent( new KeyValues( "OnMatchSessionUpdate", "state", "closed" ) ); } }
bool CMatchFramework::IsOnlineGame( void ) { IMatchSession *pMatchSession = GetMatchSession();
if ( pMatchSession ) { KeyValues* kv = pMatchSession->GetSessionSettings(); if ( kv ) { char const *szMode = kv->GetString( "system/network", NULL ); if ( szMode && !V_stricmp( "LIVE", szMode ) ) { return true; } } } return false; }
void CMatchFramework::UpdateTeamProperties( KeyValues *pTeamProperties ) { IMatchSession *pMatchSession = GetMatchSession(); IMatchTitleGameSettingsMgr *pMatchTitleGameSettingsMgr = GetMatchTitleGameSettingsMgr();
if ( pMatchSession && pMatchTitleGameSettingsMgr ) { pMatchSession->UpdateTeamProperties( pTeamProperties ); KeyValues *pCurrentSettings = pMatchSession->GetSessionSettings(); pMatchTitleGameSettingsMgr->UpdateTeamProperties( pCurrentSettings, pTeamProperties ); } }
void CMatchFramework::OnEvent( KeyValues *pEvent ) { char const *szEvent = pEvent->GetName();
if ( !Q_stricmp( "mmF->CloseSession", szEvent ) ) { CloseSession(); return; } else if ( !Q_stricmp( "OnInvite", szEvent ) ) { if ( !Q_stricmp( "join", pEvent->GetString( "action" ) ) ) { s_bInviteSessionDelayedJoin = true; } else if ( !Q_stricmp( "deny", pEvent->GetString( "action" ) ) ) { Q_memset( &s_InviteInfo, 0, sizeof( s_InviteInfo ) ); s_bInviteSessionDelayedJoin = false; } return; } else if ( !Q_stricmp( "OnSteamOverlayCall::LobbyJoin", szEvent ) ) { #if !defined( _X360 ) && !defined( NO_STEAM ) && !defined( SWDS )
GameLobbyJoinRequested_t msg; msg.m_steamIDLobby.SetFromUint64( pEvent->GetUint64( "sessionid" ) ); msg.m_steamIDFriend.SetFromUint64( ~0ull ); g_MatchSteamInviteListener.Steam_OnGameLobbyJoinRequested( &msg ); #endif
return; } else if ( !Q_stricmp( "OnMatchSessionUpdate", szEvent ) ) { KeyValues *pUpdate = pEvent->FindKey( "update" ); if ( pUpdate ) { const char *pAction = pUpdate->GetString( "options/action", "" ); if ( !Q_stricmp( "joinsession", pAction ) ) { KeyValues *pTeamMembers = pUpdate->FindKey( "teamMembers" );
if ( pTeamMembers ) { // Received console team match settings from host
// Find what team we are on
int numPlayers = pTeamMembers->GetInt( "numPlayers" ); int playerTeam = -1;
int activeUer = XBX_GetPrimaryUserId(); IPlayerLocal *player = g_pPlayerManager->GetLocalPlayer( activeUer ); uint64 localPlayerId = player->GetXUID();
for ( int i = 0; i < numPlayers; i++ ) { KeyValues *pTeamPlayer = pTeamMembers->FindKey( CFmtStr( "player%d", i ) ); uint64 playerId = pTeamPlayer->GetUint64( "xuid" );
if ( playerId == localPlayerId ) { int team = pTeamPlayer->GetInt( "team" ); DevMsg( "Adding player %llu to team %d\n", playerId, team ); playerTeam = team; break; } } m_pTeamSessionSettings = pUpdate->MakeCopy(); m_pTeamSessionSettings->SetName( "settings ");
// Delete the "teamMembers" key
m_pTeamSessionSettings->RemoveSubKey( m_pTeamSessionSettings->FindKey( "teamMembers" ) );
// Add "conteam" value
m_pTeamSessionSettings->SetInt( "conteam", playerTeam );
// Add the "sessionHostDataUnpacked" key
KeyValues *pSessionHostDataSrc = pUpdate->FindKey( "sessionHostDataUnpacked" ); if ( pSessionHostDataSrc ) { KeyValues *pSessionHostDataDst = m_pTeamSessionSettings->CreateNewKey(); pSessionHostDataDst->SetName( "sessionHostDataUnpacked" ); pSessionHostDataSrc->CopySubkeys( pSessionHostDataDst ); }
m_bJoinTeamSession = true; } } } }
//
// Delegate to the managers
//
if ( g_pPlayerManager ) g_pPlayerManager->OnEvent( pEvent ); if ( g_pServerManager ) g_pServerManager->OnEvent( pEvent ); if ( g_pDatacenter ) g_pDatacenter->OnEvent( pEvent ); if ( g_pDlcManager ) g_pDlcManager->OnEvent( pEvent );
//
// Delegate to the title
//
if ( g_pIMatchTitleEventsSink ) g_pIMatchTitleEventsSink->OnEvent( pEvent );
//
// Delegate to the session
//
if ( m_pMatchSession ) m_pMatchSession->OnEvent( pEvent ); }
void CMatchFramework::SetCurrentMatchSession( IMatchSessionInternal *pNewMatchSession ) { m_pMatchSession = pNewMatchSession; }
uint64 CMatchFramework::GetLastInviteFlags() { return g_uiLastInviteFlags; }
|