Put it all together - Introduction to party - (Unreal Engine module)
Connect the UI to display, leave, send invite, kick, and promote party member
Open the
PartyWidgetEntry_Starter
class CPP file and add the code below to theSetPartyMember()
function. This will display the party member display name and avatar.void UPartyWidgetEntry_Starter::SetPartyMember(const FUserOnlineAccountAccelByte& PartyMember, const bool bIsLeader)
{
W_PartyMember->SetNetId(PartyMember.GetUserId());
// Display party member information.
Ws_PartyMemberState->SetActiveWidget(W_PartyMemberPanel);
// Set display name.
if (PartyMember.GetDisplayName().IsEmpty())
{
const FUniqueNetIdAccelByteUserRef MemberABId = StaticCastSharedRef<const FUniqueNetIdAccelByteUser>(PartyMember.GetUserId());
W_PartyMember->SetUsername(FText::FromString(UTutorialModuleOnlineUtility::GetUserDefaultDisplayName(MemberABId.Get())));
}
else
{
W_PartyMember->SetUsername(FText::FromString(PartyMember.GetDisplayName()));
}
// Set avatar
FString AvatarURL;
PartyMember.GetUserAttribute(ACCELBYTE_ACCOUNT_GAME_AVATAR_URL, AvatarURL);
W_PartyMember->SetAvatar(AvatarURL);
// Set color tint.
const FLinearColor MemberColor = bIsLeader ? PartyLeaderColor : PartyMemberColor;
SetPartyMemberColor(MemberColor);
W_PartyMember->SetTextColor(MemberColor);
W_PartyMember->SetAvatarTint(AvatarURL.IsEmpty() ? MemberColor : FLinearColor::White);
// Set cached party member data as friend data.
// Will be used to open player action menu widget.
if (!CachedFriendData)
{
CachedFriendData = NewObject<UFriendData>();
}
CachedFriendData->UserId = PartyMember.GetUserId();
CachedFriendData->DisplayName = PartyMember.GetDisplayName();
CachedFriendData->AvatarURL = AvatarURL;
W_PartyMember->ActivateWidget();
}Next, open the
PartyWidget_Starter
class CPP file and add the code below to theDisplayParty()
function. This will query the party member information and display them.void UPartyWidget_Starter::DisplayParty()
{
// Show loading.
Btn_Leave->SetVisibility(ESlateVisibility::Collapsed);
Ws_Party->SetWidgetState(EAccelByteWarsWidgetSwitcherState::Loading);
// Collect party member user IDs.
const FUniqueNetIdPtr UserId = PartyOnlineSession->GetLocalPlayerUniqueNetId(GetOwningPlayer());
TArray<FUniqueNetIdRef> PartyMemberUserIds = PartyOnlineSession->GetPartyMembers();
// If not in any party, then only include player user ID to query its information.
if (PartyMemberUserIds.IsEmpty())
{
PartyMemberUserIds.Add(UserId.ToSharedRef());
}
// Query and display party member information.
if (UStartupSubsystem* StartupSubsystem = GetWorld()->GetGameInstance()->GetSubsystem<UStartupSubsystem>())
{
StartupSubsystem->QueryUserInfo(
PartyOnlineSession->GetLocalUserNumFromPlayerController(GetOwningPlayer()),
PartyMemberUserIds,
FOnQueryUsersInfoCompleteDelegate::CreateWeakLambda(this, [this](
const FOnlineError& Error,
const TArray<TSharedPtr<FUserOnlineAccountAccelByte>> UsersInfo)
{
// If party members are changed during query, then re-query the party members' information.
const bool bIsInParty = !PartyOnlineSession->GetPartyMembers().IsEmpty();
if (bIsInParty)
{
if (UsersInfo.Num() != PartyOnlineSession->GetPartyMembers().Num())
{
DisplayParty();
return;
}
for (int32 i = 0; i < UsersInfo.Num(); i++)
{
if (!UsersInfo[i]->GetUserId()->IsValid() ||
!PartyOnlineSession->GetPartyMembers()[i]->IsValid() ||
PartyOnlineSession->GetPartyMembers()[i].Get() != UsersInfo[i]->GetUserId().Get())
{
DisplayParty();
return;
}
}
}
// Request failed.
if (!Error.bSucceeded)
{
Ws_Party->SetWidgetState(EAccelByteWarsWidgetSwitcherState::Error);
return;
}
// Clean up last party member list.
Ws_Party->SetWidgetState(EAccelByteWarsWidgetSwitcherState::Not_Empty);
Hb_Party->ClearChildren();
Btn_Leave->SetVisibility(ESlateVisibility::Visible);
// Display party members.
for (int32 i = 0; i < MaxPartyMembers; i++)
{
if (i < UsersInfo.Num() && !UsersInfo[i])
{
continue;
}
const TWeakObjectPtr<UPartyWidgetEntry> PartyMemberEntry =
MakeWeakObjectPtr<UPartyWidgetEntry>(
CreateWidget<UPartyWidgetEntry>(this, PartyWidgetEntryClass.Get()));
Hb_Party->AddChild(PartyMemberEntry.Get());
// Display party member information.
if (i < UsersInfo.Num())
{
/* Mark party member as leader if valid.
* If not in any party, then assume the player as the leader.*/
PartyMemberEntry->SetPartyMember(*UsersInfo[i],
PartyOnlineSession->IsPartyLeader(UsersInfo[i]->GetUserId()) ||
!bIsInParty);
}
// Display button to add more party members.
else
{
PartyMemberEntry->ResetPartyMember();
}
}
}));
}
}In the same file, add the code below to the
OnLeaveButtonClicked()
function. This will trigger to leave the party when the leave button is clicked.void UPartyWidget_Starter::OnLeaveButtonClicked()
{
// Leave current party.
PartyOnlineSession->LeaveParty(PartyOnlineSession->GetLocalUserNumFromPlayerController(GetOwningPlayer()));
DeactivateWidget();
}In the same file, add the code below to the
NativeOnActivated()
function. This function will listen to the party event to update the displayed party member on the UI.void UPartyWidget_Starter::NativeOnActivated()
{
Super::NativeOnActivated();
Btn_Leave->OnClicked().Clear();
Btn_Leave->OnClicked().AddUObject(this, &ThisClass::OnLeaveButtonClicked);
// Update the displayed party members on any changes.
PartyOnlineSession->GetOnCreatePartyCompleteDelegates()->AddWeakLambda(this, [this](FName SessionName, bool bWasSuccessful)
{
DisplayParty();
});
PartyOnlineSession->GetOnLeavePartyCompleteDelegates()->AddWeakLambda(this, [this](FName SessionName, bool bWasSuccessful)
{
DisplayParty();
});
PartyOnlineSession->GetOnPartyMembersChangeDelegates()->AddWeakLambda(this, [this](FName SessionName, const FUniqueNetId& Participant, bool bJoined)
{
DisplayParty();
});
PartyOnlineSession->GetOnPartySessionUpdateReceivedDelegates()->AddWeakLambda(this, [this](FName SessionName)
{
DisplayParty();
});
DisplayParty();
}In the same file, add the code below to the
NativeOnDeactivated()
function. This unbinds the party events after the party widget is deactivated.void UPartyWidget_Starter::NativeOnDeactivated()
{
Btn_Leave->OnClicked().Clear();
// Clear online delegates.
PartyOnlineSession->GetOnCreatePartyCompleteDelegates()->RemoveAll(this);
PartyOnlineSession->GetOnLeavePartyCompleteDelegates()->RemoveAll(this);
PartyOnlineSession->GetOnPartyMembersChangeDelegates()->RemoveAll(this);
PartyOnlineSession->GetOnPartySessionUpdateReceivedDelegates()->RemoveAll(this);
Super::NativeOnDeactivated();
}The code to show party members on the UI is complete. Now, you must call several functions to perform party-related actions. Open the
PartyOnlineSession_Starter
class CPP file and add the code below to the respective predefined functions. What it does is call the respective party actions when the party action button is clicked. These action buttons are the generated buttons mentioned in the Add a party menu tutorial of this module.void UPartyOnlineSession_Starter::OnInviteToPartyButtonClicked(const int32 LocalUserNum, const FUniqueNetIdPtr& Invitee)
{
// Disable the button to avoid spamming.
if (InviteToPartyButtonMetadata)
{
if (UAccelByteWarsButtonBase* Button =
Cast<UAccelByteWarsButtonBase>(InviteToPartyButtonMetadata->GenerateWidgetRef))
{
Button->SetIsInteractionEnabled(false);
}
}
SendPartyInvite(LocalUserNum, Invitee);
}void UPartyOnlineSession_Starter::OnKickPlayerFromPartyButtonClicked(const int32 LocalUserNum, const FUniqueNetIdPtr& KickedPlayer)
{
// Disable the button to avoid spamming.
if (KickPlayerFromPartyButtonMetadata)
{
if (UAccelByteWarsButtonBase* Button =
Cast<UAccelByteWarsButtonBase>(KickPlayerFromPartyButtonMetadata->GenerateWidgetRef))
{
Button->SetIsInteractionEnabled(false);
}
}
KickPlayerFromParty(LocalUserNum, KickedPlayer);
}void UPartyOnlineSession_Starter::OnPromotePartyLeaderButtonClicked(const int32 LocalUserNum, const FUniqueNetIdPtr& NewLeader)
{
// Disable the button to avoid spamming.
if (PromotePartyLeaderButtonMetadata)
{
if (UAccelByteWarsButtonBase* Button =
Cast<UAccelByteWarsButtonBase>(PromotePartyLeaderButtonMetadata->GenerateWidgetRef))
{
Button->SetIsInteractionEnabled(false);
}
}
PromotePartyLeader(LocalUserNum, NewLeader);
}
Resources
The files used in this tutorial section are available in the Unreal Byte Wars GitHub repository.