Files
UnrealEngine/Engine/Plugins/Online/OnlineSubsystem/Source/Private/OnlinePartyInterface.cpp
2025-05-18 13:04:45 +08:00

920 lines
22 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Interfaces/OnlinePartyInterface.h"
#include "OnlineSubsystem.h" // IWYU pragma: keep
#include "Policies/CondensedJsonPrintPolicy.h"
#include "Serialization/JsonSerializer.h"
DEFINE_LOG_CATEGORY(LogOnlineParty);
FName DefaultPartyDataNamespace = NAME_Default;
bool FOnlinePartyData::operator==(const FOnlinePartyData& Other) const
{
// Only compare KeyValAttrs, other fields are optimization details
return KeyValAttrs.OrderIndependentCompareEqual(Other.KeyValAttrs);
}
bool FOnlinePartyData::operator!=(const FOnlinePartyData& Other) const
{
return !operator==(Other);
}
void FOnlinePartyData::GetDirtyKeyValAttrs(FOnlineKeyValuePairs<FString, FVariantData>& OutDirtyAttrs, TArray<FString>& OutRemovedAttrs) const
{
for (const FString& PropertyName : DirtyKeys)
{
const FVariantData* PropertyValue = KeyValAttrs.Find(PropertyName);
if (PropertyValue)
{
OutDirtyAttrs.Emplace(PropertyName, *PropertyValue);
}
else
{
OutRemovedAttrs.Emplace(PropertyName);
}
}
}
void FOnlinePartyData::ToJsonFull(FString& JsonString) const
{
JsonString.Empty();
// iterate over key/val attrs and convert each entry to a json string
TSharedRef<FJsonObject> JsonObject(new FJsonObject());
TSharedRef<FJsonObject> JsonProperties = GetAllAttributesAsJsonObject();
JsonObject->SetNumberField(TEXT("Rev"), RevisionCount);
JsonObject->SetObjectField(TEXT("Attrs"), JsonProperties);
auto JsonWriter = TJsonWriterFactory<TCHAR, TCondensedJsonPrintPolicy<TCHAR> >::Create(&JsonString);
FJsonSerializer::Serialize(JsonObject, JsonWriter);
JsonWriter->Close();
}
void FOnlinePartyData::ToJsonDirty(FString& JsonString) const
{
JsonString.Empty();
// iterate over key/val attrs and convert each entry to a json string
TSharedRef<FJsonObject> JsonObject(new FJsonObject());
TSharedRef<FJsonObject> JsonProperties = MakeShared<FJsonObject>();
for (const FString& PropertyName : DirtyKeys)
{
const FVariantData* PropertyValue = KeyValAttrs.Find(PropertyName);
check(PropertyValue);
PropertyValue->AddToJsonObject(JsonProperties, PropertyName);
}
JsonObject->SetNumberField(TEXT("Rev"), RevisionCount);
JsonObject->SetObjectField(TEXT("Attrs"), JsonProperties);
auto JsonWriter = TJsonWriterFactory<TCHAR, TCondensedJsonPrintPolicy<TCHAR> >::Create(&JsonString);
FJsonSerializer::Serialize(JsonObject, JsonWriter);
JsonWriter->Close();
}
TSharedRef<FJsonObject> FOnlinePartyData::GetAllAttributesAsJsonObject() const
{
TSharedRef<FJsonObject> JsonProperties = MakeShared<FJsonObject>();
for (const TPair<FString, FVariantData>& Iterator : KeyValAttrs)
{
const FString& PropertyName = Iterator.Key;
const FVariantData& PropertyValue = Iterator.Value;
PropertyValue.AddToJsonObject(JsonProperties, PropertyName);
}
return JsonProperties;
}
FString FOnlinePartyData::GetAllAttributesAsJsonObjectString() const
{
TSharedRef<FJsonObject> JsonProperties = GetAllAttributesAsJsonObject();
FString JsonString;
auto JsonWriter = TJsonWriterFactory<TCHAR, TCondensedJsonPrintPolicy<TCHAR> >::Create(&JsonString);
FJsonSerializer::Serialize(JsonProperties, JsonWriter);
JsonWriter->Close();
return JsonString;
}
void FOnlinePartyData::FromJson(const FString& JsonString)
{
// json string to key/val attrs
TSharedPtr<FJsonObject> JsonObject;
TSharedRef<TJsonReader<> > JsonReader = TJsonReaderFactory<>::Create(JsonString);
if (FJsonSerializer::Deserialize(JsonReader, JsonObject) &&
JsonObject.IsValid())
{
if (JsonObject->HasTypedField<EJson::Object>(TEXT("Attrs")))
{
const TSharedPtr<FJsonObject>& JsonProperties = JsonObject->GetObjectField(TEXT("Attrs"));
for (const TPair<FString, TSharedPtr<FJsonValue>>& JsonProperty : JsonProperties->Values)
{
FString PropertyName;
FVariantData PropertyData;
if (PropertyData.FromJsonValue(JsonProperty.Key, JsonProperty.Value.ToSharedRef(), PropertyName))
{
KeyValAttrs.Add(PropertyName, PropertyData);
}
}
}
if (JsonObject->HasTypedField<EJson::Number>(TEXT("Rev")))
{
int32 NewRevisionCount = JsonObject->GetIntegerField(TEXT("Rev"));
if ((RevisionCount != 0) && (NewRevisionCount != RevisionCount) && (NewRevisionCount != (RevisionCount + 1)))
{
UE_LOG_ONLINE_PARTY(Warning, TEXT("Unexpected revision received. Current %d, new %d"), RevisionCount, NewRevisionCount);
}
RevisionCount = NewRevisionCount;
}
}
}
FString FPartyInvitationRecipient::ToDebugString() const
{
return FString::Printf(TEXT("Id=[%s], PlatformData=[%s]"), *Id->ToDebugString(), *PlatformData);
}
bool FPartyConfiguration::operator==(const FPartyConfiguration& Other) const
{
return JoinRequestAction == Other.JoinRequestAction &&
PresencePermissions == Other.PresencePermissions &&
InvitePermissions == Other.InvitePermissions &&
bChatEnabled == Other.bChatEnabled &&
bIsAcceptingMembers == Other.bIsAcceptingMembers &&
NotAcceptingMembersReason == Other.NotAcceptingMembersReason &&
MaxMembers == Other.MaxMembers &&
Nickname == Other.Nickname &&
Description == Other.Description &&
Password == Other.Password;
}
bool FPartyConfiguration::operator!=(const FPartyConfiguration& Other) const
{
return !operator==(Other);
}
const TCHAR* ToString(const EPartyState Value)
{
switch (Value)
{
case EPartyState::None:
{
return TEXT("None");
}
case EPartyState::CreatePending:
{
return TEXT("CreatePending");
}
case EPartyState::JoinPending:
{
return TEXT("JoinPending");
}
case EPartyState::LeavePending:
{
return TEXT("LeavePending");
}
case EPartyState::Active:
{
return TEXT("Active");
}
case EPartyState::Disconnected:
{
return TEXT("Disconnected");
}
case EPartyState::CleanUp:
{
return TEXT("CleanUp");
}
}
return TEXT("Unknown");
}
EPartyState EPartyStateFromString(const TCHAR* Value)
{
if (FCString::Stricmp(Value, TEXT("CreatePending")) == 0)
{
return EPartyState::CreatePending;
}
else if (FCString::Stricmp(Value, TEXT("JoinPending")) == 0)
{
return EPartyState::JoinPending;
}
else if (FCString::Stricmp(Value, TEXT("LeavePending")) == 0)
{
return EPartyState::LeavePending;
}
else if (FCString::Stricmp(Value, TEXT("Active")) == 0)
{
return EPartyState::Active;
}
else if (FCString::Stricmp(Value, TEXT("Disconnected")) == 0)
{
return EPartyState::Disconnected;
}
else if (FCString::Stricmp(Value, TEXT("CleanUp")) == 0)
{
return EPartyState::CleanUp;
}
return EPartyState::None;
}
const TCHAR* ToString(const EMemberConnectionStatus Value)
{
switch (Value)
{
case EMemberConnectionStatus::Uninitialized:
return TEXT("Uninitialized");
case EMemberConnectionStatus::Disconnected:
return TEXT("Disconnected");
case EMemberConnectionStatus::Initializing:
return TEXT("Initializing");
case EMemberConnectionStatus::Connected:
return TEXT("Connected");
}
checkNoEntry();
return TEXT("Uninitialized");
}
const TCHAR* ToString(const EMemberExitedReason Value)
{
switch (Value)
{
case EMemberExitedReason::Unknown:
{
return TEXT("Unknown");
}
case EMemberExitedReason::Left:
{
return TEXT("Left");
}
case EMemberExitedReason::Removed:
{
return TEXT("Removed");
}
case EMemberExitedReason::Kicked:
{
return TEXT("Kicked");
}
}
return TEXT("Unknown"); // Same as EMemberExitedReason::Unknown, which is ok because it is only used when we do not have enough information
}
const TCHAR* ToString(const EPartyInvitationRemovedReason Value)
{
switch (Value)
{
case EPartyInvitationRemovedReason::Unknown:
{
return TEXT("Unknown");
}
case EPartyInvitationRemovedReason::Accepted:
{
return TEXT("Accepted");
}
case EPartyInvitationRemovedReason::Declined:
{
return TEXT("Declined");
}
case EPartyInvitationRemovedReason::Cleared:
{
return TEXT("Cleared");
}
case EPartyInvitationRemovedReason::Expired:
{
return TEXT("Expired");
}
case EPartyInvitationRemovedReason::Invalidated:
{
return TEXT("Invalidated");
}
}
return TEXT("Unknown"); // Same as EMemberExitedReason::Unknown, which is ok because it is only used when we do not have enough information
}
const TCHAR* ToString(const EPartyRequestToJoinRemovedReason Value)
{
switch (Value)
{
case EPartyRequestToJoinRemovedReason::Unknown:
{
return TEXT("Unknown");
}
case EPartyRequestToJoinRemovedReason::Cancelled:
{
return TEXT("Cancelled");
}
case EPartyRequestToJoinRemovedReason::Expired:
{
return TEXT("Expired");
}
case EPartyRequestToJoinRemovedReason::Dismissed:
{
return TEXT("Dismissed");
}
case EPartyRequestToJoinRemovedReason::Accepted:
{
return TEXT("Accepted");
}
}
return TEXT("Unknown");
}
const TCHAR* ToString(const ECreatePartyCompletionResult Value)
{
switch (Value)
{
case ECreatePartyCompletionResult::UnknownClientFailure:
{
return TEXT("UnknownClientFailure");
}
case ECreatePartyCompletionResult::AlreadyCreatingParty:
{
return TEXT("AlreadyCreatingParty");
}
case ECreatePartyCompletionResult::AlreadyInParty:
{
return TEXT("AlreadyInParty");
}
case ECreatePartyCompletionResult::FailedToCreateMucRoom:
{
return TEXT("FailedToCreateMucRoom");
}
case ECreatePartyCompletionResult::NoResponse:
{
return TEXT("NoResponse");
}
case ECreatePartyCompletionResult::LoggedOut:
{
return TEXT("LoggedOut");
}
case ECreatePartyCompletionResult::NotPrimaryUser:
{
return TEXT("NotPrimaryUser");
}
case ECreatePartyCompletionResult::UnknownInternalFailure:
{
return TEXT("UnknownInternalFailure");
}
case ECreatePartyCompletionResult::Succeeded:
{
return TEXT("Succeeded");
}
}
return TEXT("Unknown");
}
const TCHAR* ToString(const ESendPartyInvitationCompletionResult Value)
{
switch (Value)
{
case ESendPartyInvitationCompletionResult::NotLoggedIn:
{
return TEXT("NotLoggedIn");
}
case ESendPartyInvitationCompletionResult::InvitePending:
{
return TEXT("InvitePending");
}
case ESendPartyInvitationCompletionResult::AlreadyInParty:
{
return TEXT("AlreadyInParty");
}
case ESendPartyInvitationCompletionResult::PartyFull:
{
return TEXT("PartyFull");
}
case ESendPartyInvitationCompletionResult::NoPermission:
{
return TEXT("NoPermission");
}
case ESendPartyInvitationCompletionResult::RateLimited:
{
return TEXT("RateLimited");
}
case ESendPartyInvitationCompletionResult::UnknownInternalFailure:
{
return TEXT("UnknownInternalFailure");
}
case ESendPartyInvitationCompletionResult::Succeeded:
{
return TEXT("Succeeded");
}
}
return TEXT("Unknown");
}
const TCHAR* ToString(const EJoinPartyCompletionResult Value)
{
switch (Value)
{
case EJoinPartyCompletionResult::UnknownClientFailure:
{
return TEXT("UnknownClientFailure");
}
case EJoinPartyCompletionResult::BadBuild:
{
return TEXT("BadBuild");
}
case EJoinPartyCompletionResult::InvalidAccessKey:
{
return TEXT("InvalidAccessKey");
}
case EJoinPartyCompletionResult::AlreadyInLeadersJoiningList:
{
return TEXT("AlreadyInLeadersJoiningList");
}
case EJoinPartyCompletionResult::AlreadyInLeadersPartyRoster:
{
return TEXT("AlreadyInLeadersPartyRoster");
}
case EJoinPartyCompletionResult::NoSpace:
{
return TEXT("NoSpace");
}
case EJoinPartyCompletionResult::NotApproved:
{
return TEXT("NotApproved");
}
case EJoinPartyCompletionResult::RequesteeNotMember:
{
return TEXT("RequesteeNotMember");
}
case EJoinPartyCompletionResult::RequesteeNotLeader:
{
return TEXT("RequesteeNotLeader");
}
case EJoinPartyCompletionResult::NoResponse:
{
return TEXT("NoResponse");
}
case EJoinPartyCompletionResult::LoggedOut:
{
return TEXT("LoggedOut");
}
PRAGMA_DISABLE_DEPRECATION_WARNINGS
case EJoinPartyCompletionResult::UnableToRejoin:
PRAGMA_ENABLE_DEPRECATION_WARNINGS
{
return TEXT("UnableToRejoin");
}
case EJoinPartyCompletionResult::IncompatiblePlatform:
{
return TEXT("IncompatiblePlatform");
}
case EJoinPartyCompletionResult::AlreadyJoiningParty:
{
return TEXT("AlreadyJoiningParty");
}
case EJoinPartyCompletionResult::AlreadyInParty:
{
return TEXT("AlreadyInParty");
}
case EJoinPartyCompletionResult::JoinInfoInvalid:
{
return TEXT("JoinInfoInvalid");
}
case EJoinPartyCompletionResult::AlreadyInPartyOfSpecifiedType:
{
return TEXT("AlreadyInPartyOfSpecifiedType");
}
case EJoinPartyCompletionResult::MessagingFailure:
{
return TEXT("MessagingFailure");
}
case EJoinPartyCompletionResult::GameSpecificReason:
{
return TEXT("GameSpecificReason");
}
case EJoinPartyCompletionResult::MismatchedApp:
{
return TEXT("MismatchedApp");
}
case EJoinPartyCompletionResult::Succeeded:
{
return TEXT("Succeeded");
}
case EJoinPartyCompletionResult::UnknownInternalFailure:
{
return TEXT("DeprecatedUnknownInternalFailure");
}
}
return TEXT("Unknown");
}
const TCHAR* ToString(const ELeavePartyCompletionResult Value)
{
switch (Value)
{
case ELeavePartyCompletionResult::UnknownClientFailure:
{
return TEXT("UnknownClientFailure");
}
case ELeavePartyCompletionResult::NoResponse:
{
return TEXT("NoResponse");
}
case ELeavePartyCompletionResult::LoggedOut:
{
return TEXT("LoggedOut");
}
case ELeavePartyCompletionResult::UnknownParty:
{
return TEXT("UnknownParty");
}
case ELeavePartyCompletionResult::LeavePending:
{
return TEXT("LeavePending");
}
case ELeavePartyCompletionResult::Succeeded:
{
return TEXT("Succeeded");
}
case ELeavePartyCompletionResult::UnknownLocalUser:
{
return TEXT("DeprecatedUnknownLocalUser");
}
case ELeavePartyCompletionResult::NotMember:
{
return TEXT("DeprecatedNotMember");
}
case ELeavePartyCompletionResult::MessagingFailure:
{
return TEXT("DeprecatedMessagingFailure");
}
case ELeavePartyCompletionResult::UnknownTransportFailure:
{
return TEXT("DeprecatedUnknownTransportFailure");
}
case ELeavePartyCompletionResult::UnknownInternalFailure:
{
return TEXT("DeprecatedUnknownInternalFailure");
}
}
return TEXT("Unknown");
}
const TCHAR* ToString(const EUpdateConfigCompletionResult Value)
{
switch (Value)
{
case EUpdateConfigCompletionResult::UnknownClientFailure:
{
return TEXT("UnknownClientFailure");
}
case EUpdateConfigCompletionResult::UnknownParty:
{
return TEXT("UnknownParty");
}
case EUpdateConfigCompletionResult::LocalMemberNotMember:
{
return TEXT("LocalMemberNotMember");
}
case EUpdateConfigCompletionResult::LocalMemberNotLeader:
{
return TEXT("LocalMemberNotLeader");
}
case EUpdateConfigCompletionResult::RemoteMemberNotMember:
{
return TEXT("RemoteMemberNotMember");
}
case EUpdateConfigCompletionResult::MessagingFailure:
{
return TEXT("MessagingFailure");
}
case EUpdateConfigCompletionResult::NoResponse:
{
return TEXT("NoResponse");
}
case EUpdateConfigCompletionResult::UnknownInternalFailure:
{
return TEXT("UnknownInternalFailure");
}
case EUpdateConfigCompletionResult::Succeeded:
{
return TEXT("Succeeded");
}
}
return TEXT("Unknown");
}
const TCHAR* ToString(const EKickMemberCompletionResult Value)
{
switch (Value)
{
case EKickMemberCompletionResult::UnknownClientFailure:
{
return TEXT("UnknownClientFailure");
}
case EKickMemberCompletionResult::UnknownParty:
{
return TEXT("UnknownParty");
}
case EKickMemberCompletionResult::LocalMemberNotMember:
{
return TEXT("LocalMemberNotMember");
}
case EKickMemberCompletionResult::LocalMemberNotLeader:
{
return TEXT("LocalMemberNotLeader");
}
case EKickMemberCompletionResult::RemoteMemberNotMember:
{
return TEXT("RemoteMemberNotMember");
}
case EKickMemberCompletionResult::MessagingFailure:
{
return TEXT("MessagingFailure");
}
case EKickMemberCompletionResult::NoResponse:
{
return TEXT("NoResponse");
}
case EKickMemberCompletionResult::LoggedOut:
{
return TEXT("LoggedOut");
}
case EKickMemberCompletionResult::UnknownInternalFailure:
{
return TEXT("UnknownInternalFailure");
}
case EKickMemberCompletionResult::Succeeded:
{
return TEXT("Succeeded");
}
}
return TEXT("Unknown");
}
const TCHAR* ToString(const EPromoteMemberCompletionResult Value)
{
switch (Value)
{
case EPromoteMemberCompletionResult::UnknownClientFailure:
{
return TEXT("UnknownClientFailure");
}
case EPromoteMemberCompletionResult::UnknownParty:
{
return TEXT("UnknownParty");
}
case EPromoteMemberCompletionResult::LocalMemberNotMember:
{
return TEXT("LocalMemberNotMember");
}
case EPromoteMemberCompletionResult::LocalMemberNotLeader:
{
return TEXT("LocalMemberNotLeader");
}
case EPromoteMemberCompletionResult::TargetIsSelf:
{
return TEXT("TargetIsSelf");
}
case EPromoteMemberCompletionResult::TargetNotMember:
{
return TEXT("TargetNotMember");
}
case EPromoteMemberCompletionResult::MessagingFailure:
{
return TEXT("MessagingFailure");
}
case EPromoteMemberCompletionResult::NoResponse:
{
return TEXT("NoResponse");
}
case EPromoteMemberCompletionResult::LoggedOut:
{
return TEXT("LoggedOut");
}
case EPromoteMemberCompletionResult::UnknownInternalFailure:
{
return TEXT("UnknownInternalFailure");
}
case EPromoteMemberCompletionResult::Succeeded:
{
return TEXT("Succeeded");
}
}
return TEXT("Unknown");
}
const TCHAR* ToString(const EInvitationResponse Value)
{
switch (Value)
{
case EInvitationResponse::UnknownFailure:
{
return TEXT("UnknownFailure");
}
case EInvitationResponse::BadBuild:
{
return TEXT("BadBuild");
}
case EInvitationResponse::Rejected:
{
return TEXT("Rejected");
}
case EInvitationResponse::Accepted:
{
return TEXT("Accepted");
}
}
return TEXT("Unknown");
}
const TCHAR* ToString(const PartySystemPermissions::EPermissionType Value)
{
switch (Value)
{
case PartySystemPermissions::EPermissionType::Noone:
{
return TEXT("Noone");
}
case PartySystemPermissions::EPermissionType::Leader:
{
return TEXT("Leader");
}
case PartySystemPermissions::EPermissionType::Friends:
{
return TEXT("Friends");
}
case PartySystemPermissions::EPermissionType::Anyone:
{
return TEXT("Anyone");
}
}
return TEXT("Unknown");
}
PartySystemPermissions::EPermissionType PartySystemPermissionTypeFromString(const TCHAR* Value)
{
if (FCString::Stricmp(Value, TEXT("Leader")) == 0)
{
return PartySystemPermissions::EPermissionType::Leader;
}
else if (FCString::Stricmp(Value, TEXT("Friends")) == 0)
{
return PartySystemPermissions::EPermissionType::Friends;
}
else if (FCString::Stricmp(Value, TEXT("Anyone")) == 0)
{
return PartySystemPermissions::EPermissionType::Anyone;
}
return PartySystemPermissions::EPermissionType::Noone;
}
const TCHAR* ToString(const EJoinRequestAction Value)
{
switch (Value)
{
case EJoinRequestAction::Manual:
{
return TEXT("Manual");
}
case EJoinRequestAction::AutoApprove:
{
return TEXT("AutoApprove");
}
case EJoinRequestAction::AutoReject:
{
return TEXT("AutoReject");
}
}
return TEXT("Unknown");
}
const TCHAR* ToString(const ERequestToJoinPartyCompletionResult Value)
{
switch (Value)
{
case ERequestToJoinPartyCompletionResult::ValidationFailure:
{
return TEXT("ValidationFailure");
}
case ERequestToJoinPartyCompletionResult::NotAuthorized:
{
return TEXT("NotAuthorized");
}
case ERequestToJoinPartyCompletionResult::Forbidden:
{
return TEXT("Forbidden");
}
case ERequestToJoinPartyCompletionResult::UserNotFound:
{
return TEXT("UserNotFound");
}
case ERequestToJoinPartyCompletionResult::AlreadyExists:
{
return TEXT("AlreadyExists");
}
case ERequestToJoinPartyCompletionResult::RateLimited:
{
return TEXT("RateLimited");
}
case ERequestToJoinPartyCompletionResult::UnknownInternalFailure:
{
return TEXT("UnknownInternalFailure");
}
case ERequestToJoinPartyCompletionResult::Succeeded:
{
return TEXT("Succeeded");
}
}
return TEXT("Unknown");
}
EJoinRequestAction JoinRequestActionFromString(const TCHAR* Value)
{
if (FCString::Stricmp(Value, TEXT("AutoApprove")) == 0)
{
return EJoinRequestAction::AutoApprove;
}
else if (FCString::Stricmp(Value, TEXT("AutoReject")) == 0)
{
return EJoinRequestAction::AutoReject;
}
return EJoinRequestAction::Manual;
}
FString ToDebugString(const FPartyConfiguration& PartyConfiguration)
{
return FString::Printf(TEXT("JoinRequestAction(%s) RemoveOnDisconnect(%d) Publish(%s) Chat(%d) Invite(%s) Accepting(%d) Not Accepting Reason(%d) MaxMembers: %d Nickname: %s Description: %s Password: %s"),
ToString(PartyConfiguration.JoinRequestAction),
PartyConfiguration.bShouldRemoveOnDisconnection,
ToString(PartyConfiguration.PresencePermissions),
PartyConfiguration.bChatEnabled,
ToString(PartyConfiguration.InvitePermissions),
PartyConfiguration.bIsAcceptingMembers,
PartyConfiguration.NotAcceptingMembersReason,
PartyConfiguration.MaxMembers,
*PartyConfiguration.Nickname,
*PartyConfiguration.Description,
PartyConfiguration.Password.IsEmpty() ? TEXT("not set") : *PartyConfiguration.Password
);
}
FString ToDebugString(const IOnlinePartyJoinInfo& JoinInfo)
{
return JoinInfo.ToDebugString();
}
/**
* Dump key/value pairs for debugging
*/
FString ToDebugString(const FOnlineKeyValuePairs<FString, FVariantData>& KeyValAttrs)
{
FString Result;
bool bPrintedAny = false;
for (const TPair<FString, FVariantData>& Iterator : KeyValAttrs)
{
if (bPrintedAny)
{
Result += TEXT(",");
}
Result += FString::Printf(TEXT("[%s=%s]"), *Iterator.Key, *Iterator.Value.ToString());
bPrintedAny = true;
}
return Result;
}
/**
* Dump state about the party data for debugging
*/
FString ToDebugString(const FOnlinePartyData& PartyData)
{
FString Result;
int32 TotalBytesPerSec = PartyData.TotalPackets ? (PartyData.TotalBytes / PartyData.TotalPackets) : 0;
int32 TotalEffectiveBytesPerSec = PartyData.TotalPackets ? (PartyData.TotalEffectiveBytes / PartyData.TotalPackets) : 0;
Result += FString::Printf(TEXT("%dB [%d B/pkt], %dB [%d B/pkt], Rev: %d,"),
PartyData.TotalBytes, TotalBytesPerSec,
PartyData.TotalEffectiveBytes, TotalEffectiveBytesPerSec,
PartyData.RevisionCount);
Result += ToDebugString(PartyData.GetKeyValAttrs());
return Result;
}
FString IOnlinePartyJoinInfo::ToDebugString() const
{
return FString::Printf(TEXT("SourceUserId(%s) SourceDisplayName(%s) PartyId(%s) HasKey(%d) HasPassword(%d) IsAcceptingMembers(%d) NotAcceptingReason(%d)"),
*(GetSourceUserId()->ToDebugString()),
*(GetSourceDisplayName()),
*(GetPartyId()->ToDebugString()),
HasKey() ? 1 : 0, HasPassword() ? 1 : 0,
IsAcceptingMembers() ? 1 : 0,
GetNotAcceptingReason());
};
bool IOnlinePartySystem::RejoinParty(const FUniqueNetId& LocalUserId, const FOnlinePartyId& PartyId, const FOnlinePartyTypeId& PartyTypeId, const TArray<FUniqueNetIdRef>& FormerMembers, const FOnJoinPartyComplete& Delegate)
{
return false;
}
bool IOnlinePartySystem::LeaveParty(const FUniqueNetId& LocalUserId, const FOnlinePartyId& PartyId, const FOnLeavePartyComplete& Delegate)
{
return LeaveParty(LocalUserId, PartyId, true, Delegate);
}