搬了lyra的hudlayout

This commit is contained in:
2023-08-28 03:38:23 +08:00
parent b9666b7fe7
commit c90b2d2956
343 changed files with 10665 additions and 2 deletions

View File

@@ -0,0 +1,38 @@
{
"FileVersion": 3,
"Version": 1,
"VersionName": "1.0",
"FriendlyName": "CommonUser",
"Description": "Provides gameplay code and blueprint wrappers for online and platform operations.",
"Category": "Gameplay",
"CreatedBy": "Epic Games, Inc.",
"CreatedByURL": "https://www.epicgames.com",
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "",
"CanContainContent": false,
"IsBetaVersion": false,
"IsExperimentalVersion": false,
"Installed": false,
"Modules": [
{
"Name": "CommonUser",
"Type": "Runtime",
"LoadingPhase": "Default"
}
],
"Plugins": [
{
"Name": "OnlineSubsystem",
"Enabled": true
},
{
"Name": "OnlineSubsystemUtils",
"Enabled": true
},
{
"Name": "OnlineServices",
"Enabled": true
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,70 @@
// Copyright Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
public class CommonUser : ModuleRules
{
public CommonUser(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
bool bUseOnlineSubsystemV1 = true;
PublicIncludePaths.AddRange(
new string[] {
// ... add public include paths required here ...
}
);
PrivateIncludePaths.AddRange(
new string[] {
// ... add other private include paths required here ...
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
"CoreOnline",
"GameplayTags",
// ... add other public dependencies that you statically link with here ...
}
);
if (bUseOnlineSubsystemV1)
{
PublicDependencyModuleNames.Add("OnlineSubsystem");
}
else
{
PublicDependencyModuleNames.Add("OnlineServicesInterface");
}
PrivateDependencyModuleNames.Add("OnlineSubsystemUtils");
PublicDefinitions.Add("COMMONUSER_OSSV1=" + (bUseOnlineSubsystemV1 ? "1" : "0"));
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreOnline",
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"ApplicationCore",
"InputCore",
// ... add private dependencies that you statically link with here ...
}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);
}
}

View File

@@ -0,0 +1,105 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#include "AsyncAction_CommonUserInitialize.h"
#include "GenericPlatform/GenericPlatformInputDeviceMapper.h"
#include "TimerManager.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(AsyncAction_CommonUserInitialize)
UAsyncAction_CommonUserInitialize* UAsyncAction_CommonUserInitialize::InitializeForLocalPlay(UCommonUserSubsystem* Target, int32 LocalPlayerIndex, FInputDeviceId PrimaryInputDevice, bool bCanUseGuestLogin)
{
if (!PrimaryInputDevice.IsValid())
{
// Set to default device
PrimaryInputDevice = IPlatformInputDeviceMapper::Get().GetDefaultInputDevice();
}
UAsyncAction_CommonUserInitialize* Action = NewObject<UAsyncAction_CommonUserInitialize>();
Action->RegisterWithGameInstance(Target);
if (Target && Action->IsRegistered())
{
Action->Subsystem = Target;
Action->Params.RequestedPrivilege = ECommonUserPrivilege::CanPlay;
Action->Params.LocalPlayerIndex = LocalPlayerIndex;
Action->Params.PrimaryInputDevice = PrimaryInputDevice;
Action->Params.bCanUseGuestLogin = bCanUseGuestLogin;
Action->Params.bCanCreateNewLocalPlayer = true;
}
else
{
Action->SetReadyToDestroy();
}
return Action;
}
UAsyncAction_CommonUserInitialize* UAsyncAction_CommonUserInitialize::LoginForOnlinePlay(UCommonUserSubsystem* Target, int32 LocalPlayerIndex)
{
UAsyncAction_CommonUserInitialize* Action = NewObject<UAsyncAction_CommonUserInitialize>();
Action->RegisterWithGameInstance(Target);
if (Target && Action->IsRegistered())
{
Action->Subsystem = Target;
Action->Params.RequestedPrivilege = ECommonUserPrivilege::CanPlayOnline;
Action->Params.LocalPlayerIndex = LocalPlayerIndex;
Action->Params.bCanCreateNewLocalPlayer = false;
}
else
{
Action->SetReadyToDestroy();
}
return Action;
}
void UAsyncAction_CommonUserInitialize::HandleFailure()
{
const UCommonUserInfo* UserInfo = nullptr;
if (Subsystem.IsValid())
{
UserInfo = Subsystem->GetUserInfoForLocalPlayerIndex(Params.LocalPlayerIndex);
}
HandleInitializationComplete(UserInfo, false, NSLOCTEXT("CommonUser", "LoginFailedEarly", "Unable to start login process"), Params.RequestedPrivilege, Params.OnlineContext);
}
void UAsyncAction_CommonUserInitialize::HandleInitializationComplete(const UCommonUserInfo* UserInfo, bool bSuccess, FText Error, ECommonUserPrivilege RequestedPrivilege, ECommonUserOnlineContext OnlineContext)
{
if (ShouldBroadcastDelegates())
{
OnInitializationComplete.Broadcast(UserInfo, bSuccess, Error, RequestedPrivilege, OnlineContext);
}
SetReadyToDestroy();
}
void UAsyncAction_CommonUserInitialize::Activate()
{
if (Subsystem.IsValid())
{
Params.OnUserInitializeComplete.BindUFunction(this, GET_FUNCTION_NAME_CHECKED(UAsyncAction_CommonUserInitialize, HandleInitializationComplete));
bool bSuccess = Subsystem->TryToInitializeUser(Params);
if (!bSuccess)
{
// Call failure next frame
FTimerManager* TimerManager = GetTimerManager();
if (TimerManager)
{
TimerManager->SetTimerForNextTick(FTimerDelegate::CreateUObject(this, &UAsyncAction_CommonUserInitialize::HandleFailure));
}
}
}
else
{
SetReadyToDestroy();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,22 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#include "CommonUserModule.h"
#include "Modules/ModuleManager.h"
#define LOCTEXT_NAMESPACE "FCommonUserModule"
void FCommonUserModule::StartupModule()
{
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
}
void FCommonUserModule::ShutdownModule()
{
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
// we call this function before unloading the module.
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FCommonUserModule, CommonUser)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#include "CommonUserTypes.h"
#include "OnlineError.h"
void FOnlineResultInformation::FromOnlineError(const FOnlineErrorType& InOnlineError)
{
#if COMMONUSER_OSSV1
bWasSuccessful = InOnlineError.WasSuccessful();
ErrorId = InOnlineError.GetErrorCode();
ErrorText = InOnlineError.GetErrorMessage();
#else
bWasSuccessful = InOnlineError != UE::Online::Errors::Success();
ErrorId = InOnlineError.GetErrorId();
ErrorText = InOnlineError.GetText();
#endif
}

View File

@@ -0,0 +1,64 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CommonUserSubsystem.h"
#include "Engine/CancellableAsyncAction.h"
#include "AsyncAction_CommonUserInitialize.generated.h"
enum class ECommonUserOnlineContext : uint8;
enum class ECommonUserPrivilege : uint8;
struct FInputDeviceId;
class FText;
class UObject;
struct FFrame;
/**
* Async action to handle different functions for initializing users
*/
UCLASS()
class COMMONUSER_API UAsyncAction_CommonUserInitialize : public UCancellableAsyncAction
{
GENERATED_BODY()
public:
/**
* Initializes a local player with the common user system, which includes doing platform-specific login and privilege checks.
* When the process has succeeded or failed, it will broadcast the OnInitializationComplete delegate.
*
* @param LocalPlayerIndex Desired index of ULocalPlayer in Game Instance, 0 will be primary player and 1+ for local multiplayer
* @param PrimaryInputDevice Primary input device for the user, if invalid will use the system default
* @param bCanUseGuestLogin If true, this player can be a guest without a real system net id
*/
UFUNCTION(BlueprintCallable, Category = CommonUser, meta = (BlueprintInternalUseOnly = "true"))
static UAsyncAction_CommonUserInitialize* InitializeForLocalPlay(UCommonUserSubsystem* Target, int32 LocalPlayerIndex, FInputDeviceId PrimaryInputDevice, bool bCanUseGuestLogin);
/**
* Attempts to log an existing user into the platform-specific online backend to enable full online play
* When the process has succeeded or failed, it will broadcast the OnInitializationComplete delegate.
*
* @param LocalPlayerIndex Index of existing LocalPlayer in Game Instance
*/
UFUNCTION(BlueprintCallable, Category = CommonUser, meta = (BlueprintInternalUseOnly = "true"))
static UAsyncAction_CommonUserInitialize* LoginForOnlinePlay(UCommonUserSubsystem* Target, int32 LocalPlayerIndex);
/** Call when initialization succeeds or fails */
UPROPERTY(BlueprintAssignable)
FCommonUserOnInitializeCompleteMulticast OnInitializationComplete;
/** Fail and send callbacks if needed */
void HandleFailure();
/** Wrapper delegate, will pass on to OnInitializationComplete if appropriate */
UFUNCTION()
virtual void HandleInitializationComplete(const UCommonUserInfo* UserInfo, bool bSuccess, FText Error, ECommonUserPrivilege RequestedPrivilege, ECommonUserOnlineContext OnlineContext);
protected:
/** Actually start the initialization */
virtual void Activate() override;
TWeakObjectPtr<UCommonUserSubsystem> Subsystem;
FCommonUserInitializeParams Params;
};

View File

@@ -0,0 +1,382 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CommonUserTypes.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "UObject/ObjectPtr.h"
#include "UObject/StrongObjectPtr.h"
#include "UObject/PrimaryAssetId.h"
#include "UObject/WeakObjectPtr.h"
class APlayerController;
class ULocalPlayer;
namespace ETravelFailure { enum Type : int; }
struct FOnlineResultInformation;
#if COMMONUSER_OSSV1
#include "Interfaces/OnlineSessionInterface.h"
#include "Public/OnlineSessionSettings.h"
#else
#include "Online/Lobbies.h"
#endif // COMMONUSER_OSSV1
#include "CommonSessionSubsystem.generated.h"
class UWorld;
class FCommonSession_OnlineSessionSettings;
#if COMMONUSER_OSSV1
class FCommonOnlineSearchSettingsOSSv1;
using FCommonOnlineSearchSettings = FCommonOnlineSearchSettingsOSSv1;
#else
class FCommonOnlineSearchSettingsOSSv2;
using FCommonOnlineSearchSettings = FCommonOnlineSearchSettingsOSSv2;
#endif // COMMONUSER_OSSV1
//////////////////////////////////////////////////////////////////////
// UCommonSession_HostSessionRequest
/** Specifies the online features and connectivity that should be used for a game session */
UENUM(BlueprintType)
enum class ECommonSessionOnlineMode : uint8
{
Offline,
LAN,
Online
};
/** A request object that stores the parameters used when hosting a gameplay session */
UCLASS(BlueprintType)
class COMMONUSER_API UCommonSession_HostSessionRequest : public UObject
{
GENERATED_BODY()
public:
/** Indicates if the session is a full online session or a different type */
UPROPERTY(BlueprintReadWrite, Category=Session)
ECommonSessionOnlineMode OnlineMode;
/** True if this request should create a player-hosted lobbies if available */
UPROPERTY(BlueprintReadWrite, Category = Session)
bool bUseLobbies;
/** String used during matchmaking to specify what type of game mode this is */
UPROPERTY(BlueprintReadWrite, Category=Session)
FString ModeNameForAdvertisement;
/** The map that will be loaded at the start of gameplay, this needs to be a valid Primary Asset top-level map */
UPROPERTY(BlueprintReadWrite, Category=Session, meta=(AllowedTypes="World"))
FPrimaryAssetId MapID;
/** Extra arguments passed as URL options to the game */
UPROPERTY(BlueprintReadWrite, Category=Session)
TMap<FString, FString> ExtraArgs;
/** Maximum players allowed per gameplay session */
UPROPERTY(BlueprintReadWrite, Category=Session)
int32 MaxPlayerCount = 16;
public:
/** Returns the maximum players that should actually be used, could be overridden in child classes */
virtual int32 GetMaxPlayers() const;
/** Returns the full map name that will be used during gameplay */
virtual FString GetMapName() const;
/** Constructs the full URL that will be passed to ServerTravel */
virtual FString ConstructTravelURL() const;
/** Returns true if this request is valid, returns false and logs errors if it is not */
virtual bool ValidateAndLogErrors(FText& OutError) const;
};
//////////////////////////////////////////////////////////////////////
// UCommonSession_SearchResult
/** A result object returned from the online system that describes a joinable game session */
UCLASS(BlueprintType)
class COMMONUSER_API UCommonSession_SearchResult : public UObject
{
GENERATED_BODY()
public:
/** Returns an internal description of the session, not meant to be human readable */
UFUNCTION(BlueprintCallable, Category=Session)
FString GetDescription() const;
/** Gets an arbitrary string setting, bFoundValue will be false if the setting does not exist */
UFUNCTION(BlueprintPure, Category=Sessions)
void GetStringSetting(FName Key, FString& Value, bool& bFoundValue) const;
/** Gets an arbitrary integer setting, bFoundValue will be false if the setting does not exist */
UFUNCTION(BlueprintPure, Category = Sessions)
void GetIntSetting(FName Key, int32& Value, bool& bFoundValue) const;
/** The number of private connections that are available */
UFUNCTION(BlueprintPure, Category=Sessions)
int32 GetNumOpenPrivateConnections() const;
/** The number of publicly available connections that are available */
UFUNCTION(BlueprintPure, Category=Sessions)
int32 GetNumOpenPublicConnections() const;
/** The maximum number of publicly available connections that could be available, including already filled connections */
UFUNCTION(BlueprintPure, Category = Sessions)
int32 GetMaxPublicConnections() const;
/** Ping to the search result, MAX_QUERY_PING is unreachable */
UFUNCTION(BlueprintPure, Category=Sessions)
int32 GetPingInMs() const;
public:
/** Pointer to the platform-specific implementation */
#if COMMONUSER_OSSV1
FOnlineSessionSearchResult Result;
#else
TSharedPtr<const UE::Online::FLobby> Lobby;
#endif // COMMONUSER_OSSV1
};
//////////////////////////////////////////////////////////////////////
// UCommonSession_SearchSessionRequest
/** Delegates called when a session search completes */
DECLARE_MULTICAST_DELEGATE_TwoParams(FCommonSession_FindSessionsFinished, bool bSucceeded, const FText& ErrorMessage);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FCommonSession_FindSessionsFinishedDynamic, bool, bSucceeded, FText, ErrorMessage);
/** Request object describing a session search, this object will be updated once the search has completed */
UCLASS(BlueprintType)
class COMMONUSER_API UCommonSession_SearchSessionRequest : public UObject
{
GENERATED_BODY()
public:
/** Indicates if the this is looking for full online games or a different type like LAN */
UPROPERTY(BlueprintReadWrite, Category = Session)
ECommonSessionOnlineMode OnlineMode;
/** True if this request should look for player-hosted lobbies if they are available, false will only search for registered server sessions */
UPROPERTY(BlueprintReadWrite, Category = Session)
bool bUseLobbies;
/** List of all found sessions, will be valid when OnSearchFinished is called */
UPROPERTY(BlueprintReadOnly, Category=Session)
TArray<TObjectPtr<UCommonSession_SearchResult>> Results;
/** Native Delegate called when a session search completes */
FCommonSession_FindSessionsFinished OnSearchFinished;
/** Called by subsystem to execute finished delegates */
void NotifySearchFinished(bool bSucceeded, const FText& ErrorMessage);
private:
/** Delegate called when a session search completes */
UPROPERTY(BlueprintAssignable, Category = "Events", meta = (DisplayName = "On Search Finished", AllowPrivateAccess = true))
FCommonSession_FindSessionsFinishedDynamic K2_OnSearchFinished;
};
//////////////////////////////////////////////////////////////////////
// CommonSessionSubsystem Events
/**
* Event triggered when the local user has requested to join a session from an external source, for example from a platform overlay.
* Generally, the game should transition the player into the session.
* @param LocalPlatformUserId the local user id that accepted the invitation. This is a platform user id because the user might not be signed in yet.
* @param RequestedSession the requested session. Can be null if there was an error processing the request.
* @param RequestedSessionResult result of the requested session processing
*/
DECLARE_MULTICAST_DELEGATE_ThreeParams(FCommonSessionOnUserRequestedSession, const FPlatformUserId& /*LocalPlatformUserId*/, UCommonSession_SearchResult* /*RequestedSession*/, const FOnlineResultInformation& /*RequestedSessionResult*/);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FCommonSessionOnUserRequestedSession_Dynamic, const FPlatformUserId&, LocalPlatformUserId, UCommonSession_SearchResult*, RequestedSession, const FOnlineResultInformation&, RequestedSessionResult);
/**
* Event triggered when a session join has completed, after joining the underlying session and before traveling to the server if it was successful.
* The event parameters indicate if this was successful, or if there was an error that will stop it from traveling.
* @param Result result of the session join
*/
DECLARE_MULTICAST_DELEGATE_OneParam(FCommonSessionOnJoinSessionComplete, const FOnlineResultInformation& /*Result*/);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FCommonSessionOnJoinSessionComplete_Dynamic, const FOnlineResultInformation&, Result);
/**
* Event triggered when a session creation for hosting has completed, right before it travels to the map.
* The event parameters indicate if this was successful, or if there was an error that will stop it from traveling.
* @param Result result of the session join
*/
DECLARE_MULTICAST_DELEGATE_OneParam(FCommonSessionOnCreateSessionComplete, const FOnlineResultInformation& /*Result*/);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FCommonSessionOnCreateSessionComplete_Dynamic, const FOnlineResultInformation&, Result);
/**
* Event triggered when a session join has completed, after resolving the connect string and prior to the client traveling.
* @param URL resolved connection string for the session with any additional arguments
*/
DECLARE_MULTICAST_DELEGATE_OneParam(FCommonSessionOnPreClientTravel, FString& /*URL*/);
//////////////////////////////////////////////////////////////////////
// UCommonSessionSubsystem
/**
* Game subsystem that handles requests for hosting and joining online games.
* One subsystem is created for each game instance and can be accessed from blueprints or C++ code.
* If a game-specific subclass exists, this base subsystem will not be created.
*/
UCLASS()
class COMMONUSER_API UCommonSessionSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
UCommonSessionSubsystem() { }
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
virtual bool ShouldCreateSubsystem(UObject* Outer) const override;
/** Creates a host session request with default options for online games, this can be modified after creation */
UFUNCTION(BlueprintCallable, Category = Session)
virtual UCommonSession_HostSessionRequest* CreateOnlineHostSessionRequest();
/** Creates a session search object with default options to look for default online games, this can be modified after creation */
UFUNCTION(BlueprintCallable, Category = Session)
virtual UCommonSession_SearchSessionRequest* CreateOnlineSearchSessionRequest();
/** Creates a new online game using the session request information, if successful this will start a hard map transfer */
UFUNCTION(BlueprintCallable, Category=Session)
virtual void HostSession(APlayerController* HostingPlayer, UCommonSession_HostSessionRequest* Request);
/** Starts a process to look for existing sessions or create a new one if no viable sessions are found */
UFUNCTION(BlueprintCallable, Category=Session)
virtual void QuickPlaySession(APlayerController* JoiningOrHostingPlayer, UCommonSession_HostSessionRequest* Request);
/** Starts process to join an existing session, if successful this will connect to the specified server */
UFUNCTION(BlueprintCallable, Category=Session)
virtual void JoinSession(APlayerController* JoiningPlayer, UCommonSession_SearchResult* Request);
/** Queries online system for the list of joinable sessions matching the search request */
UFUNCTION(BlueprintCallable, Category=Session)
virtual void FindSessions(APlayerController* SearchingPlayer, UCommonSession_SearchSessionRequest* Request);
/** Clean up any active sessions, called from cases like returning to the main menu */
UFUNCTION(BlueprintCallable, Category=Session)
virtual void CleanUpSessions();
//////////////////////////////////////////////////////////////////////
// Events
/** Native Delegate when a local user has accepted an invite */
FCommonSessionOnUserRequestedSession OnUserRequestedSessionEvent;
/** Event broadcast when a local user has accepted an invite */
UPROPERTY(BlueprintAssignable, Category = "Events", meta = (DisplayName = "On User Requested Session"))
FCommonSessionOnUserRequestedSession_Dynamic K2_OnUserRequestedSessionEvent;
/** Native Delegate when a JoinSession call has completed */
FCommonSessionOnJoinSessionComplete OnJoinSessionCompleteEvent;
/** Event broadcast when a JoinSession call has completed */
UPROPERTY(BlueprintAssignable, Category = "Events", meta = (DisplayName = "On Join Session Complete"))
FCommonSessionOnJoinSessionComplete_Dynamic K2_OnJoinSessionCompleteEvent;
/** Native Delegate when a CreateSession call has completed */
FCommonSessionOnCreateSessionComplete OnCreateSessionCompleteEvent;
/** Event broadcast when a CreateSession call has completed */
UPROPERTY(BlueprintAssignable, Category = "Events", meta = (DisplayName = "On Create Session Complete"))
FCommonSessionOnCreateSessionComplete_Dynamic K2_OnCreateSessionCompleteEvent;
/** Native Delegate for modifying the connect URL prior to a client travel */
FCommonSessionOnPreClientTravel OnPreClientTravelEvent;
protected:
// Functions called during the process of creating or joining a session, these can be overidden for game-specific behavior
/** Called to fill in a session request from quick play host settings, can be overridden for game-specific behavior */
virtual TSharedRef<FCommonOnlineSearchSettings> CreateQuickPlaySearchSettings(UCommonSession_HostSessionRequest* Request, UCommonSession_SearchSessionRequest* QuickPlayRequest);
/** Called when a quick play search finishes, can be overridden for game-specific behavior */
virtual void HandleQuickPlaySearchFinished(bool bSucceeded, const FText& ErrorMessage, TWeakObjectPtr<APlayerController> JoiningOrHostingPlayer, TStrongObjectPtr<UCommonSession_HostSessionRequest> HostRequest);
/** Called when traveling to a session fails */
virtual void TravelLocalSessionFailure(UWorld* World, ETravelFailure::Type FailureType, const FString& ReasonString);
/** Called when a new session is either created or fails to be created */
virtual void OnCreateSessionComplete(FName SessionName, bool bWasSuccessful);
/** Called to finalize session creation */
virtual void FinishSessionCreation(bool bWasSuccessful);
/** Called after traveling to the new hosted session map */
virtual void HandlePostLoadMap(UWorld* World);
protected:
// Internal functions for initializing and handling results from the online systems
void BindOnlineDelegates();
void CreateOnlineSessionInternal(ULocalPlayer* LocalPlayer, UCommonSession_HostSessionRequest* Request);
void FindSessionsInternal(APlayerController* SearchingPlayer, const TSharedRef<FCommonOnlineSearchSettings>& InSearchSettings);
void JoinSessionInternal(ULocalPlayer* LocalPlayer, UCommonSession_SearchResult* Request);
void InternalTravelToSession(const FName SessionName);
void NotifyUserRequestedSession(const FPlatformUserId& PlatformUserId, UCommonSession_SearchResult* RequestedSession, const FOnlineResultInformation& RequestedSessionResult);
void NotifyJoinSessionComplete(const FOnlineResultInformation& Result);
void NotifyCreateSessionComplete(const FOnlineResultInformation& Result);
void SetCreateSessionError(const FText& ErrorText);
#if COMMONUSER_OSSV1
void BindOnlineDelegatesOSSv1();
void CreateOnlineSessionInternalOSSv1(ULocalPlayer* LocalPlayer, UCommonSession_HostSessionRequest* Request);
void FindSessionsInternalOSSv1(ULocalPlayer* LocalPlayer);
void JoinSessionInternalOSSv1(ULocalPlayer* LocalPlayer, UCommonSession_SearchResult* Request);
TSharedRef<FCommonOnlineSearchSettings> CreateQuickPlaySearchSettingsOSSv1(UCommonSession_HostSessionRequest* Request, UCommonSession_SearchSessionRequest* QuickPlayRequest);
void CleanUpSessionsOSSv1();
void HandleSessionFailure(const FUniqueNetId& NetId, ESessionFailure::Type FailureType);
void HandleSessionUserInviteAccepted(const bool bWasSuccessful, const int32 LocalUserIndex, FUniqueNetIdPtr AcceptingUserId, const FOnlineSessionSearchResult& SearchResult);
void OnStartSessionComplete(FName SessionName, bool bWasSuccessful);
void OnRegisterLocalPlayerComplete_CreateSession(const FUniqueNetId& PlayerId, EOnJoinSessionCompleteResult::Type Result);
void OnUpdateSessionComplete(FName SessionName, bool bWasSuccessful);
void OnEndSessionComplete(FName SessionName, bool bWasSuccessful);
void OnDestroySessionComplete(FName SessionName, bool bWasSuccessful);
void OnFindSessionsComplete(bool bWasSuccessful);
void OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result);
void OnRegisterJoiningLocalPlayerComplete(const FUniqueNetId& PlayerId, EOnJoinSessionCompleteResult::Type Result);
void FinishJoinSession(EOnJoinSessionCompleteResult::Type Result);
#else
void BindOnlineDelegatesOSSv2();
void CreateOnlineSessionInternalOSSv2(ULocalPlayer* LocalPlayer, UCommonSession_HostSessionRequest* Request);
void FindSessionsInternalOSSv2(ULocalPlayer* LocalPlayer);
void JoinSessionInternalOSSv2(ULocalPlayer* LocalPlayer, UCommonSession_SearchResult* Request);
TSharedRef<FCommonOnlineSearchSettings> CreateQuickPlaySearchSettingsOSSv2(UCommonSession_HostSessionRequest* HostRequest, UCommonSession_SearchSessionRequest* SearchRequest);
void CleanUpSessionsOSSv2();
/** Process a join request originating from the online service */
void OnSessionJoinRequested(const UE::Online::FUILobbyJoinRequested& EventParams);
/** Get the local user id for a given controller */
UE::Online::FAccountId GetAccountId(APlayerController* PlayerController) const;
/** Get the lobby id for a given session name */
UE::Online::FLobbyId GetLobbyId(const FName SessionName) const;
/** Event handle for UI lobby join requested */
UE::Online::FOnlineEventDelegateHandle LobbyJoinRequestedHandle;
#endif // COMMONUSER_OSSV1
protected:
/** The travel URL that will be used after session operations are complete */
FString PendingTravelURL;
/** Most recent result information for a session creation attempt, stored here to allow storing error codes for later */
FOnlineResultInformation CreateSessionResult;
/** True if we want to cancel the session after it is created */
bool bWantToDestroyPendingSession = false;
/** True if this is a dedicated server, which doesn't require a LocalPlayer to create a session */
bool bIsDedicatedServer = false;
/** Settings for the current search */
TSharedPtr<FCommonOnlineSearchSettings> SearchSettings;
/** Settings for the current host request */
TSharedPtr<FCommonSession_OnlineSessionSettings> HostSettings;
};

