bool APartyBeaconClient::RequestReservation(const FOnlineSessionSearchResult& DesiredHost, const FUniqueNetIdRepl& RequestingPartyLeader, const TArray<FPlayerReservation>& PartyMembers)
{
	bool bSuccess = false;

	if (DesiredHost.IsValid())
	{
		UWorld* World = GetWorld();

		IOnlineSubsystem* OnlineSub = Online::GetSubsystem(World);
		if (OnlineSub)
		{
			IOnlineSessionPtr SessionInt = OnlineSub->GetSessionInterface();
			if (SessionInt.IsValid())
			{
				FString ConnectInfo;
				if (SessionInt->GetResolvedConnectString(DesiredHost, BeaconPort, ConnectInfo))
				{
					FString SessionId = DesiredHost.Session.SessionInfo->GetSessionId().ToString();
					return RequestReservation(ConnectInfo, SessionId, RequestingPartyLeader, PartyMembers);
				}
			}
		}
	}

	if (!bSuccess)
	{
		OnFailure();
	}

	return bSuccess;
}
void UGameInstance::OnSessionUserInviteAccepted(const bool bWasSuccess, const int32 ControllerId, TSharedPtr< const FUniqueNetId > UserId, const FOnlineSessionSearchResult &	InviteResult)
{
	UE_LOG(LogPlayerManagement, Verbose, TEXT("OnSessionUserInviteAccepted LocalUserNum: %d bSuccess: %d"), ControllerId, bWasSuccess);
	// Don't clear invite accept delegate

	if (bWasSuccess)
	{
		if (InviteResult.IsValid())
		{
			GetOnlineSession()->OnSessionUserInviteAccepted(bWasSuccess, ControllerId, UserId, InviteResult);
		}
		else
		{
			UE_LOG(LogPlayerManagement, Warning, TEXT("Invite accept returned invalid search result."));
		}
	}
}
void UOnlineSessionClient::OnSessionUserInviteAccepted(bool bWasSuccessful, int32 ControllerId, TSharedPtr<const FUniqueNetId> UserId, const FOnlineSessionSearchResult& SearchResult)
{
	UE_LOG(LogOnline, Verbose, TEXT("OnSessionUserInviteAccepted LocalUserNum: %d bSuccess: %d"), ControllerId, bWasSuccessful);
	// Don't clear invite accept delegate

	if (bWasSuccessful)
	{
		if (SearchResult.IsValid())
		{
			bIsFromInvite = true;
			JoinSession(GameSessionName, SearchResult);
		}
		else
		{
			UE_LOG(LogOnline, Warning, TEXT("Invite accept returned no search result."));
		}
	}
}
/**
 * Delegate fired when an invite request has been accepted (via external UI)
 *
 * @param LocalUserNum local user accepting invite
 * @param bWasSuccessful true if the async action completed without error, false if there was an error
 * @param SearchResult search result containing the invite data
 */
void UOnlineSessionClient::OnSessionInviteAccepted(int32 LocalUserNum, bool bWasSuccessful, const FOnlineSessionSearchResult& SearchResult)
{
	UE_LOG(LogOnline, Verbose, TEXT("OnSessionInviteAccepted LocalUserNum: %d bSuccess: %d"), LocalUserNum, bWasSuccessful);
	// Don't clear invite accept delegate

	if (bWasSuccessful)
	{
		if (SearchResult.IsValid())
		{
			bIsFromInvite = true;
			check(GetControllerId() == LocalUserNum);
			JoinSession(LocalUserNum, GameSessionName, SearchResult);
		}
		else
		{
			UE_LOG(LogOnline, Warning, TEXT("Invite accept returned no search result."));
		}
	}
}
void FQosDatacenterStats::RecordQosAttempt(const FOnlineSessionSearchResult& SearchResult, bool bSuccess)
{
	if (bAnalyticsInProgress)
	{
		QosData.NumTotalSearches++;
		QosData.NumSuccessAttempts += bSuccess ? 1 : 0;

		FQosStats_QosSearchResult& NewSearchResult = *new (QosData.SearchResults) FQosStats_QosSearchResult();
		NewSearchResult.OwnerId = SearchResult.Session.OwningUserId;
		NewSearchResult.PingInMs = SearchResult.PingInMs;
		NewSearchResult.bIsValid = SearchResult.IsValid();

		FString TmpRegion;
		if (SearchResult.Session.SessionSettings.Get(SETTING_REGION, TmpRegion))
		{
			NewSearchResult.DatacenterId = TmpRegion;
		}
	}
}
/**
 *  The server has finished responding to the rule details request 
 * (ie, you won't get anymore RulesResponded callbacks)
 */
void FPendingSearchResultSteam::RulesRefreshComplete()
{
	UE_LOG_ONLINE(Warning, TEXT("Rules refresh complete"));
	ParentQuery->ElapsedTime = 0.0f;

	// Only append this data if there is an existing search (NULL CurrentSessionSearch implies no active search query)
	FOnlineSessionSteamPtr SessionInt = StaticCastSharedPtr<FOnlineSessionSteam>(ParentQuery->Subsystem->GetSessionInterface());
	if (SessionInt.IsValid() && SessionInt->CurrentSessionSearch.IsValid() && SessionInt->CurrentSessionSearch->SearchState == EOnlineAsyncTaskState::InProgress)
	{
		if (FillSessionFromServerRules())
		{
			// Transfer rules to actual search results
			FOnlineSessionSearchResult* SearchResult = new (ParentQuery->SearchSettings->SearchResults) FOnlineSessionSearchResult(PendingSearchResult);
			SearchResult->Session.SessionInfo = PendingSearchResult.Session.SessionInfo;
			if (!SearchResult->IsValid())
			{
				// Remove the failed element
				ParentQuery->SearchSettings->SearchResults.RemoveAtSwap(ParentQuery->SearchSettings->SearchResults.Num() - 1);
			}
		}
	}

	RemoveSelf();
}