Skip to main content

Put it all together - Recent players - (Unreal Engine module)

Last updated on October 23, 2024

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.

  1. Open the RecentPlayersWidget_Starter class CPP file and replace the InitRecentPlayersList() 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();
    }
    }));
    }
  2. 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);
    }
    }));
    }
  3. 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();
    }
  4. 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.

  1. Open the PlayersListWidget_Starter class CPP file and replace the InitGameSessionPlayersList() 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));
    }
    }
  2. Finally, open the FriendWidgetEntry class CPP file and locate the NativeOnListItemObjectSet() 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