View File

@@ -0,0 +1,14 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Modules/ModuleInterface.h"
class FCommonUserModule : public IModuleInterface
{
public:
/** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};

View File

@@ -0,0 +1,635 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CommonUserTypes.h"
#include "Engine/GameViewportClient.h"
#include "GameFramework/OnlineReplStructs.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "GameplayTagContainer.h"
#include "Interfaces/OnlineIdentityInterface.h"
#include "OnlineError.h"
#include "UObject/WeakObjectPtr.h"
#include "CommonUserSubsystem.generated.h"
class FNativeGameplayTag;
class IOnlineSubsystem;
/** List of tags used by the common user subsystem */
struct COMMONUSER_API FCommonUserTags
{
// General severity levels and specific system messages
static FNativeGameplayTag SystemMessage_Error; // SystemMessage.Error
static FNativeGameplayTag SystemMessage_Warning; // SystemMessage.Warning
static FNativeGameplayTag SystemMessage_Display; // SystemMessage.Display
/** All attempts to initialize a player failed, user has to do something before trying again */
static FNativeGameplayTag SystemMessage_Error_InitializeLocalPlayerFailed; // SystemMessage.Error.InitializeLocalPlayerFailed
// Platform trait tags, it is expected that the game instance or other system calls SetTraitTags with these tags for the appropriate platform
/** This tag means it is a console platform that directly maps controller IDs to different system users. If false, the same user can have multiple controllers */
static FNativeGameplayTag Platform_Trait_RequiresStrictControllerMapping; // Platform.Trait.RequiresStrictControllerMapping
/** This tag means the platform has a single online user and all players use index 0 */
static FNativeGameplayTag Platform_Trait_SingleOnlineUser; // Platform.Trait.SingleOnlineUser
};
/** Logical representation of an individual user, one of these will exist for all initialized local players */
UCLASS(BlueprintType)
class COMMONUSER_API UCommonUserInfo : public UObject
{
GENERATED_BODY()
public:
/** Primary controller input device for this user, they could also have additional secondary devices */
UPROPERTY(BlueprintReadOnly, Category = UserInfo)
FInputDeviceId PrimaryInputDevice;
/** Specifies the logical user on the local platform, guest users will point to the primary user */
UPROPERTY(BlueprintReadOnly, Category = UserInfo)
FPlatformUserId PlatformUser;
/** If this user is assigned a LocalPlayer, this will match the index in the GameInstance localplayers array once it is fully created */
UPROPERTY(BlueprintReadOnly, Category = UserInfo)
int32 LocalPlayerIndex = -1;
/** If true, this user is allowed to be a guest */
UPROPERTY(BlueprintReadOnly, Category = UserInfo)
bool bCanBeGuest = false;
/** If true, this is a guest user attached to primary user 0 */
UPROPERTY(BlueprintReadOnly, Category = UserInfo)
bool bIsGuest = false;
/** Overall state of the user's initialization process */
UPROPERTY(BlueprintReadOnly, Category = UserInfo)
ECommonUserInitializationState InitializationState = ECommonUserInitializationState::Invalid;
/** Returns true if this user has successfully logged in */
UFUNCTION(BlueprintCallable, Category = UserInfo)
bool IsLoggedIn() const;
/** Returns true if this user is in the middle of logging in */
UFUNCTION(BlueprintCallable, Category = UserInfo)
bool IsDoingLogin() const;
/** Returns the most recently queries result for a specific privilege, will return unknown if never queried */
UFUNCTION(BlueprintCallable, Category = UserInfo)
ECommonUserPrivilegeResult GetCachedPrivilegeResult(ECommonUserPrivilege Privilege, ECommonUserOnlineContext Context = ECommonUserOnlineContext::Game) const;
/** Ask about the general availability of a feature, this combines cached results with state */
UFUNCTION(BlueprintCallable, Category = UserInfo)
ECommonUserAvailability GetPrivilegeAvailability(ECommonUserPrivilege Privilege) const;
/** Returns the net id for the given context */
UFUNCTION(BlueprintCallable, Category = UserInfo)
FUniqueNetIdRepl GetNetId(ECommonUserOnlineContext Context = ECommonUserOnlineContext::Game) const;
/** Returns the user's human readable nickname */
UFUNCTION(BlueprintCallable, Category = UserInfo)
FString GetNickname() const;
/** Returns an internal debug string for this player */
UFUNCTION(BlueprintCallable, Category = UserInfo)
FString GetDebugString() const;
/** Accessor for platform user id */
FPlatformUserId GetPlatformUserId() const;
/** Gets the platform user index for older functions expecting an integer */
int32 GetPlatformUserIndex() const;
// Internal data, only intended to be accessed by online subsystems
/** Cached data for each online system */
struct FCachedData
{
/** Cached net id per system */
FUniqueNetIdRepl CachedNetId;
/** Cached values of various user privileges */
TMap<ECommonUserPrivilege, ECommonUserPrivilegeResult> CachedPrivileges;
};
/** Per context cache, game will always exist but others may not */
TMap<ECommonUserOnlineContext, FCachedData> CachedDataMap;
/** Looks up cached data using resolution rules */
FCachedData* GetCachedData(ECommonUserOnlineContext Context);
const FCachedData* GetCachedData(ECommonUserOnlineContext Context) const;
/** Updates cached privilege results, will propagate to game if needed */
void UpdateCachedPrivilegeResult(ECommonUserPrivilege Privilege, ECommonUserPrivilegeResult Result, ECommonUserOnlineContext Context);
/** Updates cached privilege results, will propagate to game if needed */
void UpdateCachedNetId(const FUniqueNetIdRepl& NewId, ECommonUserOnlineContext Context);
/** Return the subsystem this is owned by */
class UCommonUserSubsystem* GetSubsystem() const;
};
/** Delegates when initialization processes succeed or fail */
DECLARE_DYNAMIC_MULTICAST_DELEGATE_FiveParams(FCommonUserOnInitializeCompleteMulticast, const UCommonUserInfo*, UserInfo, bool, bSuccess, FText, Error, ECommonUserPrivilege, RequestedPrivilege, ECommonUserOnlineContext, OnlineContext);
DECLARE_DYNAMIC_DELEGATE_FiveParams(FCommonUserOnInitializeComplete, const UCommonUserInfo*, UserInfo, bool, bSuccess, FText, Error, ECommonUserPrivilege, RequestedPrivilege, ECommonUserOnlineContext, OnlineContext);
/** Delegate when a system error message is sent, the game can choose to display it to the user using the type tag */
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FCommonUserHandleSystemMessageDelegate, FGameplayTag, MessageType, FText, TitleText, FText, BodyText);
/** Delegate when a privilege changes, this can be bound to see if online status/etc changes during gameplay */
DECLARE_DYNAMIC_MULTICAST_DELEGATE_FourParams(FCommonUserAvailabilityChangedDelegate, const UCommonUserInfo*, UserInfo, ECommonUserPrivilege, Privilege, ECommonUserAvailability, OldAvailability, ECommonUserAvailability, NewAvailability);
/** Parameter struct for initialize functions, this would normally be filled in by wrapper functions like async nodes */
USTRUCT(BlueprintType)
struct COMMONUSER_API FCommonUserInitializeParams
{
GENERATED_BODY()
/** What local player index to use, can specify one above current if can create player is enabled */
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Default)
int32 LocalPlayerIndex = 0;
/** Deprecated method of selecting platform user and input device */
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Default)
int32 ControllerId = -1;
/** Primary controller input device for this user, they could also have additional secondary devices */
UPROPERTY(BlueprintReadOnly, Category = UserInfo)
FInputDeviceId PrimaryInputDevice;
/** Specifies the logical user on the local platform */
UPROPERTY(BlueprintReadOnly, Category = UserInfo)
FPlatformUserId PlatformUser;
/** Generally either CanPlay or CanPlayOnline, specifies what level of privilege is required */
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Default)
ECommonUserPrivilege RequestedPrivilege = ECommonUserPrivilege::CanPlay;
/** What specific online context to log in to, game means to login to all relevant ones */
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Default)
ECommonUserOnlineContext OnlineContext = ECommonUserOnlineContext::Game;
/** True if this is allowed to create a new local player for initial login */
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Default)
bool bCanCreateNewLocalPlayer = false;
/** True if this player can be a guest user without an actual online presence */
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Default)
bool bCanUseGuestLogin = false;
/** True if we should not show login errors, the game will be responsible for displaying them */
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Default)
bool bSuppressLoginErrors = false;
/** If bound, call this dynamic delegate at completion of login */
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Default)
FCommonUserOnInitializeComplete OnUserInitializeComplete;
};
/**
* Game subsystem that handles queries and changes to user identity and login status.
* One subsystem is created for each game instance and can be accessed from blueprints or C++ code.
* If a game-specific subclass exists, this base subsystem will not be created.
*/
UCLASS(BlueprintType, Config=Game)
class COMMONUSER_API UCommonUserSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
UCommonUserSubsystem() { }
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
virtual bool ShouldCreateSubsystem(UObject* Outer) const override;
/** BP delegate called when any requested initialization request completes */
UPROPERTY(BlueprintAssignable, Category = CommonUser)
FCommonUserOnInitializeCompleteMulticast OnUserInitializeComplete;
/** BP delegate called when the system sends an error/warning message */
UPROPERTY(BlueprintAssignable, Category = CommonUser)
FCommonUserHandleSystemMessageDelegate OnHandleSystemMessage;
/** BP delegate called when privilege availability changes for a user */
UPROPERTY(BlueprintAssignable, Category = CommonUser)
FCommonUserAvailabilityChangedDelegate OnUserPrivilegeChanged;
/** Send a system message via OnHandleSystemMessage */
UFUNCTION(BlueprintCallable, Category = CommonUser)
virtual void SendSystemMessage(FGameplayTag MessageType, FText TitleText, FText BodyText);
/** Sets the maximum number of local players, will not destroy existing ones */
UFUNCTION(BlueprintCallable, Category = CommonUser)
virtual void SetMaxLocalPlayers(int32 InMaxLocalPLayers);
/** Gets the maximum number of local players */
UFUNCTION(BlueprintPure, Category = CommonUser)
int32 GetMaxLocalPlayers() const;
/** Gets the current number of local players, will always be at least 1 */
UFUNCTION(BlueprintPure, Category = CommonUser)
int32 GetNumLocalPlayers() const;
/** Returns the state of initializing the specified local player */
UFUNCTION(BlueprintPure, Category = CommonUser)
ECommonUserInitializationState GetLocalPlayerInitializationState(int32 LocalPlayerIndex) const;
/** Returns the user info for a given local player index in game instance, 0 is always valid in a running game */
UFUNCTION(BlueprintCallable, BlueprintPure = False, Category = CommonUser)
const UCommonUserInfo* GetUserInfoForLocalPlayerIndex(int32 LocalPlayerIndex) const;
/** Deprecated, use PlatformUserId when available */
UFUNCTION(BlueprintCallable, BlueprintPure = False, Category = CommonUser)
const UCommonUserInfo* GetUserInfoForPlatformUserIndex(int32 PlatformUserIndex) const;
/** Returns the primary user info for a given platform user index. Can return null */
UFUNCTION(BlueprintCallable, BlueprintPure = False, Category = CommonUser)
const UCommonUserInfo* GetUserInfoForPlatformUser(FPlatformUserId PlatformUser) const;
/** Returns the user info for a unique net id. Can return null */
UFUNCTION(BlueprintCallable, BlueprintPure = False, Category = CommonUser)
const UCommonUserInfo* GetUserInfoForUniqueNetId(const FUniqueNetIdRepl& NetId) const;
/** Deprecated, use InputDeviceId when available */
UFUNCTION(BlueprintCallable, BlueprintPure = False, Category = CommonUser)
const UCommonUserInfo* GetUserInfoForControllerId(int32 ControllerId) const;
/** Returns the user info for a given input device. Can return null */
UFUNCTION(BlueprintCallable, BlueprintPure = False, Category = CommonUser)
const UCommonUserInfo* GetUserInfoForInputDevice(FInputDeviceId InputDevice) const;
/**
* Tries to start the process of creating or updating a local player, including logging in and creating a player controller.
* When the process has succeeded or failed, it will broadcast the OnUserInitializeComplete delegate.
*
* @param LocalPlayerIndex Desired index of LocalPlayer in Game Instance, 0 will be primary player and 1+ for local multiplayer
* @param PrimaryInputDevice The physical controller that should be mapped to this user, will use the default device if invalid
* @param bCanUseGuestLogin If true, this player can be a guest without a real Unique Net Id
*
* @returns true if the process was started, false if it failed before properly starting
*/
UFUNCTION(BlueprintCallable, Category = CommonUser)
virtual bool TryToInitializeForLocalPlay(int32 LocalPlayerIndex, FInputDeviceId PrimaryInputDevice, bool bCanUseGuestLogin);
/**
* Starts the process of taking a locally logged in user and doing a full online login including account permission checks.
* When the process has succeeded or failed, it will broadcast the OnUserInitializeComplete delegate.
*
* @param LocalPlayerIndex Index of existing LocalPlayer in Game Instance
*
* @returns true if the process was started, false if it failed before properly starting
*/
UFUNCTION(BlueprintCallable, Category = CommonUser)
virtual bool TryToLoginForOnlinePlay(int32 LocalPlayerIndex);
/**
* Starts a general user login and initialization process, using the params structure to determine what to log in to.
* When the process has succeeded or failed, it will broadcast the OnUserInitializeComplete delegate.
* AsyncAction_CommonUserInitialize provides several wrapper functions for using this in an Event graph.
*
* @returns true if the process was started, false if it failed before properly starting
*/
UFUNCTION(BlueprintCallable, Category = CommonUser)
virtual bool TryToInitializeUser(FCommonUserInitializeParams Params);
/**
* Starts the process of listening for user input for new and existing controllers and logging them.
* This will insert a key input handler on the active GameViewportClient and is turned off by calling again with empty key arrays.
*
* @param AnyUserKeys Listen for these keys for any user, even the default user. Set this for an initial press start screen or empty to disable
* @param NewUserKeys Listen for these keys for a new user without a player controller. Set this for splitscreen/local multiplayer or empty to disable
* @param Params Params passed to TryToInitializeUser after detecting key input
*/
UFUNCTION(BlueprintCallable, Category = CommonUser)
virtual void ListenForLoginKeyInput(TArray<FKey> AnyUserKeys, TArray<FKey> NewUserKeys, FCommonUserInitializeParams Params);
/** Attempts to cancel an in-progress initialization attempt, this may not work on all platforms but will disable callbacks */
UFUNCTION(BlueprintCallable, Category = CommonUser)
virtual bool CancelUserInitialization(int32 LocalPlayerIndex);
/** Logs a player out of any online systems, and optionally destroys the player entirely if it's not the first one */
UFUNCTION(BlueprintCallable, Category = CommonUser)
virtual bool TryToLogOutUser(int32 LocalPlayerIndex, bool bDestroyPlayer = false);
/** Resets the login and initialization state when returning to the main menu after an error */
UFUNCTION(BlueprintCallable, Category = CommonUser)
virtual void ResetUserState();
/** Returns true if this this could be a real platform user with a valid identity (even if not currently logged in) */
virtual bool IsRealPlatformUserIndex(int32 PlatformUserIndex) const;
/** Returns true if this this could be a real platform user with a valid identity (even if not currently logged in) */
virtual bool IsRealPlatformUser(FPlatformUserId PlatformUser) const;
/** Converts index to id */
virtual FPlatformUserId GetPlatformUserIdForIndex(int32 PlatformUserIndex) const;
/** Converts id to index */
virtual int32 GetPlatformUserIndexForId(FPlatformUserId PlatformUser) const;
/** Gets the user for an input device */
virtual FPlatformUserId GetPlatformUserIdForInputDevice(FInputDeviceId InputDevice) const;
/** Gets a user's primary input device id */
virtual FInputDeviceId GetPrimaryInputDeviceForPlatformUser(FPlatformUserId PlatformUser) const;
/** Call from game code to set the cached trait tags when platform state or options changes */
virtual void SetTraitTags(const FGameplayTagContainer& InTags);
/** Gets the current tags that affect feature avialability */
const FGameplayTagContainer& GetTraitTags() const { return CachedTraitTags; }
/** Checks if a specific platform/feature tag is enabled */
UFUNCTION(BlueprintPure, Category=CommonUser)
bool HasTraitTag(const FGameplayTag TraitTag) const { return CachedTraitTags.HasTag(TraitTag); }
/** Checks to see if we should display a press start/input confirmation screen at startup. Games can call this or check the trait tags directly */
UFUNCTION(BlueprintPure, BlueprintPure, Category=CommonUser)
virtual bool ShouldWaitForStartInput() const;
// Functions for accessing low-level online system information
#if COMMONUSER_OSSV1
/** Returns OSS interface of specific type, will return null if there is no type */
IOnlineSubsystem* GetOnlineSubsystem(ECommonUserOnlineContext Context = ECommonUserOnlineContext::Game) const;
/** Returns identity interface of specific type, will return null if there is no type */
IOnlineIdentity* GetOnlineIdentity(ECommonUserOnlineContext Context = ECommonUserOnlineContext::Game) const;
/** Returns human readable name of OSS system */
FName GetOnlineSubsystemName(ECommonUserOnlineContext Context = ECommonUserOnlineContext::Game) const;
/** Returns the current online connection status */
EOnlineServerConnectionStatus::Type GetConnectionStatus(ECommonUserOnlineContext Context = ECommonUserOnlineContext::Game) const;
#else
/** Get the services provider type, or None if there isn't one. */
UE::Online::EOnlineServices GetOnlineServicesProvider(ECommonUserOnlineContext Context = ECommonUserOnlineContext::Game) const;
/** Returns auth interface of specific type, will return null if there is no type */
UE::Online::IAuthPtr GetOnlineAuth(ECommonUserOnlineContext Context = ECommonUserOnlineContext::Game) const;
/** Returns the current online connection status */
UE::Online::EOnlineServicesConnectionStatus GetConnectionStatus(ECommonUserOnlineContext Context = ECommonUserOnlineContext::Game) const;
#endif
/** Returns true if we are currently connected to backend servers */
bool HasOnlineConnection(ECommonUserOnlineContext Context = ECommonUserOnlineContext::Game) const;
/** Returns the current login status for a player on the specified online system, only works for real platform users */
ELoginStatusType GetLocalUserLoginStatus(FPlatformUserId PlatformUser, ECommonUserOnlineContext Context = ECommonUserOnlineContext::Game) const;
/** Returns the unique net id for a local platform user */
FUniqueNetIdRepl GetLocalUserNetId(FPlatformUserId PlatformUser, ECommonUserOnlineContext Context = ECommonUserOnlineContext::Game) const;
/** Convert a user id to a debug string */
FString PlatformUserIdToString(FPlatformUserId UserId);
/** Convert a context to a debug string */
FString ECommonUserOnlineContextToString(ECommonUserOnlineContext Context);
/** Returns human readable string for privilege checks */
virtual FText GetPrivilegeDescription(ECommonUserPrivilege Privilege) const;
virtual FText GetPrivilegeResultDescription(ECommonUserPrivilegeResult Result) const;
/**
* Starts the process of login for an existing local user, will return false if callback was not scheduled
* This activates the low level state machine and does not modify the initialization state on user info
*/
DECLARE_DELEGATE_FiveParams(FOnLocalUserLoginCompleteDelegate, const UCommonUserInfo* /*UserInfo*/, ELoginStatusType /*NewStatus*/, FUniqueNetIdRepl /*NetId*/, const TOptional<FOnlineErrorType>& /*Error*/, ECommonUserOnlineContext /*Type*/);
virtual bool LoginLocalUser(const UCommonUserInfo* UserInfo, ECommonUserPrivilege RequestedPrivilege, ECommonUserOnlineContext Context, FOnLocalUserLoginCompleteDelegate OnComplete);
/** Assign a local player to a specific local user and call callbacks as needed */
virtual void SetLocalPlayerUserInfo(ULocalPlayer* LocalPlayer, const UCommonUserInfo* UserInfo);
/** Resolves a context that has default behavior into a specific context */
ECommonUserOnlineContext ResolveOnlineContext(ECommonUserOnlineContext Context) const;
/** True if there is a separate platform and service interface */
bool HasSeparatePlatformContext() const;
protected:
/** Internal structure that caches status and pointers for each online context */
struct FOnlineContextCache
{
#if COMMONUSER_OSSV1
/** Pointer to base subsystem, will stay valid as long as game instance does */
IOnlineSubsystem* OnlineSubsystem = nullptr;
/** Cached identity system, this will always be valid */
IOnlineIdentityPtr IdentityInterface;
/** Last connection status that was passed into the HandleNetworkConnectionStatusChanged hander */
EOnlineServerConnectionStatus::Type CurrentConnectionStatus = EOnlineServerConnectionStatus::Normal;
#else
/** Online services, accessor to specific services */
UE::Online::IOnlineServicesPtr OnlineServices;
/** Cached auth service */
UE::Online::IAuthPtr AuthService;
/** Login status changed event handle */
UE::Online::FOnlineEventDelegateHandle LoginStatusChangedHandle;
/** Connection status changed event handle */
UE::Online::FOnlineEventDelegateHandle ConnectionStatusChangedHandle;
/** Last connection status that was passed into the HandleNetworkConnectionStatusChanged hander */
UE::Online::EOnlineServicesConnectionStatus CurrentConnectionStatus = UE::Online::EOnlineServicesConnectionStatus::NotConnected;
#endif
/** Resets state, important to clear all shared ptrs */
void Reset()
{
#if COMMONUSER_OSSV1
OnlineSubsystem = nullptr;
IdentityInterface.Reset();
CurrentConnectionStatus = EOnlineServerConnectionStatus::Normal;
#else
OnlineServices.Reset();
AuthService.Reset();
CurrentConnectionStatus = UE::Online::EOnlineServicesConnectionStatus::NotConnected;
#endif
}
};
/** Internal structure to represent an in-progress login request */
struct FUserLoginRequest : public TSharedFromThis<FUserLoginRequest>
{
FUserLoginRequest(UCommonUserInfo* InUserInfo, ECommonUserPrivilege InPrivilege, ECommonUserOnlineContext InContext, FOnLocalUserLoginCompleteDelegate&& InDelegate)
: UserInfo(TWeakObjectPtr<UCommonUserInfo>(InUserInfo))
, DesiredPrivilege(InPrivilege)
, DesiredContext(InContext)
, Delegate(MoveTemp(InDelegate))
{}
/** Which local user is trying to log on */
TWeakObjectPtr<UCommonUserInfo> UserInfo;
/** Overall state of login request, could come from many sources */
ECommonUserAsyncTaskState OverallLoginState = ECommonUserAsyncTaskState::NotStarted;
/** State of attempt to use platform auth. When started, this immediately transitions to Failed for OSSv1, as we do not support platform auth there. */
ECommonUserAsyncTaskState TransferPlatformAuthState = ECommonUserAsyncTaskState::NotStarted;
/** State of attempt to use AutoLogin */
ECommonUserAsyncTaskState AutoLoginState = ECommonUserAsyncTaskState::NotStarted;
/** State of attempt to use external login UI */
ECommonUserAsyncTaskState LoginUIState = ECommonUserAsyncTaskState::NotStarted;
/** Final privilege to that is requested */
ECommonUserPrivilege DesiredPrivilege = ECommonUserPrivilege::Invalid_Count;
/** State of attempt to request the relevant privilege */
ECommonUserAsyncTaskState PrivilegeCheckState = ECommonUserAsyncTaskState::NotStarted;
/** The final context to log into */
ECommonUserOnlineContext DesiredContext = ECommonUserOnlineContext::Invalid;
/** What online system we are currently logging into */
ECommonUserOnlineContext CurrentContext = ECommonUserOnlineContext::Invalid;
/** User callback for completion */
FOnLocalUserLoginCompleteDelegate Delegate;
/** Most recent/relevant error to display to user */
TOptional<FOnlineErrorType> Error;
};
/** Create a new user info object */
virtual UCommonUserInfo* CreateLocalUserInfo(int32 LocalPlayerIndex);
/** Deconst wrapper for const getters */
FORCEINLINE UCommonUserInfo* ModifyInfo(const UCommonUserInfo* Info) { return const_cast<UCommonUserInfo*>(Info); }
/** Refresh user info from OSS */
virtual void RefreshLocalUserInfo(UCommonUserInfo* UserInfo);
/** Possibly send privilege availability notification, compares current value to cached old value */
virtual void HandleChangedAvailability(UCommonUserInfo* UserInfo, ECommonUserPrivilege Privilege, ECommonUserAvailability OldAvailability);
/** Updates the cached privilege on a user and notifies delegate */
virtual void UpdateUserPrivilegeResult(UCommonUserInfo* UserInfo, ECommonUserPrivilege Privilege, ECommonUserPrivilegeResult Result, ECommonUserOnlineContext Context);
/** Gets internal data for a type of online system, can return null for service */
const FOnlineContextCache* GetContextCache(ECommonUserOnlineContext Context = ECommonUserOnlineContext::Game) const;
FOnlineContextCache* GetContextCache(ECommonUserOnlineContext Context = ECommonUserOnlineContext::Game);
/** Create and set up system objects before delegates are bound */
virtual void CreateOnlineContexts();
virtual void DestroyOnlineContexts();
/** Bind online delegates */
virtual void BindOnlineDelegates();
/** Forcibly logs out and deinitializes a single user */
virtual void LogOutLocalUser(FPlatformUserId PlatformUser);
/** Performs the next step of a login request, which could include completing it. Returns true if it's done */
virtual void ProcessLoginRequest(TSharedRef<FUserLoginRequest> Request);
/** Call login on OSS, with platform auth from the platform OSS. Return true if AutoLogin started */
virtual bool TransferPlatformAuth(FOnlineContextCache* System, TSharedRef<FUserLoginRequest> Request, FPlatformUserId PlatformUser);
/** Call AutoLogin on OSS. Return true if AutoLogin started. */
virtual bool AutoLogin(FOnlineContextCache* System, TSharedRef<FUserLoginRequest> Request, FPlatformUserId PlatformUser);
/** Call ShowLoginUI on OSS. Return true if ShowLoginUI started. */
virtual bool ShowLoginUI(FOnlineContextCache* System, TSharedRef<FUserLoginRequest> Request, FPlatformUserId PlatformUser);
/** Call QueryUserPrivilege on OSS. Return true if QueryUserPrivilege started. */
virtual bool QueryUserPrivilege(FOnlineContextCache* System, TSharedRef<FUserLoginRequest> Request, FPlatformUserId PlatformUser);
/** OSS-specific functions */
#if COMMONUSER_OSSV1
virtual ECommonUserPrivilege ConvertOSSPrivilege(EUserPrivileges::Type Privilege) const;
virtual EUserPrivileges::Type ConvertOSSPrivilege(ECommonUserPrivilege Privilege) const;
virtual ECommonUserPrivilegeResult ConvertOSSPrivilegeResult(EUserPrivileges::Type Privilege, uint32 Results) const;
void BindOnlineDelegatesOSSv1();
bool AutoLoginOSSv1(FOnlineContextCache* System, TSharedRef<FUserLoginRequest> Request, FPlatformUserId PlatformUser);
bool ShowLoginUIOSSv1(FOnlineContextCache* System, TSharedRef<FUserLoginRequest> Request, FPlatformUserId PlatformUser);
bool QueryUserPrivilegeOSSv1(FOnlineContextCache* System, TSharedRef<FUserLoginRequest> Request, FPlatformUserId PlatformUser);
#else
virtual ECommonUserPrivilege ConvertOnlineServicesPrivilege(UE::Online::EUserPrivileges Privilege) const;
virtual UE::Online::EUserPrivileges ConvertOnlineServicesPrivilege(ECommonUserPrivilege Privilege) const;
virtual ECommonUserPrivilegeResult ConvertOnlineServicesPrivilegeResult(UE::Online::EUserPrivileges Privilege, UE::Online::EPrivilegeResults Results) const;
void BindOnlineDelegatesOSSv2();
void CacheConnectionStatus(ECommonUserOnlineContext Context);
bool TransferPlatformAuthOSSv2(FOnlineContextCache* System, TSharedRef<FUserLoginRequest> Request, FPlatformUserId PlatformUser);
bool AutoLoginOSSv2(FOnlineContextCache* System, TSharedRef<FUserLoginRequest> Request, FPlatformUserId PlatformUser);
bool ShowLoginUIOSSv2(FOnlineContextCache* System, TSharedRef<FUserLoginRequest> Request, FPlatformUserId PlatformUser);
bool QueryUserPrivilegeOSSv2(FOnlineContextCache* System, TSharedRef<FUserLoginRequest> Request, FPlatformUserId PlatformUser);
TSharedPtr<UE::Online::FAccountInfo> GetOnlineServiceAccountInfo(UE::Online::IAuthPtr AuthService, FPlatformUserId InUserId) const;
#endif
/** Callbacks for OSS functions */
#if COMMONUSER_OSSV1
virtual void HandleIdentityLoginStatusChanged(int32 PlatformUserIndex, ELoginStatus::Type OldStatus, ELoginStatus::Type NewStatus, const FUniqueNetId& NewId, ECommonUserOnlineContext Context);
virtual void HandleUserLoginCompleted(int32 PlatformUserIndex, bool bWasSuccessful, const FUniqueNetId& NetId, const FString& Error, ECommonUserOnlineContext Context);
virtual void HandleControllerPairingChanged(int32 PlatformUserIndex, FControllerPairingChangedUserInfo PreviousUser, FControllerPairingChangedUserInfo NewUser);
virtual void HandleNetworkConnectionStatusChanged(const FString& ServiceName, EOnlineServerConnectionStatus::Type LastConnectionStatus, EOnlineServerConnectionStatus::Type ConnectionStatus, ECommonUserOnlineContext Context);
virtual void HandleOnLoginUIClosed(TSharedPtr<const FUniqueNetId> LoggedInNetId, const int PlatformUserIndex, const FOnlineError& Error, ECommonUserOnlineContext Context);
virtual void HandleCheckPrivilegesComplete(const FUniqueNetId& UserId, EUserPrivileges::Type Privilege, uint32 PrivilegeResults, ECommonUserPrivilege RequestedPrivilege, TWeakObjectPtr<UCommonUserInfo> CommonUserInfo, ECommonUserOnlineContext Context);
#else
virtual void HandleAuthLoginStatusChanged(const UE::Online::FAuthLoginStatusChanged& EventParameters, ECommonUserOnlineContext Context);
virtual void HandleUserLoginCompletedV2(const UE::Online::TOnlineResult<UE::Online::FAuthLogin>& Result, FPlatformUserId PlatformUser, ECommonUserOnlineContext Context);
virtual void HandleOnLoginUIClosedV2(const UE::Online::TOnlineResult<UE::Online::FExternalUIShowLoginUI>& Result, FPlatformUserId PlatformUser, ECommonUserOnlineContext Context);
virtual void HandleNetworkConnectionStatusChanged(const UE::Online::FConnectionStatusChanged& EventParameters, ECommonUserOnlineContext Context);
virtual void HandleCheckPrivilegesComplete(const UE::Online::TOnlineResult<UE::Online::FQueryUserPrivilege>& Result, TWeakObjectPtr<UCommonUserInfo> CommonUserInfo, UE::Online::EUserPrivileges DesiredPrivilege, ECommonUserOnlineContext Context);
#endif
/**
* Callback for when an input device (i.e. a gamepad) has been connected or disconnected.
*/
virtual void HandleInputDeviceConnectionChanged(EInputDeviceConnectionState NewConnectionState, FPlatformUserId PlatformUserId, FInputDeviceId InputDeviceId);
virtual void HandleLoginForUserInitialize(const UCommonUserInfo* UserInfo, ELoginStatusType NewStatus, FUniqueNetIdRepl NetId, const TOptional<FOnlineErrorType>& Error, ECommonUserOnlineContext Context, FCommonUserInitializeParams Params);
virtual void HandleUserInitializeFailed(FCommonUserInitializeParams Params, FText Error);
virtual void HandleUserInitializeSucceeded(FCommonUserInitializeParams Params);
/** Callback for handling press start/login logic */
virtual bool OverrideInputKeyForLogin(FInputKeyEventArgs& EventArgs);
/** Previous override handler, will restore on cancel */
FOverrideInputKeyHandler WrappedInputKeyHandler;
/** List of keys to listen for from any user */
TArray<FKey> LoginKeysForAnyUser;
/** List of keys to listen for a new unmapped user */
TArray<FKey> LoginKeysForNewUser;
/** Params to use for a key-triggered login */
FCommonUserInitializeParams ParamsForLoginKey;
/** Maximum number of local players */
int32 MaxNumberOfLocalPlayers = 0;
/** True if this is a dedicated server, which doesn't require a LocalPlayer */
bool bIsDedicatedServer = false;
/** List of current in progress login requests */
TArray<TSharedRef<FUserLoginRequest>> ActiveLoginRequests;
/** Information about each local user, from local player index to user */
UPROPERTY()
TMap<int32, TObjectPtr<UCommonUserInfo>> LocalUserInfos;
/** Cached platform/mode trait tags */
FGameplayTagContainer CachedTraitTags;
/** Do not access this outside of initialization */
FOnlineContextCache* DefaultContextInternal = nullptr;
FOnlineContextCache* ServiceContextInternal = nullptr;
FOnlineContextCache* PlatformContextInternal = nullptr;
friend UCommonUserInfo;
};

