Put it all together - Recent players - (Unreal Engine module)
Connect the UI to display the recent players list
This section shows you how to connect the implementation in the RecentPlayersSubsystem
to a widget to display the recent players list.
Open the
RecentPlayersWidget_Starter
class CPP file and replace theInitRecentPlayersList()
with the code below to get and display the recent players list.void URecentPlayersWidget_Starter::InitRecentPlayersList()
{
ensure(RecentPlayersSubsystem);
RecentPlayersSubsystem->GetRecentPlayers(GetOwningPlayer(), FOnGetRecentPlayersComplete::CreateWeakLambda(this, [this](bool bWasSuccessful, TArray<UFriendData*> RecentPlayersList)
{
if(bWasSuccessful)
{
if(RecentPlayersList.IsEmpty())
{
Ws_RecentPlayers->SetWidgetState(EAccelByteWarsWidgetSwitcherState::Loading);
Tv_RecentPlayers->ClearListItems();
RecentPlayersSubsystem->QueryRecentPlayers(GetOwningPlayer());
}
else
{
Tv_RecentPlayers->SetListItems(RecentPlayersList);
Ws_RecentPlayers->SetWidgetState(EAccelByteWarsWidgetSwitcherState::Not_Empty);
}
}
else
{
Ws_RecentPlayers->SetWidgetState(EAccelByteWarsWidgetSwitcherState::Error);
Tv_RecentPlayers->ClearListItems();
}
}));
}Next, replace the
OnQueryRecentPlayerComplete()
function with the code below to refresh the recent players list when the list is queried, which happens when the game session ends.void URecentPlayersWidget_Starter::OnQueryRecentPlayerComplete(const FUniqueNetId& UserId, const FString& Namespace,
bool bWasSuccessful, const FString& Error)
{
if(!bWasSuccessful)
{
UE_LOG_RECENTPLAYERS(Warning, TEXT("Error querying recent players! Message: %s"), *Error);
Ws_RecentPlayers->SetWidgetState(EAccelByteWarsWidgetSwitcherState::Error);
return;
}
RecentPlayersSubsystem->GetRecentPlayers(GetOwningPlayer(), FOnGetRecentPlayersComplete::CreateWeakLambda(this, [this](bool bWasSuccessful, TArray<UFriendData*> RecentPlayersList)
{
if(bWasSuccessful)
{
Tv_RecentPlayers->SetListItems(RecentPlayersList);
Ws_RecentPlayers->SetWidgetState(RecentPlayersList.IsEmpty() ?
EAccelByteWarsWidgetSwitcherState::Empty :
EAccelByteWarsWidgetSwitcherState::Not_Empty);
}
else
{
Ws_RecentPlayers->SetWidgetState(EAccelByteWarsWidgetSwitcherState::Error);
}
}));
}Next, insert the highlighted code below to the
NativeOnActivated()
function. This code binds a delegate to manage the completion of a recent players query, ensuring that the specified callback function is invoked when the query finishes. It also initializes the recent players list to be displayed when the widget is shown.void URecentPlayersWidget_Starter::NativeOnActivated()
{
Super::NativeOnActivated();
Btn_Back->OnClicked().AddUObject(this, &ThisClass::DeactivateWidget);
// Reset widgets.
Ws_RecentPlayers->SetWidgetState(EAccelByteWarsWidgetSwitcherState::Loading);
Tv_RecentPlayers->ClearListItems();
Tv_RecentPlayers->OnItemClicked().AddUObject(this, &ThisClass::OnRecentPlayerEntryClicked);
OnQueryRecentPlayersCompletedDelegate = FOnQueryRecentPlayersCompleteDelegate::CreateUObject(this, &ThisClass::OnQueryRecentPlayerComplete);
RecentPlayersSubsystem->BindRecentPlayerDelegate(OnQueryRecentPlayersCompletedDelegate);
InitRecentPlayersList();
}Finally, unbind the recent players delegates when the widget is deactivated. To do this, add the highlighted code below to the
NativeOnDeactivated()
function.void URecentPlayersWidget_Starter::NativeOnDeactivated()
{
Btn_Back->OnClicked().Clear();
Tv_RecentPlayers->OnItemClicked().Clear();
RecentPlayersSubsystem->UnBindRecentPlayerDelegate(OnRecentPlayersListUpdatedDelegateHandle);
Super::NativeOnDeactivated();
}
Connect the UI to display the game session players list
This section shows you how to connect the implementation in RecentPlayersSubsystem
to a widget to display the game session players list.
Open the
PlayersListWidget_Starter
class CPP file and replace theInitGameSessionPlayersList()
with the code below to get and display the game session players list. This function will also refresh the list when the game session member changes.void UPlayersListWidget_Starter::InitGameSessionPlayersList()
{
Tv_PlayersList->OnItemClicked().RemoveAll(this);
Tv_PlayersList->OnItemClicked().AddUObject(this, &ThisClass::OnPlayersListEntryClicked);
RecentPlayersSubsystem->GetGameSessionPlayerList(GetOwningPlayer(), FOnGetGameSessionPlayerListComplete::CreateWeakLambda(this, [this](bool bWasSuccessful, TArray<UFriendData*> PlayersData)
{
if(bWasSuccessful)
{
Tv_PlayersList->SetListItems(PlayersData);
Ws_PlayersList->SetWidgetState(EAccelByteWarsWidgetSwitcherState::Not_Empty);
}
else
{
Ws_PlayersList->SetWidgetState(EAccelByteWarsWidgetSwitcherState::Error);
}
}));
const FOnlineSubsystemAccelByte* Subsystem = static_cast<FOnlineSubsystemAccelByte*>(Online::GetSubsystem(GetWorld()));
IOnlineSessionPtr SessionInterface = Subsystem->GetSessionInterface();
if(SessionInterface.IsValid())
{
SessionInterface->ClearOnSessionParticipantsChangeDelegates(this);
SessionInterface->AddOnSessionParticipantsChangeDelegate_Handle(FOnSessionParticipantsChangeDelegate::CreateUObject(this, &ThisClass::OnSessionParticipantsChanged));
}
}Finally, open the
FriendWidgetEntry
class CPP file and locate theNativeOnListItemObjectSet()
function. Then, replace it with the code below. The highlighted code below will set the game session players list status.void UFriendWidgetEntry::NativeOnListItemObjectSet(UObject* ListItemObject)
{
Super::NativeOnListItemObjectSet(ListItemObject);
CachedFriendData = Cast<UFriendData>(ListItemObject);
// Display display name.
if (!CachedFriendData->DisplayName.IsEmpty())
{
Tb_DisplayName->SetText(FText::FromString(CachedFriendData->DisplayName));
}
else
{
Tb_DisplayName->SetText(FText::FromString(
UTutorialModuleOnlineUtility::GetUserDefaultDisplayName(CachedFriendData->UserId.ToSharedRef().Get())));
}
// Display avatar image.
const FString AvatarURL = CachedFriendData->AvatarURL;
Img_Avatar->LoadImage(AvatarURL);
if(CachedFriendData->DataSource != EDataSource::User)
{
Ws_OptionButtons->SetVisibility(ESlateVisibility::Hidden);
if(CachedFriendData->DataSource == EDataSource::GameSessionPlayer)
{
URecentPlayersSubsystem_Starter* RecentPlayersSubsystem = GetGameInstance()->GetSubsystem<URecentPlayersSubsystem_Starter>();
if(RecentPlayersSubsystem != nullptr)
{
Tb_GameSessionStatus->SetVisibility(ESlateVisibility::Visible);
Tb_GameSessionStatus->SetText(FText::FromString(RecentPlayersSubsystem->GetGameSessionPlayerStatus(CachedFriendData)));
const FOnlineSubsystemAccelByte* Subsystem = static_cast<FOnlineSubsystemAccelByte*>(Online::GetSubsystem(GetWorld()));
IOnlineSessionPtr SessionInterface = Subsystem->GetSessionInterface();
if(SessionInterface.IsValid())
{
SessionInterface->ClearOnSessionParticipantsChangeDelegates(this);
SessionInterface->AddOnSessionParticipantsChangeDelegate_Handle(FOnSessionParticipantsChangeDelegate::CreateUObject(this, &ThisClass::OnSessionParticipantsChanged));
}
}
}
}
else
{
// Display options based on friend's invitation status.
Ws_OptionButtons->SetActiveWidgetIndex((uint8)CachedFriendData->Status);
// Show the reason why the player cannot send invitation request.
Btn_Invite->SetVisibility(!CachedFriendData->bCannotBeInvited ? ESlateVisibility::Visible : ESlateVisibility::Collapsed);
Tb_CannotInviteMessage->SetVisibility(CachedFriendData->bCannotBeInvited ? ESlateVisibility::Visible : ESlateVisibility::Collapsed);
Tb_CannotInviteMessage->SetText(FText::FromString(CachedFriendData->ReasonCannotBeInvited));
Tb_GameSessionStatus->SetVisibility(ESlateVisibility::Collapsed);
}
OnListItemObjectSet.Broadcast();
}
Resources
- The files used in this tutorial section are available in the Unreal Byte Wars GitHub repository.
- AccelByteWars/Source/AccelByteWars/TutorialModules/Social/FriendsEssentials/UI/FriendWidgetEntry.cpp
- AccelByteWars/Source/AccelByteWars/TutorialModules/Social/RecentPlayers/UI/RecentPlayersWidget_Starter.h
- AccelByteWars/Source/AccelByteWars/TutorialModules/Social/RecentPlayers/UI/RecentPlayersWidget_Starter.cpp
- AccelByteWars/Source/AccelByteWars/TutorialModules/Social/RecentPlayers/UI/PlayersListWidget_Starter.h
- AccelByteWars/Source/AccelByteWars/TutorialModules/Social/RecentPlayers/UI/PlayersListWidget_Starter.cpp