uid issue
This commit is contained in:
commit
c2130ba4e9
13850 files changed
+6241419
No files matched your search
@@ -0,0 +1,960 @@
|
||||
//===== 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;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user