View File

@@ -0,0 +1,218 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#if COMMONUSER_OSSV1
// Online Subsystem (OSS v1) includes and forward declares
#include "OnlineSubsystemTypes.h"
class IOnlineSubsystem;
struct FOnlineError;
using FOnlineErrorType = FOnlineError;
using ELoginStatusType = ELoginStatus::Type;
#else
// Online Services (OSS v2) includes and forward declares
#include "Online/Connectivity.h"
#include "Online/OnlineError.h"
namespace UE::Online
{
enum class ELoginStatus : uint8;
enum class EPrivilegeResults : uint32;
enum class EUserPrivileges : uint8;
using IAuthPtr = TSharedPtr<class IAuth>;
using IOnlineServicesPtr = TSharedPtr<class IOnlineServices>;
template <typename OpType>
class TOnlineResult;
struct FAuthLogin;
struct FConnectionStatusChanged;
struct FExternalUIShowLoginUI;
struct FAuthLoginStatusChanged;
struct FQueryUserPrivilege;
struct FAccountInfo;
}
using FOnlineErrorType = UE::Online::FOnlineError;
using ELoginStatusType = UE::Online::ELoginStatus;
#endif
#include "CommonUserTypes.generated.h"
/** Enum specifying where and how to run online queries */
UENUM(BlueprintType)
enum class ECommonUserOnlineContext : uint8
{
/** Called from game code, this uses the default system but with special handling that could merge results from multiple contexts */
Game,
/** The default engine online system, this will always exist and will be the same as either Service or Platform */
Default,
/** Explicitly ask for the external service, which may not exist */
Service,
/** Looks for external service first, then falls back to default */
ServiceOrDefault,
/** Explicitly ask for the platform system, which may not exist */
Platform,
/** Looks for platform system first, then falls back to default */
PlatformOrDefault,
/** Invalid system */
Invalid
};
/** Enum describing the state of initialization for a specific user */
UENUM(BlueprintType)
enum class ECommonUserInitializationState : uint8
{
/** User has not started login process */
Unknown,
/** Player is in the process of acquiring a user id with local login */
DoingInitialLogin,
/** Player is performing the network login, they have already logged in locally */
DoingNetworkLogin,
/** Player failed to log in at all */
FailedtoLogin,
/** Player is logged in and has access to online functionality */
LoggedInOnline,
/** Player is logged in locally (either guest or real user), but cannot perform online actions */
LoggedInLocalOnly,
/** Invalid state or user */
Invalid,
};
/** Enum specifying different privileges and capabilities available to a user */
UENUM(BlueprintType)
enum class ECommonUserPrivilege : uint8
{
/** Whether the user can play at all, online or offline */
CanPlay,
/** Whether the user can play in online modes */
CanPlayOnline,
/** Whether the user can use text chat */
CanCommunicateViaTextOnline,
/** Whether the user can use voice chat */
CanCommunicateViaVoiceOnline,
/** Whether the user can access content generated by other users */
CanUseUserGeneratedContent,
/** Whether the user can ever participate in cross-play */
CanUseCrossPlay,
/** Invalid privilege (also the count of valid ones) */
Invalid_Count UMETA(Hidden)
};
/** Enum specifying the general availability of a feature or privilege, this combines information from multiple sources */
UENUM(BlueprintType)
enum class ECommonUserAvailability : uint8
{
/** State is completely unknown and needs to be queried */
Unknown,
/** This feature is fully available for use right now */
NowAvailable,
/** This might be available after the completion of normal login procedures */
PossiblyAvailable,
/** This feature is not available now because of something like network connectivity but may be available in the future */
CurrentlyUnavailable,
/** This feature will never be available for the rest of this session due to hard account or platform restrictions */
AlwaysUnavailable,
/** Invalid feature */
Invalid,
};
/** Enum giving specific reasons why a user may or may not use a certain privilege */
UENUM(BlueprintType)
enum class ECommonUserPrivilegeResult : uint8
{
/** State is unknown and needs to be queried */
Unknown,
/** This privilege is fully available for use */
Available,
/** User has not fully logged in */
UserNotLoggedIn,
/** User does not own the game or content */
LicenseInvalid,
/** The game needs to be updated or patched before this will be available */
VersionOutdated,
/** No network connection, this may be resolved by reconnecting */
NetworkConnectionUnavailable,
/** Parental control failure */
AgeRestricted,
/** Account does not have a required subscription or account type */
AccountTypeRestricted,
/** Another account/user restriction such as being banned by the service */
AccountUseRestricted,
/** Other platform-specific failure */
PlatformFailure,
};
/** Used to track the progress of different asynchronous operations */
enum class ECommonUserAsyncTaskState : uint8
{
/** The task has not been started */
NotStarted,
/** The task is currently being processed */
InProgress,
/** The task has completed successfully */
Done,
/** The task failed to complete */
Failed
};
/** Detailed information about the online error. Effectively a wrapper for FOnlineError. */
USTRUCT(BlueprintType)
struct FOnlineResultInformation
{
GENERATED_BODY()
/** Whether the operation was successful or not. If it was successful, the error fields of this struct will not contain extra information. */
UPROPERTY(BlueprintReadOnly)
bool bWasSuccessful = true;
/** The unique error id. Can be used to compare against specific handled errors. */
UPROPERTY(BlueprintReadOnly)
FString ErrorId;
/** Error text to display to the user. */
UPROPERTY(BlueprintReadOnly)
FText ErrorText;
/**
* Initialize this from an FOnlineErrorType
* @param InOnlineError the online error to initialize from
*/
void COMMONUSER_API FromOnlineError(const FOnlineErrorType& InOnlineError);
};