Files
UnrealEngineUWP/Engine/Source/Developer/FriendsAndChat/Private/FriendsAndChatManager.cpp
Max Preussner 121fccd2ab Code and documentation cleanup pass
- removed dummy UClasses (no longer needed)
- removed file header comments (not used)
- removed duplicated function documentation in cpp files
- documentation cleanup, punctuation, spelling etc.
- pragma once include guards (now work on all platforms)
- relative public includes (are auto-discovered by UBT)
- fixed too many/too few line breaks
- deleted empty files
- missing override
- NULL to nullptr

[CL 2305058 by Max Preussner in Main branch]
2014-09-21 20:35:48 -04:00

1052 lines
30 KiB
C++

// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
#include "FriendsAndChatPrivatePCH.h"
#define LOCTEXT_NAMESPACE "FriendsAndChatManager"
/* FFriendsAndChatManager structors
*****************************************************************************/
FFriendsAndChatManager::FFriendsAndChatManager( )
: ManagerState ( EFriendsAndManagerState::Idle )
, UpdateTimeInterval( 10.0f )
, CurrentList( EFriendsDisplayLists::DefaultDisplay )
, ConfirmedFriendsCount( 0 )
, bIsInSession( false )
, bIsInited( false )
{ }
FFriendsAndChatManager::~FFriendsAndChatManager( )
{ }
/* IFriendsAndChatManager interface
*****************************************************************************/
void FFriendsAndChatManager::StartupManager()
{
}
void FFriendsAndChatManager::Init( FOnFriendsNotification& NotificationDelegate )
{
// Clear existing data
Logout();
FriendsListNotificationDelegate = &NotificationDelegate;
UpdateTimer = 0.0f;
bIsInited = false;
FFriendsMessageManager::Get()->SetMessagePolling( false );
OnlineSubMcp = static_cast< FOnlineSubsystemMcp* >( IOnlineSubsystem::Get( TEXT( "MCP" ) ) );
if (OnlineSubMcp != nullptr &&
OnlineSubMcp->GetMcpAccountMappingService().IsValid() &&
OnlineSubMcp->GetIdentityInterface().IsValid())
{
OnlineIdentity = OnlineSubMcp->GetIdentityInterface();
IOnlineUserPtr UserInterface = OnlineSubMcp->GetUserInterface();
check(UserInterface.IsValid());
FriendsInterface = OnlineSubMcp->GetFriendsInterface();
check( FriendsInterface.IsValid() )
// Create delegates for list refreshes
OnReadFriendsCompleteDelegate = FOnReadFriendsListCompleteDelegate::CreateSP( this, &FFriendsAndChatManager::OnReadFriendsComplete );
OnAcceptInviteCompleteDelegate = FOnAcceptInviteCompleteDelegate::CreateSP( this, &FFriendsAndChatManager::OnAcceptInviteComplete );
OnSendInviteCompleteDelegate = FOnSendInviteCompleteDelegate::CreateSP( this, &FFriendsAndChatManager::OnSendInviteComplete );
OnDeleteFriendsListCompleteDelegate = FOnDeleteFriendsListCompleteDelegate::CreateSP( this, &FFriendsAndChatManager::OnDeleteFriendsListComplete );
OnDeleteFriendCompleteDelegate = FOnDeleteFriendCompleteDelegate::CreateSP( this, &FFriendsAndChatManager::OnDeleteFriendComplete );
OnQueryUserIdFromDisplayNameCompleteDelegate = FOnQueryUserIdFromDisplayNameCompleteDelegate::CreateSP( this, &FFriendsAndChatManager::OnQueryUserIdFromDisplayNameComplete );
OnQueryUserInfoCompleteDelegate = FOnQueryUserInfoCompleteDelegate::CreateSP( this, &FFriendsAndChatManager::OnQueryUserInfoComplete );
FriendsInterface->AddOnReadFriendsListCompleteDelegate( 0, OnReadFriendsCompleteDelegate );
ManagerState = EFriendsAndManagerState::Idle;
FriendsList.Empty();
PendingFriendsList.Empty();
if ( UpdateFriendsTickerDelegate.IsBound() == false )
{
UpdateFriendsTickerDelegate = FTickerDelegate::CreateSP( this, &FFriendsAndChatManager::Tick );
}
SetInSession( false );
FTicker::GetCoreTicker().AddTicker( UpdateFriendsTickerDelegate );
}
}
bool FFriendsAndChatManager::Tick( float Delta )
{
if ( ManagerState == EFriendsAndManagerState::Idle )
{
UpdateTimer -= Delta;
if ( FriendByNameRequests.Num() > 0 )
{
SetState(EFriendsAndManagerState::RequestingFriends );
}
else if ( PendingOutgoingDeleteFriendRequests.Num() > 0 )
{
SetState( EFriendsAndManagerState::DeletingFriends );
}
else if ( PendingOutgoingAcceptFriendRequests.Num() > 0 )
{
SetState( EFriendsAndManagerState::AcceptingFriendRequest );
}
else if ( PendingIncomingInvitesList.Num() > 0 )
{
SendFriendInviteNotification();
}
else if ( UpdateTimer < 0.0f )
{
SetState( EFriendsAndManagerState::RequestFriendsListRefresh );
UpdateTimer = UpdateTimeInterval;
}
}
return true;
}
void FFriendsAndChatManager::Logout()
{
if ( FriendsInterface.IsValid() )
{
FriendsInterface->ClearOnReadFriendsListCompleteDelegate( 0, OnReadFriendsCompleteDelegate );
FriendsInterface->ClearOnAcceptInviteCompleteDelegate( 0, OnAcceptInviteCompleteDelegate );
FriendsInterface->ClearOnSendInviteCompleteDelegate( 0, OnSendInviteCompleteDelegate );
FriendsInterface->ClearOnDeleteFriendsListCompleteDelegate( 0, OnDeleteFriendsListCompleteDelegate );
FriendsInterface->ClearOnDeleteFriendCompleteDelegate( 0, OnDeleteFriendCompleteDelegate );
if ( OnlineSubMcp != nullptr )
{
FOnlineAccountMappingMcpPtr OnlineAccountMappingMcp = OnlineSubMcp->GetMcpAccountMappingService();
if ( OnlineAccountMappingMcp.IsValid() )
{
OnlineAccountMappingMcp->ClearOnQueryUserIdFromDisplayNameCompleteDelegate( OnQueryUserIdFromDisplayNameCompleteDelegate );
OnlineSubMcp->GetUserInterface()->ClearOnQueryUserInfoCompleteDelegate( 0, OnQueryUserInfoCompleteDelegate );
}
}
}
FriendsList.Empty();
RecentPlayerList.Empty();
PendingFriendsList.Empty();
FriendByNameRequests.Empty();
FilteredFriendsList.Empty();
PendingOutgoingDeleteFriendRequests.Empty();
PendingOutgoingAcceptFriendRequests.Empty();
PendingIncomingInvitesList.Empty();
NotifiedRequest.Empty();
ConfirmedFriendsCount = 0;
if ( FriendWindow.IsValid() )
{
FriendWindow->RequestDestroyWindow();
FriendWindow = nullptr;
}
if ( ChatWindow.IsValid() )
{
ChatWindow->RequestDestroyWindow();
ChatWindow = nullptr;
}
OnlineSubMcp = nullptr;
if ( UpdateFriendsTickerDelegate.IsBound() )
{
FTicker::GetCoreTicker().RemoveTicker( UpdateFriendsTickerDelegate );
}
}
void FFriendsAndChatManager::GenerateFriendsWindow( TSharedPtr< const SWidget > InParentWidget, const FFriendsAndChatStyle* InStyle )
{
const FVector2D DEFAULT_WINDOW_SIZE = FVector2D(308, 458);
ParentWidget = InParentWidget;
Style = *InStyle;
if ( !FriendWindow.IsValid() )
{
FriendWindow = SNew( SWindow )
.Title( LOCTEXT( "FFriendsAndChatManager_FriendsTitle", "Friends List") )
.ClientSize( DEFAULT_WINDOW_SIZE )
.ScreenPosition( FVector2D( 100, 100 ) )
.AutoCenter( EAutoCenter::None )
.SupportsMaximize( true )
.SupportsMinimize( true )
.CreateTitleBar( false )
.SizingRule( ESizingRule::FixedSize )
[
SNew( SBorder )
.VAlign( VAlign_Fill )
.HAlign( HAlign_Fill )
.BorderImage( &InStyle->Background )
[
SNew( SFriendsList )
.FriendStyle( &Style )
.OnCloseClicked( this, &FFriendsAndChatManager::OnCloseClicked )
.OnMinimizeClicked( this, &FFriendsAndChatManager::OnMinimizeClicked )
]
];
if ( ParentWidget.IsValid() )
{
FWidgetPath WidgetPath;
FSlateApplication::Get().GeneratePathToWidgetChecked( ParentWidget.ToSharedRef(), WidgetPath );
FriendWindow = FSlateApplication::Get().AddWindowAsNativeChild( FriendWindow.ToSharedRef(), WidgetPath.GetWindow() );
}
}
else
{
FriendWindow->Restore();
}
}
void FFriendsAndChatManager::SetInSession( bool bInSession )
{
bIsInSession = bInSession;
ReadListRequests.AddUnique( EFriendsLists::RecentPlayers );
}
bool FFriendsAndChatManager::IsInSession()
{
return bIsInSession;
}
TSharedPtr< SWidget > FFriendsAndChatManager::GenerateFriendsListWidget( const FFriendsAndChatStyle* InStyle )
{
if ( !FriendListWidget.IsValid() )
{
Style = *InStyle;
SAssignNew( FriendListWidget, SFriendsList )
.FriendStyle( &Style );
}
return FriendListWidget;
}
void FFriendsAndChatManager::GenerateChatWindow( TSharedPtr< FFriendStuct > FriendItem )
{
const FVector2D DEFAULT_WINDOW_SIZE = FVector2D(308, 458);
if ( !ChatWindow.IsValid() )
{
ChatWindow = SNew( SWindow )
.Title( LOCTEXT( "FriendsAndChatManager_ChatTitle", "Chat Window") )
.ClientSize( DEFAULT_WINDOW_SIZE )
.ScreenPosition( FVector2D( 200, 100 ) )
.AutoCenter( EAutoCenter::None )
.SupportsMaximize( true )
.SupportsMinimize( true )
.CreateTitleBar( false )
.SizingRule( ESizingRule::FixedSize )
[
SNew( SBorder )
.VAlign( VAlign_Fill )
.HAlign( HAlign_Fill )
.BorderImage( &Style.Background )
[
SNew( SChatWindow )
.FriendStyle( &Style )
.FriendItem( FriendItem )
.OnCloseClicked( this, &FFriendsAndChatManager::OnChatCloseClicked )
.OnMinimizeClicked( this, &FFriendsAndChatManager::OnChatMinimizeClicked )
]
];
if ( ParentWidget.IsValid() )
{
FWidgetPath WidgetPath;
FSlateApplication::Get().GeneratePathToWidgetChecked( ParentWidget.ToSharedRef(), WidgetPath );
ChatWindow = FSlateApplication::Get().AddWindowAsNativeChild( ChatWindow.ToSharedRef(), WidgetPath.GetWindow() );
}
}
}
void FFriendsAndChatManager::AcceptFriend( TSharedPtr< FFriendStuct > FriendItem )
{
PendingOutgoingAcceptFriendRequests.Add( FriendItem->GetOnlineUser()->GetUserId() );
FriendItem->SetPendingAccept();
GenerateFriendsCount();
RefreshList();
ClearNotification( FriendItem );
}
void FFriendsAndChatManager::RejectFriend( TSharedPtr< FFriendStuct > FriendItem )
{
NotifiedRequest.Remove( FriendItem->GetOnlineUser()->GetUserId() );
PendingOutgoingDeleteFriendRequests.Add( FriendItem->GetOnlineUser()->GetUserId() );
FriendsList.Remove( FriendItem );
GenerateFriendsCount();
RefreshList();
ClearNotification( FriendItem );
}
void FFriendsAndChatManager::ClearNotification( TSharedPtr< FFriendStuct > FriendItem )
{
if ( NotificationMessages.Num() > 0 )
{
if ( NotificationMessages[0]->GetUniqueID().Get() == FriendItem->GetUniqueID().Get() )
{
// Inform the UI that this friend has been rejected. Clear any notifications
NotificationMessages[0]->SetHandled();
FriendsListNotificationDelegate->Broadcast( NotificationMessages[0].ToSharedRef() );
NotificationMessages.RemoveAt( 0 );
}
}
}
FReply FFriendsAndChatManager::HandleMessageAccepted( TSharedPtr< FFriendsAndChatMessage > ChatMessage, EFriendsResponseType::Type ResponseType )
{
switch ( ResponseType )
{
case EFriendsResponseType::Response_Accept:
{
PendingOutgoingAcceptFriendRequests.Add( ChatMessage->GetUniqueID() );
TSharedPtr< FFriendStuct > User = FindUser( ChatMessage->GetUniqueID(), EFriendsLists::ToString( EFriendsLists::Default ) );
if ( User.IsValid() )
{
User->SetPendingAccept();
GenerateFriendsCount();
RefreshList();
}
}
break;
case EFriendsResponseType::Response_Reject:
{
NotifiedRequest.Remove( ChatMessage->GetUniqueID() );
TSharedPtr< FFriendStuct > User = FindUser( ChatMessage->GetUniqueID(), EFriendsLists::ToString( EFriendsLists::Default ) );
if ( User.IsValid() )
{
FriendsList.Remove( User );
GenerateFriendsCount();
RefreshList();
}
PendingOutgoingDeleteFriendRequests.Add( ChatMessage->GetUniqueID() );
}
break;
}
NotificationMessages.Remove( ChatMessage );
return FReply::Handled();
}
/** Functor for comparing friends list */
struct FCompareGroupByName
{
FORCEINLINE bool operator()( const TSharedPtr< FFriendStuct > A, const TSharedPtr< FFriendStuct > B ) const
{
check( A.IsValid() );
check ( B.IsValid() );
return ( A->GetName() > B->GetName() );
}
};
bool FFriendsAndChatManager::UpdateFriendsList()
{
bool bChanged = false;
// Early check if list has changed
if ( PendingFriendsList.Num() != FriendsList.Num() )
{
bChanged = true;
}
else
{
// Need to check each item
FriendsList.Sort( FCompareGroupByName() );
PendingFriendsList.Sort( FCompareGroupByName() );
for ( int32 Index = 0; Index < FriendsList.Num(); Index++ )
{
if ( PendingFriendsList[Index]->IsUpdated() || *FriendsList[Index].Get() != *PendingFriendsList[Index].Get() )
{
bChanged = true;
break;
}
}
}
if ( bChanged )
{
PendingIncomingInvitesList.Empty();
for ( int32 Index = 0; Index < PendingFriendsList.Num(); Index++ )
{
PendingFriendsList[Index]->ClearUpdated();
EInviteStatus::Type FriendStatus = PendingFriendsList[ Index ].Get()->GetOnlineFriend()->GetInviteStatus();
if ( FriendStatus == EInviteStatus::PendingInbound )
{
if ( NotifiedRequest.Contains( PendingFriendsList[ Index ].Get()->GetUniqueID() ) == false )
{
PendingIncomingInvitesList.Add( PendingFriendsList[ Index ] );
NotifiedRequest.Add( PendingFriendsList[ Index ]->GetUniqueID() );
}
}
}
FriendByNameInvites.Empty();
FriendsList = PendingFriendsList;
GenerateFriendsCount();
RefreshList();
}
PendingFriendsList.Empty();
if ( bIsInited == false )
{
bIsInited = true;
FFriendsMessageManager::Get()->SetMessagePolling( true );
}
return bChanged;
}
bool FFriendsAndChatManager::UpdateRecentPlayerList()
{
bool bChanged = false;
// Early check if list has changed
if ( PendingFriendsList.Num() != RecentPlayerList.Num() )
{
bChanged = true;
}
else
{
// Need to check each item
RecentPlayerList.Sort( FCompareGroupByName() );
PendingFriendsList.Sort( FCompareGroupByName() );
for ( int32 Index = 0; Index < RecentPlayerList.Num(); Index++ )
{
if ( *RecentPlayerList[Index].Get() != *PendingFriendsList[Index].Get() )
{
bChanged = true;
break;
}
}
}
RecentPlayerList = PendingFriendsList;
PendingFriendsList.Empty();
return bChanged;
}
int32 FFriendsAndChatManager::GetFilteredFriendsList( TArray< TSharedPtr< FFriendStuct > >& OutFriendsList )
{
OutFriendsList = FilteredFriendsList;
return OutFriendsList.Num();
}
int32 FFriendsAndChatManager::GetFilteredOutgoingFriendsList( TArray< TSharedPtr< FFriendStuct > >& OutFriendsList )
{
OutFriendsList = FilteredOutgoingList;
return OutFriendsList.Num();
}
int32 FFriendsAndChatManager::GetFriendCount()
{
return ConfirmedFriendsCount;
}
void FFriendsAndChatManager::GenerateFriendsCount()
{
ConfirmedFriendsCount = 0;
for ( int32 Index = 0; Index < FriendsList.Num(); Index++ )
{
if ( FriendsList[Index]->GetInviteStatus() == EInviteStatus::Accepted )
{
ConfirmedFriendsCount++;
}
}
}
void FFriendsAndChatManager::DeleteFriend( TSharedPtr< FFriendStuct > FriendItem )
{
TSharedRef<FUniqueNetId> UserID = FriendItem->GetOnlineFriend()->GetUserId();
NotifiedRequest.Remove( UserID );
PendingOutgoingDeleteFriendRequests.Add( UserID );
FriendsList.Remove( FriendItem );
GenerateFriendsCount();
RefreshList();
}
FReply FFriendsAndChatManager::OnCloseClicked()
{
if ( FriendWindow.IsValid() )
{
FriendWindow->RequestDestroyWindow();
FriendWindow = nullptr;
}
return FReply::Handled();
}
FReply FFriendsAndChatManager::OnMinimizeClicked()
{
if ( FriendWindow.IsValid() )
{
FriendWindow->Minimize();
}
return FReply::Handled();
}
FReply FFriendsAndChatManager::OnChatCloseClicked()
{
if ( ChatWindow.IsValid() )
{
ChatWindow->RequestDestroyWindow();
ChatWindow = nullptr;
}
return FReply::Handled();
}
FReply FFriendsAndChatManager::OnChatMinimizeClicked()
{
if ( ChatWindow.IsValid() )
{
ChatWindow->Minimize();
}
return FReply::Handled();
}
void FFriendsAndChatManager::RefreshList()
{
switch ( CurrentList )
{
case EFriendsDisplayLists::DefaultDisplay:
{
BuildFriendsList();
}
break;
case EFriendsDisplayLists::RecentPlayersDisplay:
{
BuildRecentPlayersList();
}
break;
case EFriendsDisplayLists::FriendRequestsDisplay:
{
BuildRequestIncomingPlayersList();
BuildRequestOutgoingPlayersList();
}
break;
}
}
void FFriendsAndChatManager::BuildFriendsList()
{
FilteredFriendsList.Empty();
for( auto Iter( FriendsList.CreateConstIterator() ); Iter; ++Iter )
{
const TSharedPtr< FFriendStuct > Friend = *Iter;
if ( Friend->GetInviteStatus() == EInviteStatus::Accepted )
{
FilteredFriendsList.Add( Friend );
}
}
OnFriendsListUpdatedDelegate.Broadcast();
}
void FFriendsAndChatManager::BuildRecentPlayersList()
{
FilteredFriendsList.Empty();
for( auto Iter( RecentPlayerList.CreateConstIterator() ); Iter; ++Iter )
{
const TSharedPtr< FFriendStuct > Friend = *Iter;
FilteredFriendsList.Add( Friend );
}
OnFriendsListUpdatedDelegate.Broadcast();
}
void FFriendsAndChatManager::BuildRequestIncomingPlayersList()
{
FilteredFriendsList.Empty();
for( auto Iter( FriendsList.CreateConstIterator() ); Iter; ++Iter )
{
const TSharedPtr< FFriendStuct > Friend = *Iter;
if ( Friend->GetInviteStatus() == EInviteStatus::PendingInbound )
{
FilteredFriendsList.Add( Friend );
}
}
}
void FFriendsAndChatManager::BuildRequestOutgoingPlayersList()
{
FilteredOutgoingList.Empty();
for( auto Iter( FriendsList.CreateConstIterator() ); Iter; ++Iter )
{
TSharedPtr< FFriendStuct > Friend = *Iter;
if ( Friend->GetInviteStatus() == EInviteStatus::PendingOutbound )
{
FilteredOutgoingList.Add( Friend );
}
}
for( auto Iter( FriendByNameRequests.CreateConstIterator() ); Iter; ++Iter )
{
const FString FriendName = *Iter;
TSharedPtr< FFriendStuct > PendingFriend = MakeShareable( new FFriendStuct( FriendName ) );
PendingFriend->ClearUpdated();
PendingFriend->SetPendingInvite();
FilteredOutgoingList.Add( PendingFriend );
}
for( auto Iter( FriendByNameInvites.CreateConstIterator() ); Iter; ++Iter )
{
const FString FriendName = *Iter;
TSharedPtr< FFriendStuct > PendingFriend = MakeShareable( new FFriendStuct( FriendName ) );
PendingFriend->ClearUpdated();
PendingFriend->SetPendingInvite();
FilteredOutgoingList.Add( PendingFriend );
}
OnFriendsListUpdatedDelegate.Broadcast();
}
void FFriendsAndChatManager::RequestFriend( const FText& FriendName )
{
if ( !FriendName.IsEmpty() )
{
if ( !FindUserID( FriendName.ToString() ).IsValid() )
{
FriendByNameRequests.AddUnique( *FriendName.ToString() );
RefreshList();
}
}
}
void FFriendsAndChatManager::SendFriendRequests()
{
// Invite Friends
FOnlineAccountMappingMcpPtr OnlineAccountMappingMcp = OnlineSubMcp->GetMcpAccountMappingService();
TSharedPtr<FUniqueNetId> UserId = OnlineIdentity->GetUniquePlayerId(0);
OnlineAccountMappingMcp->AddOnQueryUserIdFromDisplayNameCompleteDelegate(OnQueryUserIdFromDisplayNameCompleteDelegate);
for ( int32 Index = 0; Index < FriendByNameRequests.Num(); Index++ )
{
OnlineAccountMappingMcp->QueryUserIdFromDisplayName( *UserId, FriendByNameRequests[Index] );
}
}
EFriendsAndManagerState::Type FFriendsAndChatManager::GetManagerState()
{
return ManagerState;
}
void FFriendsAndChatManager::SetListSelect( EFriendsDisplayLists::Type ListSelectType )
{
if ( CurrentList != ListSelectType )
{
CurrentList = ListSelectType;
RefreshList();
}
}
TSharedPtr< FUniqueNetId > FFriendsAndChatManager::FindUserID( const FString& InUsername )
{
for ( int32 Index = 0; Index < FriendsList.Num(); Index++ )
{
if ( FriendsList[ Index ]->GetOnlineUser()->GetDisplayName() == InUsername )
{
return FriendsList[ Index ]->GetUniqueID();
}
}
return nullptr;
}
bool FFriendsAndChatManager::IsPendingInvite( const FString& InUsername )
{
return FriendByNameRequests.Contains( InUsername ) || FriendByNameInvites.Contains( InUsername );
}
TSharedPtr< FFriendStuct > FFriendsAndChatManager::FindUser( TSharedRef<FUniqueNetId> InUserID, const FString& ListName )
{
TArray< TSharedPtr< FFriendStuct > >& SearchList = ListName == EFriendsLists::ToString( EFriendsLists::Default ) ? FriendsList : RecentPlayerList;
for ( int32 Index = 0; Index < SearchList.Num(); Index++ )
{
if ( SearchList[Index]->GetUniqueID().Get() == InUserID.Get() )
{
return SearchList[Index];
}
}
return nullptr;
}
void FFriendsAndChatManager::SetState( EFriendsAndManagerState::Type NewState )
{
ManagerState = NewState;
switch ( NewState )
{
case EFriendsAndManagerState::Idle:
{
// Do nothing in this state
}
break;
case EFriendsAndManagerState::RequestFriendsListRefresh:
{
ReadListRequests.AddUnique( EFriendsLists::Default );
SetState( EFriendsAndManagerState::RequestingFriendsList );
}
break;
case EFriendsAndManagerState::RequestingFriendsList:
{
check( ReadListRequests.Num() > 0 )
FriendsInterface->ReadFriendsList( 0, EFriendsLists::ToString( ReadListRequests[0] ) );
}
break;
case EFriendsAndManagerState::ProcessFriendsList:
{
if ( UpdateFriendsList() && CurrentList == EFriendsDisplayLists::DefaultDisplay )
{
RefreshList();
}
ReadListRequests.Remove( EFriendsLists::Default );
if ( ReadListRequests.Num() > 0 )
{
SetState( EFriendsAndManagerState::RequestingFriendsList );
}
else
{
SetState( EFriendsAndManagerState::Idle );
}
}
break;
case EFriendsAndManagerState::ProcessRecentPlayersList:
{
if ( UpdateRecentPlayerList() && CurrentList == EFriendsDisplayLists::RecentPlayersDisplay )
{
BuildRecentPlayersList();
}
ReadListRequests.Remove( EFriendsLists::RecentPlayers );
if ( ReadListRequests.Num() > 0 )
{
SetState( EFriendsAndManagerState::RequestingFriendsList );
}
else
{
SetState( EFriendsAndManagerState::Idle );
}
}
break;
case EFriendsAndManagerState::RequestingFriends:
{
SendFriendRequests();
}
break;
case EFriendsAndManagerState::DeletingFriends:
{
FriendsInterface->AddOnDeleteFriendCompleteDelegate( 0, OnDeleteFriendCompleteDelegate );
FriendsInterface->DeleteFriend( 0, PendingOutgoingDeleteFriendRequests[0].Get(), EFriendsLists::ToString( EFriendsLists::Default ) );
}
break;
case EFriendsAndManagerState::AcceptingFriendRequest:
{
FriendsInterface->AddOnAcceptInviteCompleteDelegate( 0, OnAcceptInviteCompleteDelegate );
FriendsInterface->AcceptInvite( 0, PendingOutgoingAcceptFriendRequests[0].Get(), EFriendsLists::ToString( EFriendsLists::Default ) );
}
break;
default:
break;
}
}
void FFriendsAndChatManager::SendFriendInviteNotification()
{
check( PendingIncomingInvitesList[ 0 ].IsValid() )
FString InviteMessage = PendingIncomingInvitesList[ 0 ]->GetName();
InviteMessage += LOCTEXT( "FFriendsAndChatManager_InviteRequest", " Requested you as a friend" ).ToString();
TSharedPtr< FFriendsAndChatMessage > ChatMessage = MakeShareable( new FFriendsAndChatMessage( InviteMessage, PendingIncomingInvitesList[0]->GetUniqueID() ) );
ChatMessage->SetSelfHandle( false );
ChatMessage->SetButtonCallback( FOnClicked::CreateSP( this, &FFriendsAndChatManager::HandleMessageAccepted, ChatMessage, EFriendsResponseType::Response_Accept ) );
ChatMessage->SetButtonCallback( FOnClicked::CreateSP( this, &FFriendsAndChatManager::HandleMessageAccepted, ChatMessage, EFriendsResponseType::Response_Reject ) );
ChatMessage->SetButtonCallback( FOnClicked::CreateSP( this, &FFriendsAndChatManager::HandleMessageAccepted, ChatMessage, EFriendsResponseType::Response_Ignore ) );
// Only allow one friend notification at a time
if ( NotificationMessages.Num() == 0 )
{
NotificationMessages.Add( ChatMessage );
FriendsListNotificationDelegate->Broadcast( ChatMessage.ToSharedRef() );
}
PendingIncomingInvitesList.RemoveAt( 0 );
}
void FFriendsAndChatManager::OnQueryUserIdFromDisplayNameComplete(bool bWasSuccessful, const FUniqueNetId& RequestingUserId, const FString& DisplayName, const FUniqueNetId& IdentifiedUserId, const FString& Error)
{
check( OnlineSubMcp != nullptr && OnlineSubMcp->GetMcpAccountMappingService().IsValid() );
if ( bWasSuccessful && IdentifiedUserId.IsValid() )
{
TSharedPtr<FUniqueNetId> FriendId = OnlineIdentity->CreateUniquePlayerId( IdentifiedUserId.ToString() );
// Don't allow the user to add themselves as friends
TSharedPtr<FUniqueNetId> UserId = OnlineIdentity->GetUniquePlayerId(0);
if ( UserId.IsValid() && OnlineIdentity->GetUserAccount( *UserId )->GetDisplayName() != DisplayName )
{
PendingOutgoingFriendRequests.Add( FriendId.ToSharedRef() );
}
}
FriendByNameInvites.AddUnique( DisplayName );
FriendByNameRequests.Remove( DisplayName );
if ( FriendByNameRequests.Num() == 0 )
{
FOnlineAccountMappingMcpPtr OnlineAccountMappingMcp = OnlineSubMcp->GetMcpAccountMappingService();
OnlineAccountMappingMcp->ClearOnQueryUserIdFromDisplayNameCompleteDelegate(OnQueryUserIdFromDisplayNameCompleteDelegate);
if ( PendingOutgoingFriendRequests.Num() > 0 )
{
FriendsInterface->AddOnSendInviteCompleteDelegate( 0, OnSendInviteCompleteDelegate );
for ( int32 Index = 0; Index < PendingOutgoingFriendRequests.Num(); Index++ )
{
FriendsInterface->SendInvite( 0, PendingOutgoingFriendRequests[Index].Get(), EFriendsLists::ToString( EFriendsLists::Default ) );
}
}
else
{
RefreshList();
SetState( EFriendsAndManagerState::Idle );
}
}
}
void FFriendsAndChatManager::OnSendInviteComplete( int32 LocalPlayer, bool bWasSuccessful, const FUniqueNetId& FriendId, const FString& ListName, const FString& ErrorStr )
{
PendingOutgoingFriendRequests.RemoveAt( 0 );
if ( PendingOutgoingFriendRequests.Num() == 0 )
{
FriendsInterface->ClearOnSendInviteCompleteDelegate( 0, OnSendInviteCompleteDelegate );
SetState( EFriendsAndManagerState::Idle );
}
}
void FFriendsAndChatManager::OnReadFriendsComplete( int32 LocalPlayer, bool bWasSuccessful, const FString& ListName, const FString& ErrorStr )
{
TArray< TSharedRef<FOnlineFriend> > Friends;
bool bReadyToChangeState = true;
if ( ReadListRequests.Num() == 0 )
{
// We got a request back when we weren't expecting it
UE_LOG(LogOnline, Warning, TEXT("Got ReadFriends response for list %s at unexpected time"), *ListName);
return;
}
if ( FriendsInterface->GetFriendsList(0, ListName, Friends) )
{
if (Friends.Num() > 0)
{
for (int32 Index = 0; Index < Friends.Num(); Index++)
{
const FOnlineFriend& Friend = *Friends[Index];
TSharedPtr< FFriendStuct > ExistingFriend = FindUser(Friend.GetUserId(), ListName);
if ( ExistingFriend.IsValid() )
{
if (Friends[Index]->GetInviteStatus() != ExistingFriend->GetOnlineFriend()->GetInviteStatus())
{
ExistingFriend->SetOnlineFriend(Friends[Index]);
}
PendingFriendsList.Add(ExistingFriend);
}
else
{
QueryUserIds.Add(Friend.GetUserId());
}
}
}
check( OnlineSubMcp != nullptr && OnlineSubMcp->GetMcpAccountMappingService().IsValid() );
IOnlineUserPtr UserInterface = OnlineSubMcp->GetUserInterface();
if ( QueryUserIds.Num() > 0 )
{
OnlineSubMcp->GetUserInterface()->AddOnQueryUserInfoCompleteDelegate(0, OnQueryUserInfoCompleteDelegate);
UserInterface->QueryUserInfo(0, QueryUserIds);
// OnQueryUserInfoComplete will handle state change
bReadyToChangeState = false;
}
}
else
{
UE_LOG(LogOnline, Warning, TEXT("Failed to obtain Friends List %s"), *ListName);
}
if (bReadyToChangeState)
{
if (ReadListRequests[0] == EFriendsLists::Default)
{
SetState(EFriendsAndManagerState::ProcessFriendsList);
}
else
{
SetState(EFriendsAndManagerState::ProcessRecentPlayersList);
}
}
}
void FFriendsAndChatManager::OnQueryUserInfoComplete( int32 LocalPlayer, bool bWasSuccessful, const TArray< TSharedRef<class FUniqueNetId> >& UserIds, const FString& ErrorStr )
{
check(OnlineSubMcp != nullptr && OnlineSubMcp->GetMcpAccountMappingService().IsValid());
IOnlineUserPtr UserInterface = OnlineSubMcp->GetUserInterface();
OnlineSubMcp->GetUserInterface()->ClearOnQueryUserInfoCompleteDelegate(0, OnQueryUserInfoCompleteDelegate);
if (ReadListRequests.Num() == 0)
{
// We got a request back when we weren't expecting it
UE_LOG(LogOnline, Warning, TEXT("Got QueryUserInfo response for player %i at unexpected time"), LocalPlayer);
return;
}
EFriendsDisplayLists::Type DisplayList = EFriendsDisplayLists::DefaultDisplay;
if ( ReadListRequests[0] != EFriendsLists::Default )
{
DisplayList = EFriendsDisplayLists::RecentPlayersDisplay;
}
for ( int32 UserIdx=0; UserIdx < UserIds.Num(); UserIdx++ )
{
TSharedPtr<FOnlineFriend> OnlineFriend = FriendsInterface->GetFriend( 0, *UserIds[UserIdx], EFriendsLists::ToString( ReadListRequests[0] ) );
TSharedPtr<FOnlineUser> OnlineUser = OnlineSubMcp->GetUserInterface()->GetUserInfo( LocalPlayer, *UserIds[UserIdx] );
if (OnlineFriend.IsValid() && OnlineUser.IsValid())
{
TSharedPtr< FFriendStuct > FriendItem = MakeShareable(new FFriendStuct(OnlineFriend, OnlineUser, DisplayList));
PendingFriendsList.Add( FriendItem );
}
else
{
UE_LOG(LogOnline, Log, TEXT("PlayerId=%s not found"), *UserIds[UserIdx]->ToDebugString());
}
}
QueryUserIds.Empty();
if ( ReadListRequests[0] == EFriendsLists::Default )
{
SetState( EFriendsAndManagerState::ProcessFriendsList );
}
else
{
SetState( EFriendsAndManagerState::ProcessRecentPlayersList );
}
}
void FFriendsAndChatManager::OnAcceptInviteComplete( int32 LocalPlayer, bool bWasSuccessful, const FUniqueNetId& FriendId, const FString& ListName, const FString& ErrorStr )
{
PendingOutgoingAcceptFriendRequests.RemoveAt( 0 );
// Do something with an accepted invite
FriendsInterface->ClearOnAcceptInviteCompleteDelegate( 0, OnAcceptInviteCompleteDelegate );
if ( PendingOutgoingAcceptFriendRequests.Num() > 0 )
{
SetState( EFriendsAndManagerState::AcceptingFriendRequest );
}
else
{
RefreshList();
SetState( EFriendsAndManagerState::Idle );
}
}
void FFriendsAndChatManager::OnDeleteFriendsListComplete( int32 LocalPlayer, bool bWasSuccessful, const FString& ListName, const FString& ErrorStr )
{
FriendsInterface->ClearOnDeleteFriendsListCompleteDelegate( 0, OnDeleteFriendsListCompleteDelegate );
SetState( EFriendsAndManagerState::Idle );
}
void FFriendsAndChatManager::OnDeleteFriendComplete( int32 LocalPlayer, bool bWasSuccessful, const FUniqueNetId& DeletedFriendID, const FString& ListName, const FString& ErrorStr )
{
PendingOutgoingDeleteFriendRequests.RemoveAt( 0 );
FriendsInterface->ClearOnDeleteFriendCompleteDelegate( 0, OnDeleteFriendCompleteDelegate );
if ( PendingOutgoingDeleteFriendRequests.Num() > 0 )
{
SetState( EFriendsAndManagerState::DeletingFriends );
}
else
{
RefreshList();
SetState( EFriendsAndManagerState::Idle );
}
}
/* FFriendsAndChatManager system singletons
*****************************************************************************/
TSharedPtr< FFriendsAndChatManager > FFriendsAndChatManager::SingletonInstance = nullptr;
TSharedRef< FFriendsAndChatManager > FFriendsAndChatManager::Get()
{
if ( !SingletonInstance.IsValid() )
{
SingletonInstance = MakeShareable( new FFriendsAndChatManager() );
SingletonInstance->StartupManager();
}
return SingletonInstance.ToSharedRef();
}
void FFriendsAndChatManager::Shutdown()
{
SingletonInstance.Reset();
}
#undef LOCTEXT_NAMESPACE