// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Internationalization/Internationalization.h" #include "OnlineSubsystemTypes.h" #include "Misc/DateTime.h" #include "OnlineDelegateMacros.h" #include "OnlineKeyValuePair.h" #define UE_API ONLINESUBSYSTEM_API ONLINESUBSYSTEM_API DECLARE_LOG_CATEGORY_EXTERN(LogOnlinePresence, Log, All); #define UE_LOG_ONLINE_PRESENCE(Verbosity, Format, ...) \ { \ UE_LOG(LogOnlinePresence, Verbosity, TEXT("%s%s"), ONLINE_LOG_PREFIX, *FString::Printf(Format, ##__VA_ARGS__)); \ } #define UE_CLOG_ONLINE_PRESENCE(Conditional, Verbosity, Format, ...) \ { \ UE_CLOG(Conditional, LogOnlinePresence, Verbosity, TEXT("%s%s"), ONLINE_LOG_PREFIX, *FString::Printf(Format, ##__VA_ARGS__)); \ } /** Type of presence keys */ typedef FString FPresenceKey; /** Type of presence properties - a key/value map */ typedef FOnlineKeyValuePairs FPresenceProperties; /** The default key that will update presence text in the platform's UI */ extern ONLINESUBSYSTEM_API const FString DefaultPresenceKey; /** Custom presence data that is not seen by users but can be polled */ extern ONLINESUBSYSTEM_API const FString CustomPresenceDataKey; /** Name of the client that sent the presence update */ extern ONLINESUBSYSTEM_API const FString DefaultAppIdKey; /** User friendly name of the client that sent the presence update */ extern ONLINESUBSYSTEM_API const FString DefaultProductNameKey; /** Platform of the client that sent the presence update */ extern ONLINESUBSYSTEM_API const FString DefaultPlatformKey; /** Override Id of the client to set the presence state to */ extern ONLINESUBSYSTEM_API const FString OverrideAppIdKey; /** Id of the session for the presence update. @todo samz - SessionId on presence data should be FUniqueNetId not uint64 */ extern ONLINESUBSYSTEM_API const FString DefaultSessionIdKey; /** Resource the client is logged in with */ extern ONLINESUBSYSTEM_API const FString PresenceResourceKey; namespace EOnlinePresenceState { enum Type : uint8 { Online, Offline, Away, ExtendedAway, DoNotDisturb, Chat }; /** * @return the stringified version of the enum passed in */ inline const TCHAR* ToString(EOnlinePresenceState::Type EnumVal) { switch (EnumVal) { case Online: return TEXT("Online"); case Offline: return TEXT("Offline"); case Away: return TEXT("Away"); case ExtendedAway: return TEXT("ExtendedAway"); case DoNotDisturb: return TEXT("DoNotDisturb"); case Chat: return TEXT("Chat"); } return TEXT(""); } /** * @return EOnlinePresenceState from the string passed in */ inline EOnlinePresenceState::Type FromString(const TCHAR* StringVal) { if (FCString::Stricmp(StringVal, TEXT("Online")) == 0) { return EOnlinePresenceState::Online; } else if (FCString::Stricmp(StringVal, TEXT("Offline")) == 0) { return EOnlinePresenceState::Offline; } else if (FCString::Stricmp(StringVal, TEXT("Away")) == 0) { return EOnlinePresenceState::Away; } else if (FCString::Stricmp(StringVal, TEXT("ExtendedAway")) == 0) { return EOnlinePresenceState::ExtendedAway; } else if (FCString::Stricmp(StringVal, TEXT("DoNotDisturb")) == 0) { return EOnlinePresenceState::DoNotDisturb; } else if (FCString::Stricmp(StringVal, TEXT("Chat")) == 0) { return EOnlinePresenceState::Chat; } // Default to Offline / generally unavailable return EOnlinePresenceState::Offline; } static FText OnlineText = NSLOCTEXT("OnlinePresence", "Online", "Online"); static FText OfflineText = NSLOCTEXT("OnlinePresence", "Offline", "Offline"); static FText AwayText = NSLOCTEXT("OnlinePresence", "Away", "Away"); static FText DoNotDisturbText = NSLOCTEXT("OnlinePresence", "DoNotDisturb", "Do Not Disturb"); static FText ChatText = NSLOCTEXT("OnlinePresence", "Chat", "Chat"); /** * @return the loc text version of the enum passed in */ inline const FText ToLocText(EOnlinePresenceState::Type EnumVal) { switch (EnumVal) { case Online: return OnlineText; case Offline: return OfflineText; case ExtendedAway: // falls through to return away text case Away: return AwayText; case DoNotDisturb: return DoNotDisturbText; case Chat: return ChatText; } return FText::GetEmpty(); } } class FOnlineUserPresenceStatus { public: FString StatusStr; EOnlinePresenceState::Type State; FPresenceProperties Properties; FOnlineUserPresenceStatus() : State(EOnlinePresenceState::Offline) { } FString ToDebugString() const { FString PropertiesStr; for (const TPair& Pair : Properties) { PropertiesStr += FString::Printf(TEXT("\n%s : %s"), *Pair.Key, *Pair.Value.ToString()); } return FString::Printf(TEXT("FOnlineUserPresenceStatus {State: %s, Status: %s, Properties: %s}"), EOnlinePresenceState::ToString(State), *StatusStr, *PropertiesStr); } }; /** * Parameters to IOnlinePresence::SetPresence. Similar to FOnlineUserPresenceStatus, but fields requesting update must be explicitly set. */ struct FOnlinePresenceSetPresenceParameters { public: /** Updated status string */ TOptional StatusStr; /** Updated state */ TOptional State; /** Updated properties. Note that this will update all properties, not just the subset specified in Properties. */ TOptional Properties; FString ToDebugString() const { FString PropertiesStr; if (Properties.IsSet()) { for (const TPair& Pair : Properties.GetValue()) { PropertiesStr += FString::Printf(TEXT("\n%s : %s"), *Pair.Key, *Pair.Value.ToString()); } } else { PropertiesStr = TEXT("Unset"); } return FString::Printf(TEXT("FOnlinePresenceSetPresenceParameters {State: %s, Status: %s, Properties: %s}"), State.IsSet() ? EOnlinePresenceState::ToString(State.GetValue()) : TEXT("Unset"), StatusStr.IsSet() ? *StatusStr.GetValue() : TEXT("Unset"), *PropertiesStr); } }; /** * Presence info for an online user returned via IOnlinePresence interface */ class FOnlineUserPresence { public: FUniqueNetIdPtr SessionId; uint32 bIsOnline:1; uint32 bIsPlaying:1; uint32 bIsPlayingThisGame:1; uint32 bIsJoinable:1; uint32 bHasVoiceSupport:1; FDateTime LastOnline; FOnlineUserPresenceStatus Status; /** Constructor */ FOnlineUserPresence() { Reset(); } void Reset() { SessionId = nullptr; bIsOnline = 0; bIsPlaying = 0; bIsPlayingThisGame = 0; bIsJoinable = 0; bHasVoiceSupport = 0; Status = FOnlineUserPresenceStatus(); LastOnline = FDateTime::MaxValue(); } const FString GetPlatform() const { FString ParsedOnlinePlatform = TEXT(""); const FVariantData* VariantOnlinePlatform = Status.Properties.Find(DefaultPlatformKey); if (VariantOnlinePlatform != nullptr && VariantOnlinePlatform->GetType() == EOnlineKeyValuePairDataType::String) { VariantOnlinePlatform->GetValue(ParsedOnlinePlatform); } return ParsedOnlinePlatform; } const FString GetAppId() const { FString Result = TEXT(""); const FVariantData* AppId = Status.Properties.Find(DefaultAppIdKey); const FVariantData* OverrideAppId = Status.Properties.Find(OverrideAppIdKey); if (OverrideAppId != nullptr && OverrideAppId->GetType() == EOnlineKeyValuePairDataType::String) { OverrideAppId->GetValue(Result); } else if (AppId != nullptr && AppId->GetType() == EOnlineKeyValuePairDataType::String) { AppId->GetValue(Result); } return Result; } FString ToDebugString() const { return FString::Printf(TEXT("FOnlineUserPresence {Online: %d Playing: %d ThisGame: %d Joinable: %d VoiceSupport: %d SessionId: %s Status: %s"), bIsOnline, bIsPlaying, bIsPlayingThisGame, bIsJoinable, bHasVoiceSupport, SessionId.IsValid() ? *SessionId->ToDebugString() : TEXT("NULL"), *Status.ToDebugString()); } }; /** * Delegate executed when new presence data is available for a user. * * @param UserId The unique id of the user whose presence was received. * @param Presence The received presence */ DECLARE_MULTICAST_DELEGATE_TwoParams(FOnPresenceReceived, const class FUniqueNetId& /*UserId*/, const TSharedRef& /*Presence*/); typedef FOnPresenceReceived::FDelegate FOnPresenceReceivedDelegate; /** * Delegate executed when the array of presence data for a user changes. * * @param UserId The unique id of the user whose presence was received. * @param PresenceArray The updated presence array */ DECLARE_MULTICAST_DELEGATE_TwoParams(FOnPresenceArrayUpdated, const class FUniqueNetId& /*UserId*/, const TArray >& /*PresenceArray*/); typedef FOnPresenceArrayUpdated::FDelegate FOnPresenceArrayUpdatedDelegate; /** * Interface class for getting and setting rich presence information. */ class IOnlinePresence { public: /** Virtual destructor to force proper child cleanup */ virtual ~IOnlinePresence() {} /** * Delegate executed when setting or querying presence for a user has completed. * * @param UserId The unique id of the user whose presence was set. * @param bWasSuccessful true if the async action completed without error, false if there was an error. */ DECLARE_DELEGATE_TwoParams(FOnPresenceTaskCompleteDelegate, const class FUniqueNetId& /*UserId*/, const bool /*bWasSuccessful*/); /** * Starts an async task that sets presence information for the user. * * @param User The unique id of the user whose presence is being set. * @param Status The collection of state and key/value pairs to set as the user's presence data. * @param Delegate The delegate to be executed when the potentially asynchronous set operation completes. */ virtual void SetPresence(const FUniqueNetId& User, const FOnlineUserPresenceStatus& Status, const FOnPresenceTaskCompleteDelegate& Delegate = FOnPresenceTaskCompleteDelegate()) = 0; /** * Starts an async task that sets presence information for the user. * * @param User The unique id of the user whose presence is being set. * @param Status The collection of state and key/value pairs to set as the user's presence data. * @param Delegate The delegate to be executed when the potentially asynchronous set operation completes. */ UE_API virtual void SetPresence(const FUniqueNetId& User, FOnlinePresenceSetPresenceParameters&& Parameters, const FOnPresenceTaskCompleteDelegate& Delegate = FOnPresenceTaskCompleteDelegate()); /** * Starts an async operation that will update the cache with presence data from all users in the Users array. * On platforms that support multiple keys, this function will query all keys. * * @param Users The list of unique ids of the users to query for presence information. * @param Delegate The delegate to be executed when the potentially asynchronous query operation completes. */ virtual void QueryPresence(const FUniqueNetId& User, const FOnPresenceTaskCompleteDelegate& Delegate = FOnPresenceTaskCompleteDelegate()) = 0; /** * Starts an async operation that will update the cache with presence data from all users in the Users array. * On platforms that support multiple keys, this function will query all keys. * * @param Users The unique id of the user initiating the query for presence information. * @param UserIds The list of unique ids of the users to query for presence information. * @param Delegate The delegate to be executed when the potentially asynchronous query operation completes. */ virtual void QueryPresence(const FUniqueNetId& LocalUserId, const TArray& UserIds, const FOnPresenceTaskCompleteDelegate& Delegate) {}; /** * Delegate executed when new presence data is available for a user. * * @param UserId The unique id of the user whose presence was received. * @param Presence The presence that was received. */ DEFINE_ONLINE_DELEGATE_TWO_PARAM(OnPresenceReceived, const class FUniqueNetId& /*UserId*/, const TSharedRef& /*Presence*/); /** * Delegate executed when the array of presence data for a user changes. * * @param UserId The unique id of the user whose presence was received. * @param PresenceArray The updated presence array */ DEFINE_ONLINE_DELEGATE_TWO_PARAM(OnPresenceArrayUpdated, const class FUniqueNetId& /*UserId*/, const TArray >& /*NewPresenceArray*/); /** * Gets the cached presence information for a user. * * @param User The unique id of the user from which to get presence information. * @param OutPresence If found, a shared pointer to the cached presence data for User will be stored here. * @return Whether the data was found or not. */ virtual EOnlineCachedResult::Type GetCachedPresence(const FUniqueNetId& User, TSharedPtr& OutPresence) = 0; /** * Gets the cached presence information for a user. * * @param LocalUserId The unique id of the local user * @param User The unique id of the user from which to get presence information. * @param AppId The id of the application you want to get the presence of * @param OutPresence If found, a shared pointer to the cached presence data for User will be stored here. * @return Whether the data was found or not. */ virtual EOnlineCachedResult::Type GetCachedPresenceForApp(const FUniqueNetId& LocalUserId, const FUniqueNetId& User, const FString& AppId, TSharedPtr& OutPresence) = 0; }; #undef UE_API