3542 lines
96 KiB
C++
3542 lines
96 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "Misc/Guid.h"
|
|
#include "Modules/ModuleManager.h"
|
|
#include "ILauncherProfile.h"
|
|
#include "ILauncherServicesModule.h"
|
|
#include "Misc/Paths.h"
|
|
#include "Launcher/LauncherProjectPath.h"
|
|
#include "Misc/CommandLine.h"
|
|
#include "Internationalization/Culture.h"
|
|
#include "Misc/App.h"
|
|
#include "Interfaces/ITargetPlatform.h"
|
|
#include "Interfaces/ITargetPlatformManagerModule.h"
|
|
#include "ITargetDeviceProxy.h"
|
|
#include "ITargetDeviceServicesModule.h"
|
|
#include "GameProjectHelper.h"
|
|
#include "Profiles/LauncherProfileLaunchRole.h"
|
|
#include "PlatformInfo.h"
|
|
#include "TargetReceipt.h"
|
|
#include "DesktopPlatformModule.h"
|
|
#include "GameProjectHelper.h"
|
|
|
|
DEFINE_LOG_CATEGORY_STATIC(LogLauncherProfile, Log, All);
|
|
|
|
class Error;
|
|
|
|
enum ELauncherVersion
|
|
{
|
|
LAUNCHERSERVICES_MINPROFILEVERSION=10,
|
|
LAUNCHERSERVICES_ADDEDINCREMENTALDEPLOYVERSION=11,
|
|
LAUNCHERSERVICES_ADDEDPATCHSOURCECONTENTPATH=12,
|
|
LAUNCHERSERVICES_ADDEDRELEASEVERSION=13,
|
|
LAUNCHERSERVICES_REMOVEDPATCHSOURCECONTENTPATH=14,
|
|
LAUNCHERSERVICES_ADDEDDLCINCLUDEENGINECONTENT=15,
|
|
LAUNCHERSERVICES_ADDEDGENERATECHUNKS=16,
|
|
LAUNCHERSERVICES_ADDEDNUMCOOKERSTOSPAWN=17,
|
|
LAUNCHERSERVICES_ADDEDSKIPCOOKINGEDITORCONTENT=18,
|
|
LAUNCHERSERVICES_ADDEDDEFAULTDEPLOYPLATFORM=19,
|
|
LAUNCHERSERVICES_FIXCOMPRESSIONSERIALIZE=20,
|
|
LAUNCHERSERVICES_SHAREABLEPROJECTPATHS = 21,
|
|
LAUNCHERSERVICES_FILEFORMATCHANGE = 22,
|
|
LAUNCHERSERVICES_ADDARCHIVE = 23,
|
|
LAUNCHERSERVICES_ADDEDENCRYPTINIFILES = 24,
|
|
LAUNCHERSERVICES_ADDEDMULTILEVELPATCHING = 25,
|
|
LAUNCHERSERVICES_ADDEDADDITIONALCOMMANDLINE = 26,
|
|
LAUNCHERSERVICES_ADDEDINCLUDEPREREQUISITES = 27,
|
|
LAUNCHERSERVICES_ADDEDBUILDMODE = 28,
|
|
LAUNCHERSERVICES_ADDEDUSEIOSTORE = 29,
|
|
LAUNCHERSERVICES_ADDEDMAKEBINARYCONFIG = 30,
|
|
LAUNCHERSERVICES_ADDEDREFERENCECONTAINERS = 31,
|
|
LAUNCHERSERVICES_REMOVEDNUMCOOKERSTOSPAWN = 32,
|
|
LAUNCHERSERVICES_ADDEDORIGINALRELEASEVERSION = 33,
|
|
LAUNCHERSERVICES_ADDBUILDTARGETNAME = 34,
|
|
LAUNCHERSERVICES_ADDEDRETAINSTAGEDDIRECTORY = 35,
|
|
LAUNCHERSERVICES_REMOVEDRETAINSTAGEDDIRECTORY = 36,
|
|
LAUNCHERSERVICES_ADDZENOPTIONS = 37,
|
|
LAUNCHERSERVICES_ADDBUILDARCHITECTURE = 38,
|
|
LAUNCHERSERVICES_ADDCUSTOMPROPERTIES = 39,
|
|
LAUNCHERSERVICES_INCREMENTALCOOKMODE = 40,
|
|
//ADD NEW STUFF HERE
|
|
|
|
|
|
LAUNCHERSERVICES_FINALPLUSONE,
|
|
LAUNCHERSERVICES_FINAL = LAUNCHERSERVICES_FINALPLUSONE-1,
|
|
};
|
|
|
|
enum ESimpleLauncherVersion
|
|
{
|
|
LAUNCHERSERVICES_SIMPLEPROFILEVERSION=1,
|
|
LAUNCHERSERVICES_SIMPLEFILEFORMATCHANGE = 2,
|
|
};
|
|
|
|
LAUNCHERSERVICES_API bool HasPromotedTarget(const TCHAR* BaseDir, const TCHAR* TargetName, const TCHAR* Platform, EBuildConfiguration Configuration, const TCHAR* Architecture);
|
|
|
|
inline bool TryGetDefaultTargetName(const FString& ProjectFile, EBuildTargetType TargetType, FString& OutTargetName)
|
|
{
|
|
const TArray<FTargetInfo>& Targets = FDesktopPlatformModule::Get()->GetTargetsForProject(ProjectFile);
|
|
for (const FTargetInfo& Target : Targets)
|
|
{
|
|
if (Target.Type == TargetType && Target.DefaultTarget.Get(true))
|
|
{
|
|
OutTargetName = Target.Name;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Implements a simple profile which controls the desired output of the Launcher for simple
|
|
*/
|
|
class FLauncherSimpleProfile final
|
|
: public ILauncherSimpleProfile
|
|
{
|
|
public:
|
|
|
|
FLauncherSimpleProfile(const FString& InDeviceName)
|
|
: DeviceName(InDeviceName)
|
|
{
|
|
SetDefaults();
|
|
}
|
|
|
|
//~ Begin ILauncherSimpleProfile Interface
|
|
|
|
virtual const FString& GetDeviceName() const override
|
|
{
|
|
return DeviceName;
|
|
}
|
|
|
|
virtual FName GetDeviceVariant() const override
|
|
{
|
|
return Variant;
|
|
}
|
|
|
|
virtual EBuildConfiguration GetBuildConfiguration() const override
|
|
{
|
|
return BuildConfiguration;
|
|
}
|
|
|
|
virtual ELauncherProfileCookModes::Type GetCookMode() const override
|
|
{
|
|
return CookMode;
|
|
}
|
|
|
|
virtual void SetDeviceName(const FString& InDeviceName) override
|
|
{
|
|
if (DeviceName != InDeviceName)
|
|
{
|
|
DeviceName = InDeviceName;
|
|
}
|
|
}
|
|
|
|
virtual void SetDeviceVariant(FName InVariant) override
|
|
{
|
|
Variant = InVariant;
|
|
}
|
|
|
|
virtual void SetBuildConfiguration(EBuildConfiguration InConfiguration) override
|
|
{
|
|
BuildConfiguration = InConfiguration;
|
|
}
|
|
|
|
virtual void SetCookMode(ELauncherProfileCookModes::Type InMode) override
|
|
{
|
|
CookMode = InMode;
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Archive) override
|
|
{
|
|
int32 Version = LAUNCHERSERVICES_SIMPLEPROFILEVERSION;
|
|
|
|
Archive << Version;
|
|
|
|
if (Version != LAUNCHERSERVICES_SIMPLEPROFILEVERSION)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// IMPORTANT: make sure to bump LAUNCHERSERVICES_SIMPLEPROFILEVERSION when modifying this!
|
|
Archive << DeviceName
|
|
<< Variant
|
|
<< BuildConfiguration
|
|
<< CookMode;
|
|
|
|
return true;
|
|
}
|
|
|
|
virtual void Save(TJsonWriter<>& Writer) override
|
|
{
|
|
int32 Version = LAUNCHERSERVICES_SIMPLEFILEFORMATCHANGE;
|
|
|
|
Writer.WriteObjectStart();
|
|
Writer.WriteValue(TEXT("Version"), Version);
|
|
Writer.WriteValue(TEXT("DeviceName"), DeviceName);
|
|
Writer.WriteValue(TEXT("Variant"), Variant.ToString());
|
|
Writer.WriteValue(TEXT("BuildConfiguration"), (int32)BuildConfiguration);
|
|
Writer.WriteValue(TEXT("CookMode"), CookMode);
|
|
Writer.WriteObjectEnd();
|
|
}
|
|
|
|
virtual bool Load(const FJsonObject& Object) override
|
|
{
|
|
int32 Version = (int32)Object.GetNumberField(TEXT("Version"));
|
|
if (Version < LAUNCHERSERVICES_SIMPLEFILEFORMATCHANGE)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
DeviceName = Object.GetStringField(TEXT("DeviceName"));
|
|
Variant = *(Object.GetStringField(TEXT("Variant")));
|
|
BuildConfiguration = (EBuildConfiguration)((int32)Object.GetNumberField(TEXT("BuildConfiguration")));
|
|
CookMode = (TEnumAsByte<ELauncherProfileCookModes::Type>)((int32)Object.GetNumberField(TEXT("CookMode")));
|
|
|
|
return true;
|
|
}
|
|
|
|
virtual void SetDefaults() override
|
|
{
|
|
// None will mean the preferred Variant for the device is used.
|
|
Variant = NAME_None;
|
|
|
|
// I don't use FApp::GetBuildConfiguration() because i don't want the act of running in debug the first time to cause the simple
|
|
// profiles created for your persistent devices to be in debug. The user might not see this if they don't expand the Advanced options.
|
|
BuildConfiguration = EBuildConfiguration::Development;
|
|
|
|
CookMode = ELauncherProfileCookModes::OnTheFly;
|
|
}
|
|
|
|
private:
|
|
|
|
// Holds the name of the device this simple profile is for
|
|
FString DeviceName;
|
|
|
|
// Holds the name of the device variant.
|
|
FName Variant;
|
|
|
|
// Holds the desired build configuration (only used if creating new builds).
|
|
EBuildConfiguration BuildConfiguration;
|
|
|
|
// Holds the cooking mode.
|
|
TEnumAsByte<ELauncherProfileCookModes::Type> CookMode;
|
|
};
|
|
|
|
|
|
/**
|
|
* Implements a profile which controls the desired output of the Launcher
|
|
*/
|
|
class FLauncherProfile final
|
|
: public ILauncherProfile
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Gets the folder in which profile files are stored.
|
|
*
|
|
* @return The folder path.
|
|
*/
|
|
static FString GetProfileFolder(bool bNotForLicensees)
|
|
{
|
|
if (bNotForLicensees)
|
|
{
|
|
return FPaths::EngineDir() / TEXT("Restricted/NotForLicensees/Programs/UnrealFrontend/Profiles");
|
|
}
|
|
return FPaths::EngineDir() / TEXT("Programs/UnrealFrontend/Profiles");
|
|
}
|
|
|
|
/**
|
|
* Default constructor.
|
|
*/
|
|
FLauncherProfile(ILauncherProfileManagerRef ProfileManager)
|
|
: LauncherProfileManager(ProfileManager)
|
|
, DefaultLaunchRole(MakeShareable(new FLauncherProfileLaunchRole()))
|
|
{
|
|
SetDefaults();
|
|
ProjectChangedDelegate.AddRaw(this, &FLauncherProfile::OnSelectedProjectChanged);
|
|
}
|
|
|
|
/**
|
|
* Creates and initializes a new instance.
|
|
*
|
|
* @param InProfileName - The name of the profile.
|
|
*/
|
|
FLauncherProfile(ILauncherProfileManagerRef ProfileManager, FGuid InId, const FString& InProfileName)
|
|
: LauncherProfileManager(ProfileManager)
|
|
, DefaultLaunchRole(MakeShareable(new FLauncherProfileLaunchRole()))
|
|
, Id(InId)
|
|
, Name(InProfileName)
|
|
{
|
|
SetDefaults();
|
|
ProjectChangedDelegate.AddRaw(this, &FLauncherProfile::OnSelectedProjectChanged);
|
|
}
|
|
|
|
/**
|
|
* Destructor.
|
|
*/
|
|
~FLauncherProfile( )
|
|
{
|
|
if (DeployedDeviceGroup.IsValid())
|
|
{
|
|
DeployedDeviceGroup->OnDeviceAdded().Remove(OnLauncherDeviceGroupDeviceAddedDelegateHandle);
|
|
DeployedDeviceGroup->OnDeviceRemoved().Remove(OnLauncherDeviceGroupDeviceRemoveDelegateHandle);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the identifier of the device group to deploy to.
|
|
*
|
|
* This method is used internally by the profile manager to read the device group identifier after
|
|
* loading this profile from a file. The profile manager will use this identifier to locate the
|
|
* actual device group to deploy to.
|
|
*
|
|
* @return The device group identifier, or an invalid GUID if no group was set or deployment is disabled.
|
|
*/
|
|
const FGuid& GetDeployedDeviceGroupId( ) const
|
|
{
|
|
return DeployedDeviceGroupId;
|
|
}
|
|
|
|
//~ Begin ILauncherProfile Interface
|
|
|
|
virtual void AddCookedCulture( const FString& CultureName ) override
|
|
{
|
|
CookedCultures.AddUnique(CultureName);
|
|
|
|
Validate();
|
|
}
|
|
|
|
virtual void AddCookedMap( const FString& MapName ) override
|
|
{
|
|
CookedMaps.AddUnique(MapName);
|
|
|
|
Validate();
|
|
}
|
|
|
|
virtual void AddCookedPlatform( const FString& PlatformName ) override
|
|
{
|
|
CookedPlatforms.AddUnique(PlatformName);
|
|
|
|
RefreshValidBuildTargets();
|
|
Validate();
|
|
}
|
|
|
|
virtual void SetDefaultDeployPlatform(const FName PlatformName) override
|
|
{
|
|
|
|
DefaultDeployPlatform = PlatformName;
|
|
|
|
if (DeployedDeviceGroup.IsValid())
|
|
{
|
|
DeployedDeviceGroup->RemoveAllDevices();
|
|
|
|
if (DefaultDeployPlatform != NAME_None)
|
|
{
|
|
TArray<TSharedPtr<ITargetDeviceProxy>> PlatformDeviceProxies;
|
|
ITargetDeviceServicesModule& TargetDeviceServicesModule = FModuleManager::LoadModuleChecked<ITargetDeviceServicesModule>("TargetDeviceServices");
|
|
const TSharedRef<ITargetDeviceProxyManager>& InDeviceProxyManager = TargetDeviceServicesModule.GetDeviceProxyManager();
|
|
|
|
InDeviceProxyManager->GetProxies(NAME_None, true, PlatformDeviceProxies);
|
|
|
|
TSharedPtr<ITargetDeviceProxy> DefaultPlatformDevice;
|
|
for (int32 ProxyIndex = 0; ProxyIndex < PlatformDeviceProxies.Num(); ++ProxyIndex)
|
|
{
|
|
TSharedPtr<ITargetDeviceProxy> DeviceProxy = PlatformDeviceProxies[ProxyIndex];
|
|
|
|
if (DeviceProxy->GetVanillaPlatformId(NAME_None) == DefaultDeployPlatform)
|
|
{
|
|
DefaultPlatformDevice = DeviceProxy;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (DefaultPlatformDevice.IsValid())
|
|
{
|
|
DeployedDeviceGroup->AddDevice(DefaultPlatformDevice->GetTargetDeviceId(NAME_None));
|
|
}
|
|
}
|
|
}
|
|
|
|
Validate();
|
|
}
|
|
|
|
virtual void ClearCookedCultures( ) override
|
|
{
|
|
if (CookedCultures.Num() > 0)
|
|
{
|
|
CookedCultures.Reset();
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void ClearCookedMaps( ) override
|
|
{
|
|
if (CookedMaps.Num() > 0)
|
|
{
|
|
CookedMaps.Reset();
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void ClearCookedPlatforms( ) override
|
|
{
|
|
if (CookedPlatforms.Num() > 0)
|
|
{
|
|
CookedPlatforms.Reset();
|
|
|
|
RefreshValidBuildTargets();
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual ILauncherProfileLaunchRolePtr CreateLaunchRole( ) override
|
|
{
|
|
ILauncherProfileLaunchRolePtr Role = MakeShareable(new FLauncherProfileLaunchRole());
|
|
|
|
LaunchRoles.Add(Role);
|
|
|
|
Validate();
|
|
|
|
return Role;
|
|
}
|
|
|
|
virtual EBuildConfiguration GetBuildConfiguration( ) const override
|
|
{
|
|
return BuildConfiguration;
|
|
}
|
|
|
|
virtual bool HasBuildTargetSpecified() const override
|
|
{
|
|
return BuildTargetSpecified;
|
|
}
|
|
|
|
virtual FString GetBuildTarget() const override
|
|
{
|
|
if (BuildTargetSpecified)
|
|
{
|
|
return BuildTargetName;
|
|
}
|
|
else
|
|
{
|
|
return LauncherProfileManager->GetBuildTarget();
|
|
}
|
|
}
|
|
|
|
virtual EBuildConfiguration GetCookConfiguration( ) const override
|
|
{
|
|
return CookConfiguration;
|
|
}
|
|
|
|
virtual ELauncherProfileCookModes::Type GetCookMode( ) const override
|
|
{
|
|
return CookMode;
|
|
}
|
|
|
|
virtual const FString& GetCookOptions( ) const override
|
|
{
|
|
return CookOptions;
|
|
}
|
|
|
|
virtual const TArray<FString>& GetCookedCultures( ) const override
|
|
{
|
|
return CookedCultures;
|
|
}
|
|
|
|
virtual const bool GetSkipCookingEditorContent() const override
|
|
{
|
|
return bSkipCookingEditorContent;
|
|
}
|
|
|
|
virtual const TArray<FString>& GetCookedMaps( ) const override
|
|
{
|
|
return CookedMaps;
|
|
}
|
|
|
|
virtual const TArray<FString>& GetCookedPlatforms( ) const override
|
|
{
|
|
return CookedPlatforms;
|
|
}
|
|
|
|
virtual const ILauncherProfileLaunchRoleRef& GetDefaultLaunchRole( ) const override
|
|
{
|
|
return DefaultLaunchRole;
|
|
}
|
|
|
|
virtual ILauncherDeviceGroupPtr GetDeployedDeviceGroup( ) override
|
|
{
|
|
// setting the default platform will update the device group. always do this when getting the group because
|
|
// devices come in lazily through messages and can't be added properly at profile load.
|
|
if (DefaultDeployPlatform != NAME_None)
|
|
{
|
|
SetDefaultDeployPlatform(DefaultDeployPlatform);
|
|
}
|
|
return DeployedDeviceGroup;
|
|
}
|
|
|
|
virtual const FName GetDefaultDeployPlatform() const override
|
|
{
|
|
return DefaultDeployPlatform;
|
|
}
|
|
|
|
virtual bool IsGeneratingPatch() const override
|
|
{
|
|
return GeneratePatch;
|
|
}
|
|
|
|
virtual bool ShouldAddPatchLevel() const override
|
|
{
|
|
return AddPatchLevel;
|
|
}
|
|
|
|
virtual bool ShouldStageBaseReleasePaks() const override
|
|
{
|
|
return StageBaseReleasePaks;
|
|
}
|
|
|
|
virtual bool IsCreatingDLC() const override
|
|
{
|
|
return CreateDLC;
|
|
}
|
|
virtual void SetCreateDLC(bool InBuildDLC) override
|
|
{
|
|
CreateDLC = InBuildDLC;
|
|
}
|
|
|
|
virtual FString GetDLCName() const override
|
|
{
|
|
return DLCName;
|
|
}
|
|
virtual void SetDLCName(const FString& InDLCName) override
|
|
{
|
|
DLCName = InDLCName;
|
|
}
|
|
|
|
virtual bool IsDLCIncludingEngineContent() const
|
|
{
|
|
return DLCIncludeEngineContent;
|
|
}
|
|
virtual void SetDLCIncludeEngineContent(bool InDLCIncludeEngineContent)
|
|
{
|
|
DLCIncludeEngineContent = InDLCIncludeEngineContent;
|
|
}
|
|
|
|
|
|
|
|
virtual bool IsCreatingReleaseVersion() const override
|
|
{
|
|
return CreateReleaseVersion;
|
|
}
|
|
|
|
virtual void SetCreateReleaseVersion(bool InCreateReleaseVersion) override
|
|
{
|
|
CreateReleaseVersion = InCreateReleaseVersion;
|
|
}
|
|
|
|
virtual FString GetCreateReleaseVersionName() const override
|
|
{
|
|
return CreateReleaseVersionName;
|
|
}
|
|
|
|
virtual void SetCreateReleaseVersionName(const FString& InCreateReleaseVersionName) override
|
|
{
|
|
CreateReleaseVersionName = InCreateReleaseVersionName;
|
|
}
|
|
|
|
|
|
virtual FString GetBasedOnReleaseVersionName() const override
|
|
{
|
|
return BasedOnReleaseVersionName;
|
|
}
|
|
|
|
virtual void SetBasedOnReleaseVersionName(const FString& InBasedOnReleaseVersionName) override
|
|
{
|
|
BasedOnReleaseVersionName = InBasedOnReleaseVersionName;
|
|
}
|
|
|
|
virtual FString GetOriginalReleaseVersionName() const override
|
|
{
|
|
return OriginalReleaseVersionName;
|
|
}
|
|
|
|
virtual void SetOriginalReleaseVersionName(const FString& InOriginalReleaseVersionName) override
|
|
{
|
|
OriginalReleaseVersionName = InOriginalReleaseVersionName;
|
|
}
|
|
|
|
virtual FString GetReferenceContainerGlobalFileName() const override
|
|
{
|
|
return ReferenceContainerGlobalFileName;
|
|
}
|
|
virtual void SetReferenceContainerGlobalFileName(const FString& InReferenceContainerGlobalFileName) override
|
|
{
|
|
ReferenceContainerGlobalFileName = InReferenceContainerGlobalFileName;
|
|
}
|
|
virtual FString GetReferenceContainerCryptoKeysFileName() const override
|
|
{
|
|
return ReferenceContainerCryptoKeysFileName;
|
|
}
|
|
virtual void SetReferenceContainerCryptoKeysFileName(const FString& InReferenceContainerCryptoKeysFileName) override
|
|
{
|
|
ReferenceContainerCryptoKeysFileName = InReferenceContainerCryptoKeysFileName;
|
|
}
|
|
|
|
virtual ELauncherProfileDeploymentModes::Type GetDeploymentMode( ) const override
|
|
{
|
|
return DeploymentMode;
|
|
}
|
|
|
|
virtual bool GetForceClose() const override
|
|
{
|
|
return ForceClose;
|
|
}
|
|
|
|
virtual FGuid GetId( ) const override
|
|
{
|
|
return Id;
|
|
}
|
|
|
|
virtual void AssignId( bool bOverrideExisting ) override
|
|
{
|
|
if (bOverrideExisting || !Id.IsValid())
|
|
{
|
|
Id = FGuid::NewGuid();
|
|
}
|
|
}
|
|
|
|
|
|
virtual FString GetFileName() const override
|
|
{
|
|
//toupper for filename so that filepaths can be compared the same on case sensitive and case-insensitive platforms
|
|
return GetName().ToUpper() + TEXT("_") + GetId().ToString() + TEXT(".ulp2");
|
|
}
|
|
|
|
virtual FString GetFilePath() const override
|
|
{
|
|
return GetProfileFolder(bNotForLicensees) / GetFileName();
|
|
}
|
|
|
|
virtual ELauncherProfileLaunchModes::Type GetLaunchMode( ) const override
|
|
{
|
|
return LaunchMode;
|
|
}
|
|
|
|
virtual const TArray<ILauncherProfileLaunchRolePtr>& GetLaunchRoles( ) const override
|
|
{
|
|
return LaunchRoles;
|
|
}
|
|
|
|
virtual const int32 GetLaunchRolesFor( const FString& DeviceId, TArray<ILauncherProfileLaunchRolePtr>& OutRoles ) override
|
|
{
|
|
OutRoles.Empty();
|
|
|
|
if (LaunchMode == ELauncherProfileLaunchModes::CustomRoles)
|
|
{
|
|
for (TArray<ILauncherProfileLaunchRolePtr>::TConstIterator It(LaunchRoles); It; ++It)
|
|
{
|
|
ILauncherProfileLaunchRolePtr Role = *It;
|
|
|
|
if (Role->GetAssignedDevice() == DeviceId)
|
|
{
|
|
OutRoles.Add(Role);
|
|
}
|
|
}
|
|
}
|
|
else if (LaunchMode == ELauncherProfileLaunchModes::DefaultRole)
|
|
{
|
|
OutRoles.Add(DefaultLaunchRole);
|
|
}
|
|
|
|
return OutRoles.Num();
|
|
}
|
|
|
|
virtual FString GetName( ) const override
|
|
{
|
|
return Name;
|
|
}
|
|
|
|
virtual FString GetDescription() const override
|
|
{
|
|
return Description;
|
|
}
|
|
|
|
virtual ELauncherProfilePackagingModes::Type GetPackagingMode( ) const override
|
|
{
|
|
return PackagingMode;
|
|
}
|
|
|
|
virtual FString GetPackageDirectory( ) const override
|
|
{
|
|
return PackageDir;
|
|
}
|
|
|
|
virtual bool IsArchiving( ) const override
|
|
{
|
|
return bArchive;
|
|
}
|
|
|
|
virtual FString GetArchiveDirectory( ) const override
|
|
{
|
|
return ArchiveDir;
|
|
}
|
|
|
|
virtual bool HasProjectSpecified() const override
|
|
{
|
|
return ProjectSpecified;
|
|
}
|
|
|
|
virtual FString GetProjectName() const override
|
|
{
|
|
if (ProjectSpecified)
|
|
{
|
|
FString Path = FLauncherProjectPath::GetProjectName(FullProjectPath);
|
|
return Path;
|
|
}
|
|
return LauncherProfileManager->GetProjectName();
|
|
}
|
|
|
|
virtual FString GetProjectBasePath() const override
|
|
{
|
|
if (ProjectSpecified)
|
|
{
|
|
return FLauncherProjectPath::GetProjectBasePath(FullProjectPath);
|
|
}
|
|
return LauncherProfileManager->GetProjectBasePath();
|
|
}
|
|
|
|
virtual FString GetProjectPath() const override
|
|
{
|
|
if (ProjectSpecified)
|
|
{
|
|
return FullProjectPath;
|
|
}
|
|
return LauncherProfileManager->GetProjectPath();
|
|
}
|
|
|
|
virtual uint32 GetTimeout() const override
|
|
{
|
|
return Timeout;
|
|
}
|
|
|
|
virtual bool HasValidationError() const override
|
|
{
|
|
return ValidationErrors.Num() > 0;
|
|
}
|
|
|
|
virtual bool HasValidationError( ELauncherProfileValidationErrors::Type Error ) const override
|
|
{
|
|
return ValidationErrors.Contains(Error);
|
|
}
|
|
|
|
virtual FString GetInvalidPlatform() const override
|
|
{
|
|
return InvalidPlatform;
|
|
}
|
|
|
|
virtual ELauncherProfileBuildModes::Type GetBuildMode() const override
|
|
{
|
|
return BuildMode;
|
|
}
|
|
|
|
virtual bool ShouldBuild() override
|
|
{
|
|
bool bBuild = true;
|
|
if (BuildMode == ELauncherProfileBuildModes::DoNotBuild)
|
|
{
|
|
bBuild = false;
|
|
}
|
|
else if (BuildMode == ELauncherProfileBuildModes::Auto)
|
|
{
|
|
if (FApp::GetEngineIsPromotedBuild())
|
|
{
|
|
bBuild = false;
|
|
|
|
TArray<FString> TargetPlatformNames = FindPlatforms();
|
|
for (const FString& TargetPlatformName : TargetPlatformNames)
|
|
{
|
|
// Get the target we're building for
|
|
const ITargetPlatform* TargetPlatform = GetTargetPlatformManager()->FindTargetPlatform(TargetPlatformName);
|
|
const PlatformInfo::FTargetPlatformInfo& PlatformInfo = TargetPlatform->GetTargetPlatformInfo();
|
|
|
|
// Figure out which target we're building
|
|
FString ReceiptDir;
|
|
FString TargetName;
|
|
if (TryGetDefaultTargetName(FPaths::GetProjectFilePath(), PlatformInfo.PlatformType, TargetName))
|
|
{
|
|
ReceiptDir = FPaths::GetPath(FPaths::GetProjectFilePath());
|
|
}
|
|
else if (TryGetDefaultTargetName(FString(), PlatformInfo.PlatformType, TargetName))
|
|
{
|
|
FText Reason;
|
|
if (TargetPlatform->RequiresTempTarget(false, BuildConfiguration, false, Reason))
|
|
{
|
|
UE_LOG(LogLauncherProfile, Log, TEXT("Project requires temp target (%s)"), *Reason.ToString());
|
|
ReceiptDir = FPaths::GetPath(FPaths::GetProjectFilePath());
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogLauncherProfile, Log, TEXT("Project does not require temp target"));
|
|
ReceiptDir = FPaths::EngineDir();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogLauncherProfile, Log, TEXT("Unable to find any targets for platform %s - forcing build"), *TargetPlatformName);
|
|
bBuild = true;
|
|
break;
|
|
}
|
|
|
|
// Check if the existing target is valid
|
|
FString BuildPlatform = PlatformInfo.DataDrivenPlatformInfo->UBTPlatformString;
|
|
if (!HasPromotedTarget(*ReceiptDir, *TargetName, *BuildPlatform, BuildConfiguration, nullptr))
|
|
{
|
|
bBuild = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return bBuild;
|
|
}
|
|
|
|
virtual bool IsBuildingUAT() const override
|
|
{
|
|
return BuildUAT;
|
|
}
|
|
|
|
virtual FString GetAdditionalCommandLineParameters() const override
|
|
{
|
|
return AdditionalCommandLineParameters;
|
|
}
|
|
|
|
virtual bool IsCookingIncrementally( ) const override
|
|
{
|
|
if ( CookMode != ELauncherProfileCookModes::DoNotCook )
|
|
{
|
|
return (IncrementalCookMode == ELauncherProfileIncrementalCookMode::ModifiedOnly);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
virtual ELauncherProfileIncrementalCookMode::Type GetIncrementalCookMode() const override
|
|
{
|
|
return IncrementalCookMode;
|
|
}
|
|
|
|
|
|
virtual bool IsIterateSharedCookedBuild() const override
|
|
{
|
|
if ( CookMode != ELauncherProfileCookModes::DoNotCook )
|
|
{
|
|
return IterateSharedCookedBuild;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
virtual bool IsCompressed() const override
|
|
{
|
|
return Compressed;
|
|
}
|
|
|
|
virtual bool IsEncryptingIniFiles() const override
|
|
{
|
|
return EncryptIniFiles;
|
|
}
|
|
|
|
virtual bool IsForDistribution() const override
|
|
{
|
|
return ForDistribution;
|
|
}
|
|
|
|
virtual bool IsCookingUnversioned( ) const override
|
|
{
|
|
return CookUnversioned;
|
|
}
|
|
|
|
virtual bool IsDeployablePlatform( const FString& PlatformName ) override
|
|
{
|
|
if (CookMode == ELauncherProfileCookModes::ByTheBook || CookMode == ELauncherProfileCookModes::ByTheBookInEditor)
|
|
{
|
|
return CookedPlatforms.Contains(PlatformName);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
virtual bool IsDeployingIncrementally( ) const override
|
|
{
|
|
return DeployIncremental;
|
|
}
|
|
|
|
virtual bool IsFileServerHidden( ) const override
|
|
{
|
|
return HideFileServerWindow;
|
|
}
|
|
|
|
virtual bool IsFileServerStreaming( ) const override
|
|
{
|
|
return DeployStreamingServer;
|
|
}
|
|
|
|
virtual bool IsPackingWithUnrealPak( ) const override
|
|
{
|
|
return DeployWithUnrealPak;
|
|
}
|
|
|
|
virtual bool IsIncludingPrerequisites() const override
|
|
{
|
|
return IncludePrerequisites;
|
|
}
|
|
|
|
virtual bool IsGeneratingChunks() const override
|
|
{
|
|
return bGenerateChunks;
|
|
}
|
|
|
|
virtual bool IsGenerateHttpChunkData() const override
|
|
{
|
|
return bGenerateHttpChunkData;
|
|
}
|
|
|
|
virtual FString GetHttpChunkDataDirectory() const override
|
|
{
|
|
return HttpChunkDataDirectory;
|
|
}
|
|
|
|
virtual FString GetHttpChunkDataReleaseName() const override
|
|
{
|
|
return HttpChunkDataReleaseName;
|
|
}
|
|
|
|
virtual bool IsValidForLaunch( ) override
|
|
{
|
|
return (ValidationErrors.Num() == 0);
|
|
}
|
|
|
|
virtual void RemoveCookedCulture( const FString& CultureName ) override
|
|
{
|
|
CookedCultures.Remove(CultureName);
|
|
|
|
Validate();
|
|
}
|
|
|
|
virtual void RemoveCookedMap( const FString& MapName ) override
|
|
{
|
|
CookedMaps.Remove(MapName);
|
|
|
|
Validate();
|
|
}
|
|
|
|
virtual void RemoveCookedPlatform( const FString& PlatformName ) override
|
|
{
|
|
CookedPlatforms.Remove(PlatformName);
|
|
|
|
RefreshValidBuildTargets();
|
|
Validate();
|
|
}
|
|
|
|
virtual void RemoveLaunchRole( const ILauncherProfileLaunchRoleRef& Role ) override
|
|
{
|
|
LaunchRoles.Remove(Role);
|
|
|
|
Validate();
|
|
}
|
|
|
|
virtual bool Serialize( FArchive& Archive ) override
|
|
{
|
|
int32 Version = LAUNCHERSERVICES_FINAL;
|
|
|
|
Archive << Version;
|
|
|
|
if (Version < LAUNCHERSERVICES_MINPROFILEVERSION)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (Version > LAUNCHERSERVICES_FINAL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (Archive.IsSaving())
|
|
{
|
|
if (DeployedDeviceGroup.IsValid())
|
|
{
|
|
DeployedDeviceGroupId = DeployedDeviceGroup->GetId();
|
|
}
|
|
else
|
|
{
|
|
DeployedDeviceGroupId = FGuid();
|
|
}
|
|
}
|
|
|
|
// IMPORTANT: make sure to bump LAUNCHERSERVICES_PROFILEVERSION when modifying this!
|
|
bool BuildGame = false;
|
|
bool CookIncremental = false;
|
|
Archive << Id
|
|
<< Name
|
|
<< Description
|
|
<< BuildConfiguration
|
|
<< ProjectSpecified
|
|
<< ShareableProjectPath
|
|
<< CookConfiguration
|
|
<< CookIncremental
|
|
<< CookOptions
|
|
<< CookMode
|
|
<< CookUnversioned
|
|
<< CookedCultures
|
|
<< CookedMaps
|
|
<< CookedPlatforms
|
|
<< DeployStreamingServer
|
|
<< DeployWithUnrealPak
|
|
<< DeployedDeviceGroupId
|
|
<< DeploymentMode
|
|
<< HideFileServerWindow
|
|
<< LaunchMode
|
|
<< PackagingMode
|
|
<< PackageDir
|
|
<< BuildGame
|
|
<< ForceClose
|
|
<< Timeout;
|
|
|
|
if (Version >= LAUNCHERSERVICES_SHAREABLEPROJECTPATHS)
|
|
{
|
|
FullProjectPath = FPaths::ConvertRelativePathToFull(FPaths::RootDir(), ShareableProjectPath);
|
|
}
|
|
|
|
FString DeployPlatformString = DefaultDeployPlatform.ToString();
|
|
if (Version >= LAUNCHERSERVICES_FIXCOMPRESSIONSERIALIZE)
|
|
{
|
|
Archive << Compressed;
|
|
}
|
|
if ( Version>= LAUNCHERSERVICES_ADDEDENCRYPTINIFILES)
|
|
{
|
|
Archive << EncryptIniFiles;
|
|
Archive << ForDistribution;
|
|
}
|
|
if (Version >= LAUNCHERSERVICES_ADDEDDEFAULTDEPLOYPLATFORM)
|
|
{
|
|
Archive << DeployPlatformString;
|
|
}
|
|
if (Version >= LAUNCHERSERVICES_ADDEDNUMCOOKERSTOSPAWN && Version < LAUNCHERSERVICES_REMOVEDNUMCOOKERSTOSPAWN)
|
|
{
|
|
int32 OldNumCookersToSpawn;
|
|
Archive << OldNumCookersToSpawn;
|
|
}
|
|
if (Version >= LAUNCHERSERVICES_ADDEDSKIPCOOKINGEDITORCONTENT)
|
|
{
|
|
Archive << bSkipCookingEditorContent;
|
|
}
|
|
if (Version >= LAUNCHERSERVICES_ADDEDINCREMENTALDEPLOYVERSION)
|
|
{
|
|
Archive << DeployIncremental;
|
|
}
|
|
if ( Version >= LAUNCHERSERVICES_REMOVEDPATCHSOURCECONTENTPATH )
|
|
{
|
|
Archive << GeneratePatch;
|
|
}
|
|
if ( Version >= LAUNCHERSERVICES_ADDEDMULTILEVELPATCHING )
|
|
{
|
|
Archive << AddPatchLevel;
|
|
Archive << StageBaseReleasePaks;
|
|
}
|
|
else if ( Version >= LAUNCHERSERVICES_ADDEDPATCHSOURCECONTENTPATH)
|
|
{
|
|
FString Temp;
|
|
Archive << Temp;
|
|
Archive << GeneratePatch;
|
|
}
|
|
if (Version >= LAUNCHERSERVICES_ADDEDDLCINCLUDEENGINECONTENT)
|
|
{
|
|
Archive << DLCIncludeEngineContent;
|
|
}
|
|
|
|
if ( Version >= LAUNCHERSERVICES_ADDEDRELEASEVERSION )
|
|
{
|
|
Archive << CreateReleaseVersion;
|
|
Archive << CreateReleaseVersionName;
|
|
Archive << BasedOnReleaseVersionName;
|
|
|
|
Archive << CreateDLC;
|
|
Archive << DLCName;
|
|
}
|
|
if (Version >= LAUNCHERSERVICES_ADDEDGENERATECHUNKS)
|
|
{
|
|
Archive << bGenerateChunks;
|
|
Archive << bGenerateHttpChunkData;
|
|
Archive << HttpChunkDataDirectory;
|
|
Archive << HttpChunkDataReleaseName;
|
|
}
|
|
if (Version >= LAUNCHERSERVICES_ADDARCHIVE)
|
|
{
|
|
Archive << bArchive;
|
|
Archive << ArchiveDir;
|
|
}
|
|
if (Version >= LAUNCHERSERVICES_ADDEDADDITIONALCOMMANDLINE)
|
|
{
|
|
Archive << AdditionalCommandLineParameters;
|
|
}
|
|
if (Version >= LAUNCHERSERVICES_ADDEDINCLUDEPREREQUISITES)
|
|
{
|
|
Archive << IncludePrerequisites;
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDEDBUILDMODE)
|
|
{
|
|
Archive << BuildMode;
|
|
}
|
|
else if(Archive.IsLoading())
|
|
{
|
|
BuildMode = BuildGame ? ELauncherProfileBuildModes::Build : ELauncherProfileBuildModes::DoNotBuild;
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDEDUSEIOSTORE)
|
|
{
|
|
Archive << bUseIoStore;
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDEDMAKEBINARYCONFIG)
|
|
{
|
|
Archive << bMakeBinaryConfig;
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDEDREFERENCECONTAINERS)
|
|
{
|
|
Archive << ReferenceContainerGlobalFileName;
|
|
Archive << ReferenceContainerCryptoKeysFileName;
|
|
}
|
|
if (Version >= LAUNCHERSERVICES_ADDEDORIGINALRELEASEVERSION)
|
|
{
|
|
Archive << OriginalReleaseVersionName;
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDBUILDTARGETNAME)
|
|
{
|
|
Archive << BuildTargetSpecified;
|
|
Archive << BuildTargetName;
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDEDRETAINSTAGEDDIRECTORY && Version < LAUNCHERSERVICES_REMOVEDRETAINSTAGEDDIRECTORY)
|
|
{
|
|
bool bRetainStagedDirectory = false;
|
|
Archive << bRetainStagedDirectory;
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDZENOPTIONS)
|
|
{
|
|
Archive << bUseZenStore;
|
|
Archive << bImportingZenSnapshot;
|
|
Archive << bUseZenPakStreaming;
|
|
Archive << ZenPakStreamingPath;
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDBUILDARCHITECTURE)
|
|
{
|
|
Archive << ClientArchitectures;
|
|
Archive << ServerArchitectures;
|
|
Archive << EditorArchitectures;
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDCUSTOMPROPERTIES)
|
|
{
|
|
Archive << CustomStringProperties;
|
|
Archive << CustomBoolProperties;
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_INCREMENTALCOOKMODE)
|
|
{
|
|
Archive << IncrementalCookMode;
|
|
}
|
|
else if (Archive.IsLoading())
|
|
{
|
|
IncrementalCookMode = CookIncremental ? ELauncherProfileIncrementalCookMode::ModifiedOnly : ELauncherProfileIncrementalCookMode::None;
|
|
}
|
|
|
|
DefaultLaunchRole->Serialize(Archive);
|
|
|
|
// serialize launch roles
|
|
if (Archive.IsLoading())
|
|
{
|
|
DeployedDeviceGroup.Reset();
|
|
LaunchRoles.Reset();
|
|
}
|
|
|
|
int32 NumLaunchRoles = LaunchRoles.Num();
|
|
|
|
Archive << NumLaunchRoles;
|
|
|
|
for (int32 RoleIndex = 0; RoleIndex < NumLaunchRoles; ++RoleIndex)
|
|
{
|
|
if (Archive.IsLoading())
|
|
{
|
|
LaunchRoles.Add(MakeShareable(new FLauncherProfileLaunchRole(Archive)));
|
|
}
|
|
else
|
|
{
|
|
LaunchRoles[RoleIndex]->Serialize(Archive);
|
|
}
|
|
}
|
|
|
|
if (Archive.IsLoading())
|
|
{
|
|
DefaultDeployPlatform = FName(*DeployPlatformString);
|
|
}
|
|
|
|
if (DefaultDeployPlatform != NAME_None)
|
|
{
|
|
SetDefaultDeployPlatform(DefaultDeployPlatform);
|
|
}
|
|
|
|
if (Archive.IsLoading())
|
|
{
|
|
RefreshValidBuildTargets();
|
|
}
|
|
Validate();
|
|
|
|
return true;
|
|
}
|
|
|
|
virtual void Save(TJsonWriter<>& Writer) override
|
|
{
|
|
int32 Version = LAUNCHERSERVICES_FINAL;
|
|
|
|
if (DeployedDeviceGroup.IsValid())
|
|
{
|
|
DeployedDeviceGroupId = DeployedDeviceGroup->GetId();
|
|
}
|
|
else
|
|
{
|
|
DeployedDeviceGroupId = FGuid();
|
|
}
|
|
|
|
Writer.WriteObjectStart();
|
|
Writer.WriteValue("Version", Version);
|
|
Writer.WriteValue("Id", Id.ToString());
|
|
Writer.WriteValue("Name", Name);
|
|
Writer.WriteValue("Description", Description);
|
|
Writer.WriteValue("BuildConfiguration", (int32)BuildConfiguration);
|
|
Writer.WriteValue("ProjectSpecified", ProjectSpecified);
|
|
Writer.WriteValue("ShareableProjectPath", ShareableProjectPath);
|
|
Writer.WriteValue("CookConfiguration", (int32)CookConfiguration);
|
|
Writer.WriteValue("CookOptions", CookOptions);
|
|
Writer.WriteValue("CookMode", CookMode);
|
|
Writer.WriteValue("CookUnversioned", CookUnversioned);
|
|
|
|
// write the cultures
|
|
if (CookedCultures.Num() > 0)
|
|
{
|
|
Writer.WriteArrayStart("CookedCultures");
|
|
for (auto Value : CookedCultures)
|
|
{
|
|
Writer.WriteValue(Value);
|
|
}
|
|
Writer.WriteArrayEnd();
|
|
}
|
|
|
|
// write the maps
|
|
if (CookedMaps.Num() > 0)
|
|
{
|
|
Writer.WriteArrayStart("CookedMaps");
|
|
for (auto Value : CookedMaps)
|
|
{
|
|
Writer.WriteValue(Value);
|
|
}
|
|
Writer.WriteArrayEnd();
|
|
}
|
|
|
|
// write the platforms
|
|
if (CookedPlatforms.Num() > 0)
|
|
{
|
|
Writer.WriteArrayStart("CookedPlatforms");
|
|
for (auto Value : CookedPlatforms)
|
|
{
|
|
Writer.WriteValue(Value);
|
|
}
|
|
Writer.WriteArrayEnd();
|
|
}
|
|
|
|
Writer.WriteValue("DeployStreamingServer", DeployStreamingServer);
|
|
Writer.WriteValue("DeployWithUnrealPak", DeployWithUnrealPak);
|
|
Writer.WriteValue("DeployedDeviceGroupId", DeployedDeviceGroupId.ToString());
|
|
Writer.WriteValue("DeploymentMode", DeploymentMode);
|
|
Writer.WriteValue("HideFileServerWindow", HideFileServerWindow);
|
|
Writer.WriteValue("LaunchMode", LaunchMode);
|
|
Writer.WriteValue("PackagingMode", PackagingMode);
|
|
Writer.WriteValue("PackageDir", PackageDir);
|
|
Writer.WriteValue("BuildMode", BuildMode);
|
|
Writer.WriteValue("ForceClose", ForceClose);
|
|
Writer.WriteValue("Timeout", (int32)Timeout);
|
|
Writer.WriteValue("Compressed", Compressed);
|
|
Writer.WriteValue("EncryptIniFiles", EncryptIniFiles);
|
|
Writer.WriteValue("ForDistribution", ForDistribution);
|
|
Writer.WriteValue("DeployPlatform", DefaultDeployPlatform.ToString());
|
|
Writer.WriteValue("SkipCookingEditorContent", bSkipCookingEditorContent);
|
|
Writer.WriteValue("DeployIncremental", DeployIncremental);
|
|
Writer.WriteValue("GeneratePatch", GeneratePatch);
|
|
Writer.WriteValue("AddPatchLevel", AddPatchLevel);
|
|
Writer.WriteValue("StageBaseReleasePaks", StageBaseReleasePaks);
|
|
Writer.WriteValue("DLCIncludeEngineContent", DLCIncludeEngineContent);
|
|
Writer.WriteValue("CreateReleaseVersion", CreateReleaseVersion);
|
|
Writer.WriteValue("CreateReleaseVersionName", CreateReleaseVersionName);
|
|
Writer.WriteValue("BasedOnReleaseVersionName", BasedOnReleaseVersionName);
|
|
Writer.WriteValue("ReferenceContainerGlobalFileName", ReferenceContainerGlobalFileName);
|
|
Writer.WriteValue("ReferenceContainerCryptoKeysFileName", ReferenceContainerCryptoKeysFileName);
|
|
Writer.WriteValue("OriginalReleaseVersionName", OriginalReleaseVersionName);
|
|
Writer.WriteValue("CreateDLC", CreateDLC);
|
|
Writer.WriteValue("DLCName", DLCName);
|
|
Writer.WriteValue("GenerateChunks", bGenerateChunks);
|
|
Writer.WriteValue("GenerateHttpChunkData", bGenerateHttpChunkData);
|
|
Writer.WriteValue("HttpChunkDataDirectory", HttpChunkDataDirectory);
|
|
Writer.WriteValue("HttpChunkDataReleaseName", HttpChunkDataReleaseName);
|
|
Writer.WriteValue("Archive", bArchive);
|
|
Writer.WriteValue("ArchiveDirectory", ArchiveDir);
|
|
Writer.WriteValue("AdditionalCommandLineParameters", AdditionalCommandLineParameters);
|
|
Writer.WriteValue("IncludePrerequisites", IncludePrerequisites);
|
|
Writer.WriteValue("UseIoStore", bUseIoStore);
|
|
Writer.WriteValue("MakeBinaryConfig", bMakeBinaryConfig);
|
|
Writer.WriteValue("BuildTargetSpecified", BuildTargetSpecified);
|
|
Writer.WriteValue("BuildTargetName", BuildTargetName);
|
|
Writer.WriteValue("UseZenStore", bUseZenStore);
|
|
Writer.WriteValue("ImportingZenSnapshot", bImportingZenSnapshot);
|
|
Writer.WriteValue("UseZenPakStreaming", bUseZenPakStreaming);
|
|
Writer.WriteValue("ZenPakStreamingPath", ZenPakStreamingPath);
|
|
Writer.WriteValue("ClientArchitectures", ClientArchitectures);
|
|
Writer.WriteValue("ServerArchitectures", ServerArchitectures);
|
|
Writer.WriteValue("EditorArchitectures", EditorArchitectures);
|
|
Writer.WriteValue("CustomStringProperties", CustomStringProperties);
|
|
Writer.WriteValue("CustomBoolProperties", CustomBoolProperties);
|
|
Writer.WriteValue("IncrementalCookMode", IncrementalCookMode);
|
|
|
|
// serialize the default launch role
|
|
DefaultLaunchRole->Save(Writer, TEXT("DefaultRole"));
|
|
|
|
// serialize the launch roles
|
|
if (LaunchRoles.Num())
|
|
{
|
|
Writer.WriteArrayStart("LaunchRoles");
|
|
for (auto Value : LaunchRoles)
|
|
{
|
|
Value->Save(Writer);
|
|
}
|
|
Writer.WriteArrayEnd();
|
|
}
|
|
|
|
// write out the UAT project params
|
|
SaveUATParams(Writer);
|
|
Writer.WriteObjectEnd();
|
|
}
|
|
|
|
void SaveUATParams(TJsonWriter<>& Writer)
|
|
{
|
|
Writer.WriteArrayStart("scripts");
|
|
Writer.WriteObjectStart();
|
|
|
|
TArray<FString> Platforms = FindPlatforms();
|
|
|
|
// script to run
|
|
Writer.WriteValue("script", TEXT("BuildCookRun"));
|
|
|
|
// project to operate on
|
|
Writer.WriteValue("project", ProjectSpecified ? ShareableProjectPath : "");
|
|
|
|
// ancillary arguments
|
|
Writer.WriteValue("noP4", true);
|
|
Writer.WriteValue("nocompile", !IsBuildingUAT());
|
|
Writer.WriteValue("nocompileeditor", FApp::IsEngineInstalled());
|
|
Writer.WriteValue("unrealexe", GetEditorExe());
|
|
Writer.WriteValue("utf8output", true);
|
|
|
|
// client configurations
|
|
Writer.WriteArrayStart("clientconfig");
|
|
Writer.WriteValue(LexToString(BuildConfiguration));
|
|
Writer.WriteArrayEnd();
|
|
|
|
// server configurations
|
|
Writer.WriteArrayStart("serverconfig");
|
|
Writer.WriteValue(LexToString(BuildConfiguration));
|
|
Writer.WriteArrayEnd();
|
|
|
|
// platforms
|
|
TArray<FString> ServerPlatforms;
|
|
TArray<FString> ClientPlatforms;
|
|
FString OptionalParams;
|
|
bool ClosesAfterLaunch = FindAllPlatforms(ServerPlatforms, ClientPlatforms, OptionalParams);
|
|
if (ServerPlatforms.Num() > 0)
|
|
{
|
|
Writer.WriteValue("server", true);
|
|
Writer.WriteArrayStart("serverplatform");
|
|
for (int32 Idx = 0; Idx < ServerPlatforms.Num(); Idx++)
|
|
{
|
|
Writer.WriteValue(ServerPlatforms[Idx]);
|
|
}
|
|
Writer.WriteArrayEnd();
|
|
}
|
|
|
|
if (ClientPlatforms.Num() > 0)
|
|
{
|
|
Writer.WriteArrayStart("platform");
|
|
for (int32 Idx = 0; Idx < ClientPlatforms.Num(); Idx++)
|
|
{
|
|
Writer.WriteValue(ClientPlatforms[Idx]);
|
|
}
|
|
Writer.WriteArrayEnd();
|
|
}
|
|
|
|
// optional params
|
|
TMap<FString, FString> OptionalCommands = ParseCommands(OptionalParams);
|
|
for (TMap<FString, FString>::TIterator Iter = OptionalCommands.CreateIterator(); Iter; ++Iter)
|
|
{
|
|
Writer.WriteValue(Iter.Key(), Iter.Value());
|
|
}
|
|
|
|
// game command line
|
|
FString InitialMap = GetDefaultLaunchRole()->GetInitialMap();
|
|
if (InitialMap.IsEmpty() && GetCookedMaps().Num() == 1)
|
|
{
|
|
InitialMap = GetCookedMaps()[0];
|
|
}
|
|
Writer.WriteObjectStart("cmdline");
|
|
Writer.WriteValue("", InitialMap);
|
|
Writer.WriteValue("messaging", true);
|
|
Writer.WriteObjectEnd();
|
|
|
|
// devices
|
|
ITargetDeviceServicesModule& DeviceServiceModule = FModuleManager::LoadModuleChecked<ITargetDeviceServicesModule>(TEXT("TargetDeviceServices"));
|
|
TSharedRef<ITargetDeviceProxyManager> DeviceProxyManager = DeviceServiceModule.GetDeviceProxyManager();
|
|
ILauncherDeviceGroupPtr DeviceGroup = GetDeployedDeviceGroup();
|
|
TMap<FString, FString> RoleCommands;
|
|
FString CommandLine = GetDefaultLaunchRole()->GetUATCommandLine();
|
|
if (CommandLine.Len() > 0)
|
|
{
|
|
// parse out the commands
|
|
TMap<FString, FString> Commands = ParseCommands(CommandLine);
|
|
RoleCommands.Append(Commands);
|
|
}
|
|
if (DeviceGroup.IsValid())
|
|
{
|
|
const TArray<FString>& Devices = DeviceGroup->GetDeviceIDs();
|
|
bool bUseVsync = false;
|
|
|
|
Writer.WriteArrayStart("device");
|
|
|
|
// for each deployed device...
|
|
for (int32 DeviceIndex = 0; DeviceIndex < Devices.Num(); ++DeviceIndex)
|
|
{
|
|
const FString& DeviceId = Devices[DeviceIndex];
|
|
TSharedPtr<ITargetDeviceProxy> DeviceProxy = DeviceProxyManager->FindProxyDeviceForTargetDevice(DeviceId);
|
|
Writer.WriteValue(DeviceId);
|
|
if (DeviceProxy.IsValid())
|
|
{
|
|
TArray<ILauncherProfileLaunchRolePtr> Roles;
|
|
if (GetLaunchRolesFor(DeviceId, Roles) > 0)
|
|
{
|
|
for (int32 RoleIndex = 0; RoleIndex < Roles.Num(); RoleIndex++)
|
|
{
|
|
if (!bUseVsync && Roles[RoleIndex]->IsVsyncEnabled())
|
|
{
|
|
bUseVsync = true;
|
|
}
|
|
CommandLine = Roles[RoleIndex]->GetUATCommandLine();
|
|
TMap<FString, FString> Commands = ParseCommands(CommandLine);
|
|
RoleCommands.Append(Commands);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Writer.WriteArrayEnd();
|
|
}
|
|
|
|
// write out the additional command-line arguments
|
|
static FGuid SessionId(FGuid::NewGuid());
|
|
Writer.WriteObjectStart("addcmdline");
|
|
Writer.WriteValue("sessionid", SessionId.ToString());
|
|
Writer.WriteValue("sessionowner", FPlatformProcess::UserName(true));
|
|
Writer.WriteValue("sessionname", GetName());
|
|
for (TMap<FString, FString>::TIterator Iter = RoleCommands.CreateIterator(); Iter; ++Iter)
|
|
{
|
|
Writer.WriteValue(Iter.Key(), Iter.Value());
|
|
}
|
|
Writer.WriteObjectEnd();
|
|
|
|
// map list
|
|
Writer.WriteArrayStart("map");
|
|
const TArray<FString>& CookedMapsArray = GetCookedMaps();
|
|
if (CookedMapsArray.Num() > 0 && (GetCookMode() == ELauncherProfileCookModes::ByTheBook || GetCookMode() == ELauncherProfileCookModes::ByTheBookInEditor))
|
|
{
|
|
for (int32 MapIndex = 0; MapIndex < CookedMapsArray.Num(); ++MapIndex)
|
|
{
|
|
Writer.WriteValue(CookedMapsArray[MapIndex]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Writer.WriteValue(InitialMap);
|
|
}
|
|
Writer.WriteArrayEnd();
|
|
|
|
// staging directory
|
|
auto PackageDirectory = GetPackageDirectory();
|
|
if (PackageDirectory.Len() > 0)
|
|
{
|
|
Writer.WriteValue("stagingdirectory", PackageDirectory);
|
|
}
|
|
|
|
// build
|
|
Writer.WriteValue("build", ShouldBuild());
|
|
|
|
// cook
|
|
switch (GetCookMode())
|
|
{
|
|
case ELauncherProfileCookModes::ByTheBook:
|
|
{
|
|
Writer.WriteValue("cook", true);
|
|
Writer.WriteValue("unversionedcookedcontent", IsCookingUnversioned());
|
|
Writer.WriteValue("pak", IsPackingWithUnrealPak());
|
|
|
|
if (IsCreatingReleaseVersion())
|
|
{
|
|
Writer.WriteValue("createreleaseversion", GetCreateReleaseVersionName());
|
|
}
|
|
|
|
if (IsCreatingDLC())
|
|
{
|
|
Writer.WriteValue("dlcname", GetDLCName());
|
|
}
|
|
|
|
Writer.WriteValue("generatepatch", IsGeneratingPatch());
|
|
|
|
if (IsGeneratingPatch() || IsCreatingReleaseVersion() || IsCreatingDLC())
|
|
{
|
|
if (GetBasedOnReleaseVersionName().IsEmpty() == false)
|
|
{
|
|
Writer.WriteValue("basedonreleaseversion", GetBasedOnReleaseVersionName());
|
|
Writer.WriteValue("stagebasereleasepaks", ShouldStageBaseReleasePaks());
|
|
}
|
|
|
|
if (GetOriginalReleaseVersionName().IsEmpty() == false)
|
|
{
|
|
Writer.WriteValue("originalreleaseversion", GetOriginalReleaseVersionName());
|
|
}
|
|
}
|
|
|
|
if (IsGeneratingPatch())
|
|
{
|
|
Writer.WriteValue("addpatchlevel", ShouldAddPatchLevel());
|
|
}
|
|
|
|
Writer.WriteValue("manifests", IsGeneratingChunks());
|
|
|
|
if (IsGenerateHttpChunkData())
|
|
{
|
|
Writer.WriteValue("createchunkinstall", true);
|
|
Writer.WriteValue("chunkinstalldirectory", GetHttpChunkDataDirectory());
|
|
Writer.WriteValue("chunkinstallversion", GetHttpChunkDataReleaseName());
|
|
}
|
|
|
|
if (IsArchiving())
|
|
{
|
|
Writer.WriteValue("archive", true);
|
|
Writer.WriteValue("archivedirectory", GetArchiveDirectory());
|
|
}
|
|
|
|
TMap<FString, FString> CookCommands = ParseCommands(GetCookOptions());
|
|
for (TMap<FString, FString>::TIterator Iter = CookCommands.CreateIterator(); Iter; ++Iter)
|
|
{
|
|
Writer.WriteValue(Iter.Key(), Iter.Value());
|
|
}
|
|
}
|
|
break;
|
|
case ELauncherProfileCookModes::OnTheFly:
|
|
{
|
|
Writer.WriteValue("cookonthefly", true);
|
|
|
|
//if UAT doesn't stick around as long as the process we are going to run, then we can't kill the COTF server when UAT goes down because the program
|
|
//will still need it. If UAT DOES stick around with the process then we DO want the COTF server to die with UAT so the next time we launch we don't end up
|
|
//with two COTF servers.
|
|
if (ClosesAfterLaunch)
|
|
{
|
|
Writer.WriteValue("nokill", true);
|
|
}
|
|
}
|
|
break;
|
|
case ELauncherProfileCookModes::OnTheFlyInEditor:
|
|
Writer.WriteValue("skipcook", true);
|
|
Writer.WriteValue("cookonthefly", true);
|
|
break;
|
|
case ELauncherProfileCookModes::ByTheBookInEditor:
|
|
Writer.WriteValue("skipcook", true);
|
|
break;
|
|
case ELauncherProfileCookModes::DoNotCook:
|
|
Writer.WriteValue("skipcook", true);
|
|
break;
|
|
}
|
|
|
|
Writer.WriteValue("iterativecooking", IsCookingIncrementally());
|
|
Writer.WriteValue("iteratesharedcookedbuild", IsIterateSharedCookedBuild() );
|
|
Writer.WriteValue("skipcookingeditorcontent", GetSkipCookingEditorContent());
|
|
Writer.WriteValue("compressed", IsCompressed());
|
|
Writer.WriteValue("EncryptIniFiles", IsEncryptingIniFiles());
|
|
Writer.WriteValue("ForDistribution", IsForDistribution());
|
|
|
|
// stage/package/deploy
|
|
bool bIsStaging = false;
|
|
if (GetDeploymentMode() != ELauncherProfileDeploymentModes::DoNotDeploy)
|
|
{
|
|
switch (GetDeploymentMode())
|
|
{
|
|
case ELauncherProfileDeploymentModes::CopyRepository:
|
|
{
|
|
Writer.WriteValue("skipstage", true);
|
|
Writer.WriteValue("deploy", true);
|
|
}
|
|
break;
|
|
|
|
case ELauncherProfileDeploymentModes::CopyToDevice:
|
|
{
|
|
Writer.WriteValue("iterativedeploy", IsDeployingIncrementally());
|
|
}
|
|
case ELauncherProfileDeploymentModes::FileServer:
|
|
{
|
|
Writer.WriteValue("stage", true);
|
|
bIsStaging = true;
|
|
Writer.WriteValue("deploy", true);
|
|
}
|
|
break;
|
|
}
|
|
|
|
// run
|
|
if (GetLaunchMode() != ELauncherProfileLaunchModes::DoNotLaunch)
|
|
{
|
|
Writer.WriteValue("run", true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (GetPackagingMode() == ELauncherProfilePackagingModes::Locally)
|
|
{
|
|
Writer.WriteValue("stage", true);
|
|
bIsStaging = true;
|
|
Writer.WriteValue("package", true);
|
|
}
|
|
}
|
|
|
|
if (bIsStaging &&
|
|
GetReferenceContainerGlobalFileName().Len())
|
|
{
|
|
// (only iostore uses this) - pass reference chunk database
|
|
Writer.WriteValue("ReferenceContainerGlobalFileName", GetReferenceContainerGlobalFileName());
|
|
if (GetReferenceContainerCryptoKeysFileName().Len())
|
|
{
|
|
Writer.WriteValue("ReferenceContainerCryptoKeys", GetReferenceContainerCryptoKeysFileName());
|
|
}
|
|
}
|
|
|
|
if (ClientArchitectures.Num() > 0)
|
|
{
|
|
Writer.WriteValue("clientarchitecture", FString::Join(ClientArchitectures, TEXT("+")));
|
|
}
|
|
if (ServerArchitectures.Num() > 0)
|
|
{
|
|
Writer.WriteValue("serverarchitecture", FString::Join(ServerArchitectures, TEXT("+")));
|
|
}
|
|
if (EditorArchitectures.Num() > 0)
|
|
{
|
|
Writer.WriteValue("editorarchitecture", FString::Join(EditorArchitectures, TEXT("+")));
|
|
}
|
|
|
|
/*
|
|
"script", ""
|
|
"project", ""
|
|
"i18npreset", ""
|
|
"cookcultures", ["", "", ""]
|
|
"targetplatform, ["". "", ""]
|
|
"servertargetplatform, ["", "", ""]
|
|
"build", "true/false"
|
|
"run", "true/false"
|
|
"cook, "true/false"
|
|
"cookflavor, ""
|
|
"createreleaseversionroot", ""
|
|
"basedonreleaseversionroot", ""
|
|
"createreleaseversion", ""
|
|
"baseonreleaseversion", ""
|
|
"generatepatch", "true/false"
|
|
"additionalcookeroptions", ["","",""]
|
|
"dlcname", ""
|
|
"diffcookedcontentpath", ""
|
|
"dlcincludeengine", "true/false"
|
|
"skipcook", "true/false"
|
|
"clean", "true/false"
|
|
"signpak", ""
|
|
"signedpak", "true/false"
|
|
"pak", "true/false"
|
|
"skippak", "true/false"
|
|
"noxge", "true/false"
|
|
"cookonthefly", "true/false"
|
|
"cookontheflystreaming", "true/false"
|
|
"unversionedcookcontent", "true/false"
|
|
"skipcookingeditorcontent", "true/false"
|
|
"compressed", "true/false"
|
|
"iterativecooking", "true/false"
|
|
"skipcookonthefly", "true/false"
|
|
"cookall", "true/false"
|
|
"cookmapsonly", "true/false"
|
|
"fileserver", "true/false"
|
|
"dedicatedserver", "true/false"
|
|
"client", "true/false"
|
|
"noclient", "true/false"
|
|
"logwindow", "true/false"
|
|
"stage", "true/false"
|
|
"skipstage", "true/false"
|
|
"stagingdirectory", ""
|
|
"stagenonmonolithic", "true/false"
|
|
"codesign", "true/false"
|
|
"manifests", "true/false"
|
|
"createchunkinstall", "true/false"
|
|
"chunkinstalldirectory", ""
|
|
"chunkinstallversion", ""
|
|
"archive", "true/false"
|
|
"archivedirectory", ""
|
|
"archivemetadata", "true/false"
|
|
"distrbution", "true/false"
|
|
"prereqs", "true/false"
|
|
"nobootstrapexe", "true/false"
|
|
"prebuilt", "true/false"
|
|
"nodebuginfo", "true/false"
|
|
"nocleanstage", "true/false"
|
|
"maptorun", ""
|
|
"additionalservermapparams", ["", "", ""]
|
|
"foreign", "true/false"
|
|
"foreigncode", "true/false"
|
|
"cmdline", ["", "", ""]
|
|
"bundlename", ""
|
|
"addcmdline", ["", "", ""]
|
|
"package", "true/false"
|
|
"deploy", "true/false"
|
|
"iterativedeploy", "true/false"
|
|
"fastcook", "true/false"
|
|
"ignorecookerrors", "true/false"
|
|
"uploadsymbols", "true/false"
|
|
"device", ""
|
|
"serverdevice", ""
|
|
"nullrhi", "true/false"
|
|
"fakeclient", "true/false"
|
|
"editortests", "true/false"
|
|
"runautomationtest", ""
|
|
"runautomationtests", "true/false"
|
|
"skipserver", "true/false"
|
|
"unrealexe", ""
|
|
"unattended", "true/false"
|
|
"deviceuser", ""
|
|
"devicepass", ""
|
|
"crashreporter", "true/false"
|
|
"specifiedarchitecture", ""
|
|
"clientconfig", ["", "", ""]
|
|
"serverconfig", ["", "", ""]
|
|
"port", ["", "", ""]
|
|
"mapstocook", ["", "", ""]
|
|
"numclients", "8"
|
|
"crashindex", "8"
|
|
"runtimeoutseconds", "8"
|
|
*/
|
|
Writer.WriteObjectEnd();
|
|
Writer.WriteArrayEnd();
|
|
}
|
|
|
|
TMap<FString, FString> ParseCommands(FString CommandLine)
|
|
{
|
|
TMap<FString, FString> RoleCommands;
|
|
FString Left;
|
|
FString Right;
|
|
while (CommandLine.Split(TEXT(" "), &Left, &Right))
|
|
{
|
|
if(Left.Len() > 0)
|
|
{
|
|
FString Key;
|
|
FString Value;
|
|
if (!Left.Split(TEXT("="), &Key, &Value))
|
|
{
|
|
Key = Left;
|
|
Value = TEXT("true");
|
|
}
|
|
Key.RemoveFromStart(TEXT("-"));
|
|
RoleCommands.Add(Key, Value);
|
|
}
|
|
CommandLine = Right;
|
|
}
|
|
if (CommandLine.Len() > 0)
|
|
{
|
|
if (!CommandLine.Split(TEXT("="), &Left, &Right))
|
|
{
|
|
Right = TEXT("true");
|
|
}
|
|
Left.RemoveFromStart(TEXT("-"));
|
|
RoleCommands.Add(Left, Right);
|
|
}
|
|
|
|
return RoleCommands;
|
|
}
|
|
|
|
TArray<FString> FindPlatforms()
|
|
{
|
|
TArray<FString> Platforms;
|
|
if (GetCookMode() == ELauncherProfileCookModes::ByTheBook)
|
|
{
|
|
Platforms = GetCookedPlatforms();
|
|
}
|
|
|
|
// determine deployment platforms
|
|
ILauncherDeviceGroupPtr DeviceGroup = GetDeployedDeviceGroup();
|
|
FName Variant = NAME_None;
|
|
|
|
// Loading the Device Proxy Manager to get the needed Device Manager.
|
|
ITargetDeviceServicesModule& DeviceServiceModule = FModuleManager::LoadModuleChecked<ITargetDeviceServicesModule>(TEXT("TargetDeviceServices"));
|
|
TSharedRef<ITargetDeviceProxyManager> DeviceProxyManager = DeviceServiceModule.GetDeviceProxyManager();
|
|
|
|
if (DeviceGroup.IsValid() && Platforms.Num() < 1)
|
|
{
|
|
const TArray<FString>& Devices = DeviceGroup->GetDeviceIDs();
|
|
// for each deployed device...
|
|
for (int32 DeviceIndex = 0; DeviceIndex < Devices.Num(); ++DeviceIndex)
|
|
{
|
|
const FString& DeviceId = Devices[DeviceIndex];
|
|
|
|
TSharedPtr<ITargetDeviceProxy> DeviceProxy = DeviceProxyManager->FindProxyDeviceForTargetDevice(DeviceId);
|
|
|
|
if (DeviceProxy.IsValid())
|
|
{
|
|
// add the platform
|
|
Variant = DeviceProxy->GetTargetDeviceVariant(DeviceId);
|
|
Platforms.AddUnique(DeviceProxy->GetTargetPlatformName(Variant));
|
|
}
|
|
}
|
|
}
|
|
|
|
return Platforms;
|
|
}
|
|
|
|
bool FindAllPlatforms(TArray<FString>& ServerPlatforms, TArray<FString>& ClientPlatforms, FString& OptionalParams)
|
|
{
|
|
bool bUATClosesAfterLaunch = false;
|
|
TArray<FString> InPlatforms = FindPlatforms();
|
|
for (int32 PlatformIndex = 0; PlatformIndex < InPlatforms.Num(); ++PlatformIndex)
|
|
{
|
|
// Platform info for the given platform
|
|
const PlatformInfo::FTargetPlatformInfo* PlatformInfo = PlatformInfo::FindPlatformInfo(FName(*InPlatforms[PlatformIndex]));
|
|
if (PlatformInfo == nullptr)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// add the UBT platform name to the appropriate list
|
|
TArray<FString>& Platforms = PlatformInfo->PlatformType == EBuildTargetType::Server ? ServerPlatforms : ClientPlatforms;
|
|
Platforms.Add(PlatformInfo->DataDrivenPlatformInfo->UBTPlatformName.ToString());
|
|
|
|
// Append any extra UAT flags specified for this platform flavor
|
|
if (!PlatformInfo->UATCommandLine.IsEmpty())
|
|
{
|
|
OptionalParams += PlatformInfo->UATCommandLine;
|
|
}
|
|
|
|
bUATClosesAfterLaunch |= PlatformInfo->DataDrivenPlatformInfo->bUATClosesAfterLaunch;
|
|
}
|
|
|
|
// If both Client and Server are desired to be built avoid Server causing clients to not be built PlatformInfo wise
|
|
if (OptionalParams.Contains(TEXT("-client")) && OptionalParams.Contains(TEXT("-noclient")))
|
|
{
|
|
OptionalParams = OptionalParams.Replace(TEXT("-noclient"), TEXT(""));
|
|
}
|
|
|
|
return bUATClosesAfterLaunch;
|
|
}
|
|
|
|
virtual bool Load(const FJsonObject& Object) override
|
|
{
|
|
int32 Version = (int32)Object.GetNumberField(TEXT("Version"));
|
|
if (Version < LAUNCHERSERVICES_FILEFORMATCHANGE || Version > LAUNCHERSERVICES_FINAL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool CookIncremental;
|
|
|
|
FGuid::Parse(Object.GetStringField(TEXT("Id")), Id);
|
|
Name = Object.GetStringField(TEXT("Name"));
|
|
Description = Object.GetStringField(TEXT("Description"));
|
|
BuildConfiguration = (EBuildConfiguration)((int32)Object.GetNumberField(TEXT("BuildConfiguration")));
|
|
ProjectSpecified = Object.GetBoolField(TEXT("ProjectSpecified"));
|
|
ShareableProjectPath = Object.GetStringField(TEXT("ShareableProjectPath"));
|
|
CookConfiguration = (EBuildConfiguration)((int32)Object.GetNumberField(TEXT("CookConfiguration")));
|
|
CookIncremental = Object.GetBoolField(TEXT("CookIncremental"));
|
|
CookOptions = Object.GetStringField(TEXT("CookOptions"));
|
|
CookMode = (TEnumAsByte<ELauncherProfileCookModes::Type>)((int32)Object.GetNumberField(TEXT("CookMode")));
|
|
CookUnversioned = Object.GetBoolField(TEXT("CookUnversioned"));
|
|
|
|
CookedCultures.Reset();
|
|
const TArray<TSharedPtr<FJsonValue>>* Cultures = NULL;
|
|
if (Object.TryGetArrayField(TEXT("CookedCultures"), Cultures))
|
|
{
|
|
for (auto Value : *Cultures)
|
|
{
|
|
CookedCultures.Add(Value->AsString());
|
|
}
|
|
}
|
|
|
|
CookedMaps.Reset();
|
|
const TArray<TSharedPtr<FJsonValue>>* Maps = NULL;
|
|
if (Object.TryGetArrayField(TEXT("CookedMaps"), Maps))
|
|
{
|
|
for (auto Value : *Maps)
|
|
{
|
|
CookedMaps.Add(Value->AsString());
|
|
}
|
|
}
|
|
|
|
CookedPlatforms.Reset();
|
|
const TArray<TSharedPtr<FJsonValue>>* Platforms = NULL;
|
|
if (Object.TryGetArrayField(TEXT("CookedPlatforms"), Platforms))
|
|
{
|
|
for (auto Value : *Platforms)
|
|
{
|
|
CookedPlatforms.Add(Value->AsString());
|
|
}
|
|
}
|
|
|
|
DeployStreamingServer = Object.GetBoolField(TEXT("DeployStreamingServer"));
|
|
DeployWithUnrealPak = Object.GetBoolField(TEXT("DeployWithUnrealPak"));
|
|
FGuid::Parse(Object.GetStringField(TEXT("DeployedDeviceGroupId")), DeployedDeviceGroupId);
|
|
DeploymentMode = (TEnumAsByte<ELauncherProfileDeploymentModes::Type>)((int32)Object.GetNumberField(TEXT("DeploymentMode")));
|
|
HideFileServerWindow = Object.GetBoolField(TEXT("HideFileServerWindow"));
|
|
LaunchMode = (TEnumAsByte<ELauncherProfileLaunchModes::Type>)((int32)Object.GetNumberField(TEXT("LaunchMode")));
|
|
PackagingMode = (TEnumAsByte<ELauncherProfilePackagingModes::Type>)((int32)Object.GetNumberField(TEXT("PackagingMode")));
|
|
PackageDir = Object.GetStringField(TEXT("PackageDir"));
|
|
|
|
int64 BuildModeValue;
|
|
if (Object.TryGetNumberField(TEXT("BuildMode"), BuildModeValue))
|
|
{
|
|
BuildMode = (TEnumAsByte<ELauncherProfileBuildModes::Type>)(int32)BuildModeValue;
|
|
}
|
|
else
|
|
{
|
|
BuildMode = Object.GetBoolField(TEXT("BuildGame")) ? ELauncherProfileBuildModes::Build : ELauncherProfileBuildModes::DoNotBuild;
|
|
}
|
|
|
|
ForceClose = Object.GetBoolField(TEXT("ForceClose"));
|
|
Timeout = (uint32)Object.GetNumberField(TEXT("Timeout"));
|
|
Compressed = Object.GetBoolField(TEXT("Compressed"));
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDEDENCRYPTINIFILES)
|
|
{
|
|
EncryptIniFiles = Object.GetBoolField(TEXT("EncryptIniFiles"));
|
|
ForDistribution = Object.GetBoolField(TEXT("ForDistribution"));
|
|
}
|
|
else
|
|
{
|
|
EncryptIniFiles = false;
|
|
ForDistribution = false;
|
|
}
|
|
|
|
DefaultDeployPlatform = *(Object.GetStringField(TEXT("DeployPlatform")));
|
|
bSkipCookingEditorContent = Object.GetBoolField(TEXT("SkipCookingEditorContent"));
|
|
DeployIncremental = Object.GetBoolField(TEXT("DeployIncremental"));
|
|
GeneratePatch = Object.GetBoolField(TEXT("GeneratePatch"));
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDEDMULTILEVELPATCHING)
|
|
{
|
|
AddPatchLevel = Object.GetBoolField(TEXT("AddPatchLevel"));
|
|
StageBaseReleasePaks = Object.GetBoolField(TEXT("StageBaseReleasePaks"));
|
|
}
|
|
else
|
|
{
|
|
AddPatchLevel = false;
|
|
StageBaseReleasePaks = false;
|
|
}
|
|
|
|
DLCIncludeEngineContent = Object.GetBoolField(TEXT("DLCIncludeEngineContent"));
|
|
CreateReleaseVersion = Object.GetBoolField(TEXT("CreateReleaseVersion"));
|
|
CreateReleaseVersionName = Object.GetStringField(TEXT("CreateReleaseVersionName"));
|
|
BasedOnReleaseVersionName = Object.GetStringField(TEXT("BasedOnReleaseVersionName"));
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDEDREFERENCECONTAINERS)
|
|
{
|
|
ReferenceContainerCryptoKeysFileName = Object.GetStringField(TEXT("ReferenceContainerCryptoKeysFileName"));
|
|
ReferenceContainerGlobalFileName = Object.GetStringField(TEXT("ReferenceContainerGlobalFileName"));
|
|
}
|
|
else
|
|
{
|
|
ReferenceContainerCryptoKeysFileName.Empty();
|
|
ReferenceContainerGlobalFileName.Empty();
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDEDORIGINALRELEASEVERSION)
|
|
{
|
|
OriginalReleaseVersionName = Object.GetStringField(TEXT("OriginalReleaseVersionName"));
|
|
}
|
|
else
|
|
{
|
|
OriginalReleaseVersionName.Empty();
|
|
}
|
|
|
|
CreateDLC = Object.GetBoolField(TEXT("CreateDLC"));
|
|
DLCName = Object.GetStringField(TEXT("DLCName"));
|
|
bGenerateChunks = Object.GetBoolField(TEXT("GenerateChunks"));
|
|
bGenerateHttpChunkData = Object.GetBoolField(TEXT("GenerateHttpChunkData"));
|
|
HttpChunkDataDirectory = Object.GetStringField(TEXT("HttpChunkDataDirectory"));
|
|
HttpChunkDataReleaseName = Object.GetStringField(TEXT("HttpChunkDataReleaseName"));
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDARCHIVE)
|
|
{
|
|
bArchive = Object.GetBoolField(TEXT("Archive"));
|
|
ArchiveDir = Object.GetStringField(TEXT("ArchiveDirectory"));
|
|
}
|
|
else
|
|
{
|
|
bArchive = false;
|
|
ArchiveDir = TEXT("");
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDEDADDITIONALCOMMANDLINE)
|
|
{
|
|
AdditionalCommandLineParameters = Object.GetStringField(TEXT("AdditionalCommandLineParameters"));
|
|
}
|
|
else
|
|
{
|
|
AdditionalCommandLineParameters = TEXT("");
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDEDINCLUDEPREREQUISITES)
|
|
{
|
|
IncludePrerequisites = Object.GetBoolField(TEXT("IncludePrerequisites"));
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDEDUSEIOSTORE)
|
|
{
|
|
bUseIoStore = Object.GetBoolField(TEXT("UseIoStore"));
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDEDMAKEBINARYCONFIG)
|
|
{
|
|
bMakeBinaryConfig = Object.GetBoolField(TEXT("MakeBinaryConfig"));
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDBUILDTARGETNAME)
|
|
{
|
|
BuildTargetSpecified = Object.GetBoolField(TEXT("BuildTargetSpecified"));
|
|
BuildTargetName = Object.GetStringField(TEXT("BuildTargetName"));
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDZENOPTIONS)
|
|
{
|
|
bUseZenStore = Object.GetBoolField(TEXT("UseZenStore"));
|
|
bImportingZenSnapshot = Object.GetBoolField(TEXT("ImportingZenSnapshot"));
|
|
bUseZenPakStreaming = Object.GetBoolField(TEXT("UseZenPakStreaming"));
|
|
ZenPakStreamingPath = Object.GetStringField(TEXT("ZenPakStreamingPath"));
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDBUILDARCHITECTURE)
|
|
{
|
|
ClientArchitectures.Reset();
|
|
ServerArchitectures.Reset();
|
|
EditorArchitectures.Reset();
|
|
Object.TryGetStringArrayField(TEXT("ClientArchitectures"), ClientArchitectures);
|
|
Object.TryGetStringArrayField(TEXT("ServerArchitectures"), ServerArchitectures);
|
|
Object.TryGetStringArrayField(TEXT("EditorArchitectures"), EditorArchitectures);
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_ADDCUSTOMPROPERTIES)
|
|
{
|
|
const TSharedPtr<FJsonObject>* CustomPropertiesObject;
|
|
|
|
CustomStringProperties.Reset();
|
|
if (Object.TryGetObjectField(TEXT("CustomStringProperties"), CustomPropertiesObject))
|
|
{
|
|
for (const auto& KeyPairs : (*CustomPropertiesObject)->Values)
|
|
{
|
|
CustomStringProperties.Add(KeyPairs.Key, KeyPairs.Value->AsString());
|
|
}
|
|
}
|
|
|
|
CustomBoolProperties.Reset();
|
|
if (Object.TryGetObjectField(TEXT("CustomBoolProperties"), CustomPropertiesObject))
|
|
{
|
|
for (const auto& KeyPairs : (*CustomPropertiesObject)->Values)
|
|
{
|
|
CustomBoolProperties.Add(KeyPairs.Key, KeyPairs.Value->AsBool());
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Version >= LAUNCHERSERVICES_INCREMENTALCOOKMODE)
|
|
{
|
|
IncrementalCookMode = (TEnumAsByte<ELauncherProfileIncrementalCookMode::Type>)((int32)Object.GetNumberField(TEXT("IncrementalCookMode")));
|
|
}
|
|
else
|
|
{
|
|
IncrementalCookMode = CookIncremental ? ELauncherProfileIncrementalCookMode::ModifiedOnly : ELauncherProfileIncrementalCookMode::None;
|
|
}
|
|
|
|
|
|
// load the default launch role
|
|
TSharedPtr<FJsonObject> Role = Object.GetObjectField(TEXT("DefaultRole"));
|
|
DefaultLaunchRole->Load(*(Role.Get()));
|
|
|
|
// serialize the launch roles
|
|
DeployedDeviceGroup.Reset();
|
|
LaunchRoles.Reset();
|
|
const TArray<TSharedPtr<FJsonValue>>* Roles = NULL;
|
|
if (Object.TryGetArrayField(TEXT("LaunchRoles"), Roles))
|
|
{
|
|
for (auto Value : *Roles)
|
|
{
|
|
LaunchRoles.Add(MakeShareable(new FLauncherProfileLaunchRole(*(Value->AsObject().Get()))));
|
|
}
|
|
}
|
|
|
|
// if (Version >= LAUNCHERSERVICES_SHAREABLEPROJECTPATHS) Always true due to early out at top of function
|
|
{
|
|
FullProjectPath = FPaths::ConvertRelativePathToFull(FPaths::RootDir(), ShareableProjectPath);
|
|
}
|
|
|
|
if (DefaultDeployPlatform != NAME_None)
|
|
{
|
|
SetDefaultDeployPlatform(DefaultDeployPlatform);
|
|
}
|
|
|
|
RefreshValidBuildTargets();
|
|
Validate();
|
|
|
|
return true;
|
|
}
|
|
|
|
virtual void SetDefaults( ) override
|
|
{
|
|
ProjectSpecified = false;
|
|
AdditionalCommandLineParameters = FString();
|
|
|
|
// default project settings
|
|
if (FPaths::IsProjectFilePathSet())
|
|
{
|
|
FullProjectPath = FPaths::GetProjectFilePath();
|
|
}
|
|
else if (FGameProjectHelper::IsGameAvailable(FApp::GetProjectName()))
|
|
{
|
|
FullProjectPath = FPaths::RootDir() / FApp::GetProjectName() / FApp::GetProjectName() + TEXT(".uproject");
|
|
}
|
|
else
|
|
{
|
|
FullProjectPath = FString();
|
|
}
|
|
|
|
FString RelativeProjectPath = FullProjectPath;
|
|
bool bRelative = FPaths::MakePathRelativeTo(RelativeProjectPath, *FPaths::RootDir());
|
|
|
|
bool bIsUnderUERoot = bRelative && !(RelativeProjectPath.StartsWith(FString("../"), ESearchCase::CaseSensitive));
|
|
if (bIsUnderUERoot)
|
|
{
|
|
ShareableProjectPath = RelativeProjectPath;
|
|
}
|
|
else
|
|
{
|
|
ShareableProjectPath = FullProjectPath;
|
|
}
|
|
|
|
// Use the locally specified project path is resolving through the root isn't working
|
|
ProjectSpecified = !FullProjectPath.IsEmpty();
|
|
|
|
// I don't use FApp::GetBuildConfiguration() because i don't want the act of running in debug the first time to cause
|
|
// profiles the user creates to be in debug. This will keep consistency.
|
|
BuildConfiguration = EBuildConfiguration::Development;
|
|
|
|
FInternationalization& I18N = FInternationalization::Get();
|
|
|
|
// default build settings
|
|
BuildMode = ELauncherProfileBuildModes::Auto;
|
|
BuildUAT = !FApp::GetEngineIsPromotedBuild() && !FApp::IsEngineInstalled();
|
|
BuildTargetSpecified = false;
|
|
|
|
// default cook settings
|
|
CookConfiguration = FApp::GetBuildConfiguration();
|
|
CookMode = ELauncherProfileCookModes::OnTheFly;
|
|
CookOptions = FString();
|
|
IncrementalCookMode = ELauncherProfileIncrementalCookMode::None;
|
|
IterateSharedCookedBuild=false;
|
|
CookUnversioned = true;
|
|
Compressed = true;
|
|
EncryptIniFiles = false;
|
|
ForDistribution = false;
|
|
CookedCultures.Reset();
|
|
CookedCultures.Add(I18N.GetCurrentCulture()->GetName());
|
|
CookedMaps.Reset();
|
|
CookedPlatforms.Reset();
|
|
bSkipCookingEditorContent = false;
|
|
ForceClose = true;
|
|
Timeout = 60;
|
|
|
|
/* if (GetTargetPlatformManager()->GetRunningTargetPlatform() != NULL)
|
|
{
|
|
CookedPlatforms.Add(GetTargetPlatformManager()->GetRunningTargetPlatform()->PlatformName());
|
|
}*/
|
|
|
|
bArchive = false;
|
|
ArchiveDir = TEXT("");
|
|
|
|
// default deploy settings
|
|
DeployedDeviceGroup.Reset();
|
|
DeploymentMode = ELauncherProfileDeploymentModes::CopyToDevice;
|
|
DeployStreamingServer = false;
|
|
IncludePrerequisites = false;
|
|
DeployWithUnrealPak = false;
|
|
DeployedDeviceGroupId = FGuid();
|
|
HideFileServerWindow = false;
|
|
DeployIncremental = false;
|
|
|
|
CreateReleaseVersion = false;
|
|
GeneratePatch = false;
|
|
AddPatchLevel = false;
|
|
StageBaseReleasePaks = false;
|
|
CreateDLC = false;
|
|
DLCIncludeEngineContent = false;
|
|
|
|
bGenerateChunks = false;
|
|
bGenerateHttpChunkData = false;
|
|
HttpChunkDataDirectory = TEXT("");
|
|
HttpChunkDataReleaseName = TEXT("");
|
|
|
|
// default launch settings
|
|
DefaultDeployPlatform = NAME_None;
|
|
LaunchMode = ELauncherProfileLaunchModes::DefaultRole;
|
|
DefaultLaunchRole->SetCommandLine(FString());
|
|
DefaultLaunchRole->SetInitialCulture(I18N.GetCurrentCulture()->GetName());
|
|
DefaultLaunchRole->SetInitialMap(FString());
|
|
DefaultLaunchRole->SetName(TEXT("Default Role"));
|
|
DefaultLaunchRole->SetInstanceType(ELauncherProfileRoleInstanceTypes::StandaloneClient);
|
|
DefaultLaunchRole->SetVsyncEnabled(false);
|
|
LaunchRoles.Reset();
|
|
|
|
// default packaging settings
|
|
PackagingMode = ELauncherProfilePackagingModes::DoNotPackage;
|
|
|
|
// default UAT settings
|
|
ILauncherServicesModule& LauncherServicesModule = FModuleManager::GetModuleChecked<ILauncherServicesModule>(TEXT("LauncherServices"));
|
|
EditorExe = LauncherServicesModule.GetExecutableForCommandlets();
|
|
|
|
bNotForLicensees = false;
|
|
bUseIoStore = false;
|
|
bUseZenStore = false;
|
|
bImportingZenSnapshot = false;
|
|
bUseZenPakStreaming = false;
|
|
bShouldUpdateFlash = false;
|
|
bIsDeviceASimulator = false;
|
|
bMakeBinaryConfig = false;
|
|
|
|
RefreshValidBuildTargets();
|
|
Validate();
|
|
}
|
|
|
|
virtual void SetBuildMode(ELauncherProfileBuildModes::Type Mode) override
|
|
{
|
|
if (BuildMode != Mode)
|
|
{
|
|
BuildMode = Mode;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetBuildUAT(bool Build) override
|
|
{
|
|
if (BuildUAT != Build)
|
|
{
|
|
BuildUAT = Build;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetAdditionalCommandLineParameters(const FString& Params) override
|
|
{
|
|
if (AdditionalCommandLineParameters != Params)
|
|
{
|
|
AdditionalCommandLineParameters = Params;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetBuildConfiguration( EBuildConfiguration Configuration ) override
|
|
{
|
|
if (BuildConfiguration != Configuration)
|
|
{
|
|
BuildConfiguration = Configuration;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetBuildTargetSpecified(bool Specified) override
|
|
{
|
|
if (BuildTargetSpecified != Specified)
|
|
{
|
|
BuildTargetSpecified = Specified;
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void FallbackBuildTargetUpdated() override
|
|
{
|
|
if (!HasBuildTargetSpecified())
|
|
{
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
|
|
virtual void SetBuildTarget( const FString& TargetName ) override
|
|
{
|
|
if (BuildTargetName != TargetName)
|
|
{
|
|
BuildTargetName = TargetName;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetCookConfiguration( EBuildConfiguration Configuration ) override
|
|
{
|
|
if (CookConfiguration != Configuration)
|
|
{
|
|
CookConfiguration = Configuration;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetCookMode( ELauncherProfileCookModes::Type Mode ) override
|
|
{
|
|
if (CookMode != Mode)
|
|
{
|
|
CookMode = Mode;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetCookOptions(const FString& Options) override
|
|
{
|
|
if (CookOptions != Options)
|
|
{
|
|
CookOptions = Options;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetSkipCookingEditorContent(const bool InSkipCookingEditorContent) override
|
|
{
|
|
if (bSkipCookingEditorContent != InSkipCookingEditorContent)
|
|
{
|
|
bSkipCookingEditorContent = InSkipCookingEditorContent;
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetDeployWithUnrealPak( bool UseUnrealPak ) override
|
|
{
|
|
if (DeployWithUnrealPak != UseUnrealPak)
|
|
{
|
|
DeployWithUnrealPak = UseUnrealPak;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetGenerateChunks(bool bInGenerateChunks) override
|
|
{
|
|
if (bGenerateChunks != bInGenerateChunks)
|
|
{
|
|
bGenerateChunks = bInGenerateChunks;
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetGenerateHttpChunkData(bool bInGenerateHttpChunkData) override
|
|
{
|
|
if (bGenerateHttpChunkData != bInGenerateHttpChunkData)
|
|
{
|
|
bGenerateHttpChunkData = bInGenerateHttpChunkData;
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetHttpChunkDataDirectory(const FString& InHttpChunkDataDirectory) override
|
|
{
|
|
if (HttpChunkDataDirectory != InHttpChunkDataDirectory)
|
|
{
|
|
HttpChunkDataDirectory = InHttpChunkDataDirectory;
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetHttpChunkDataReleaseName(const FString& InHttpChunkDataReleaseName) override
|
|
{
|
|
if (HttpChunkDataReleaseName != InHttpChunkDataReleaseName)
|
|
{
|
|
HttpChunkDataReleaseName = InHttpChunkDataReleaseName;
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetDeployedDeviceGroup( const ILauncherDeviceGroupPtr& DeviceGroup ) override
|
|
{
|
|
if(DeployedDeviceGroup.IsValid())
|
|
{
|
|
DeployedDeviceGroup->OnDeviceAdded().Remove(OnLauncherDeviceGroupDeviceAddedDelegateHandle);
|
|
DeployedDeviceGroup->OnDeviceRemoved().Remove(OnLauncherDeviceGroupDeviceRemoveDelegateHandle);
|
|
}
|
|
DeployedDeviceGroup = DeviceGroup;
|
|
if (DeployedDeviceGroup.IsValid())
|
|
{
|
|
OnLauncherDeviceGroupDeviceAddedDelegateHandle = DeployedDeviceGroup->OnDeviceAdded().AddRaw(this, &FLauncherProfile::OnLauncherDeviceGroupDeviceAdded);
|
|
OnLauncherDeviceGroupDeviceRemoveDelegateHandle = DeployedDeviceGroup->OnDeviceRemoved().AddRaw(this, &FLauncherProfile::OnLauncherDeviceGroupDeviceRemove);
|
|
DeployedDeviceGroupId = DeployedDeviceGroup->GetId();
|
|
}
|
|
else
|
|
{
|
|
DeployedDeviceGroupId = FGuid();
|
|
}
|
|
|
|
if (DefaultDeployPlatform != NAME_None)
|
|
{
|
|
SetDefaultDeployPlatform(DefaultDeployPlatform);
|
|
}
|
|
|
|
Validate();
|
|
}
|
|
|
|
virtual FIsCookFinishedDelegate& OnIsCookFinished() override
|
|
{
|
|
return IsCookFinishedDelegate;
|
|
}
|
|
|
|
virtual FCookCanceledDelegate& OnCookCanceled() override
|
|
{
|
|
return CookCanceledDelegate;
|
|
}
|
|
|
|
virtual void SetDeploymentMode( ELauncherProfileDeploymentModes::Type Mode ) override
|
|
{
|
|
if (DeploymentMode != Mode)
|
|
{
|
|
DeploymentMode = Mode;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetForceClose( bool Close ) override
|
|
{
|
|
if (ForceClose != Close)
|
|
{
|
|
ForceClose = Close;
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetHideFileServerWindow( bool Hide ) override
|
|
{
|
|
HideFileServerWindow = Hide;
|
|
}
|
|
|
|
virtual void SetIncrementalCooking( bool Incremental ) override
|
|
{
|
|
SetIncrementalCookMode( Incremental ? ELauncherProfileIncrementalCookMode::ModifiedOnly : ELauncherProfileIncrementalCookMode::None );
|
|
}
|
|
|
|
virtual void SetIncrementalCookMode( ELauncherProfileIncrementalCookMode::Type Mode ) override
|
|
{
|
|
if (IncrementalCookMode != Mode)
|
|
{
|
|
IncrementalCookMode = Mode;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
|
|
virtual void SetIterateSharedCookedBuild( bool SharedCookedBuild ) override
|
|
{
|
|
if (IterateSharedCookedBuild != SharedCookedBuild)
|
|
{
|
|
IterateSharedCookedBuild = SharedCookedBuild;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetCompressed( bool Enabled ) override
|
|
{
|
|
if (Compressed != Enabled)
|
|
{
|
|
Compressed = Enabled;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetForDistribution(bool Enabled)override
|
|
{
|
|
if (ForDistribution != Enabled)
|
|
{
|
|
ForDistribution = Enabled;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetEncryptingIniFiles(bool Enabled) override
|
|
{
|
|
if (EncryptIniFiles != Enabled)
|
|
{
|
|
EncryptIniFiles = Enabled;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetIncrementalDeploying( bool Incremental ) override
|
|
{
|
|
if (DeployIncremental != Incremental)
|
|
{
|
|
DeployIncremental = Incremental;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetLaunchMode( ELauncherProfileLaunchModes::Type Mode ) override
|
|
{
|
|
if (LaunchMode != Mode)
|
|
{
|
|
LaunchMode = Mode;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetName( const FString& NewName ) override
|
|
{
|
|
if (Name != NewName)
|
|
{
|
|
Name = NewName;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetDescription(const FString& NewDescription) override
|
|
{
|
|
if (Description != NewDescription)
|
|
{
|
|
Description = NewDescription;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetNotForLicensees() override
|
|
{
|
|
bNotForLicensees = true;
|
|
}
|
|
|
|
virtual void SetPackagingMode( ELauncherProfilePackagingModes::Type Mode ) override
|
|
{
|
|
if (PackagingMode != Mode)
|
|
{
|
|
PackagingMode = Mode;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetPackageDirectory( const FString& Dir ) override
|
|
{
|
|
if (PackageDir != Dir)
|
|
{
|
|
PackageDir = Dir;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetArchive( bool bInArchive ) override
|
|
{
|
|
if (bInArchive != bArchive)
|
|
{
|
|
bArchive = bInArchive;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetArchiveDirectory( const FString& Dir ) override
|
|
{
|
|
if (ArchiveDir != Dir)
|
|
{
|
|
ArchiveDir = Dir;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetProjectSpecified(bool Specified) override
|
|
{
|
|
if (ProjectSpecified != Specified)
|
|
{
|
|
ProjectSpecified = Specified;
|
|
|
|
RefreshValidBuildTargets();
|
|
Validate();
|
|
|
|
ProjectChangedDelegate.Broadcast();
|
|
}
|
|
}
|
|
|
|
virtual void FallbackProjectUpdated() override
|
|
{
|
|
if (!HasProjectSpecified())
|
|
{
|
|
RefreshValidBuildTargets();
|
|
Validate();
|
|
|
|
ProjectChangedDelegate.Broadcast();
|
|
}
|
|
}
|
|
|
|
virtual void SetProjectPath( const FString& Path ) override
|
|
{
|
|
if (FullProjectPath != Path)
|
|
{
|
|
if(Path.IsEmpty())
|
|
{
|
|
FullProjectPath = Path;
|
|
}
|
|
else
|
|
{
|
|
FullProjectPath = FPaths::ConvertRelativePathToFull(Path);
|
|
|
|
FString RelativeProjectPath = Path;
|
|
bool bRelative = FPaths::MakePathRelativeTo(RelativeProjectPath, *FPaths::RootDir());
|
|
|
|
bool bIsUnderUERoot = bRelative && !(RelativeProjectPath.StartsWith(FString("../"), ESearchCase::CaseSensitive));
|
|
if (bIsUnderUERoot)
|
|
{
|
|
ShareableProjectPath = RelativeProjectPath;
|
|
}
|
|
else
|
|
{
|
|
ShareableProjectPath = FullProjectPath;
|
|
}
|
|
}
|
|
CookedMaps.Reset();
|
|
|
|
RefreshValidBuildTargets();
|
|
Validate();
|
|
|
|
ProjectChangedDelegate.Broadcast();
|
|
}
|
|
}
|
|
|
|
virtual void SetStreamingFileServer( bool Streaming ) override
|
|
{
|
|
if (DeployStreamingServer != Streaming)
|
|
{
|
|
DeployStreamingServer = Streaming;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetIncludePrerequisites(bool InValue) override
|
|
{
|
|
if (IncludePrerequisites != InValue)
|
|
{
|
|
IncludePrerequisites = InValue;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetTimeout( uint32 InTime ) override
|
|
{
|
|
if (Timeout != InTime)
|
|
{
|
|
Timeout = InTime;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetUnversionedCooking( bool Unversioned ) override
|
|
{
|
|
if (CookUnversioned != Unversioned)
|
|
{
|
|
CookUnversioned = Unversioned;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual void SetGeneratePatch( bool InGeneratePatch ) override
|
|
{
|
|
GeneratePatch = InGeneratePatch;
|
|
}
|
|
|
|
virtual void SetAddPatchLevel( bool InAddPatchLevel) override
|
|
{
|
|
AddPatchLevel = InAddPatchLevel;
|
|
}
|
|
|
|
virtual void SetStageBaseReleasePaks(bool InStageBaseReleasePaks) override
|
|
{
|
|
StageBaseReleasePaks = InStageBaseReleasePaks;
|
|
}
|
|
|
|
virtual bool SupportsEngineMaps( ) const override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
virtual FOnProfileProjectChanged& OnProjectChanged() override
|
|
{
|
|
return ProjectChangedDelegate;
|
|
}
|
|
|
|
virtual FOnProfileBuildTargetOptionsChanged& OnBuildTargetOptionsChanged() override
|
|
{
|
|
return BuildTargetOptionsChangedDelegate;
|
|
}
|
|
|
|
virtual void SetEditorExe( const FString& InEditorExe ) override
|
|
{
|
|
EditorExe = InEditorExe;
|
|
}
|
|
|
|
virtual FString GetEditorExe( ) const override
|
|
{
|
|
return EditorExe;
|
|
}
|
|
|
|
virtual void SetUseIoStore(bool bInUseIoStore) override
|
|
{
|
|
bUseIoStore = bInUseIoStore;
|
|
|
|
if (bUseIoStore)
|
|
{
|
|
SetDeployWithUnrealPak(true);
|
|
}
|
|
|
|
Validate();
|
|
}
|
|
|
|
virtual bool IsUsingIoStore() const override
|
|
{
|
|
return bUseIoStore;
|
|
}
|
|
|
|
virtual void SetUseZenStore(bool bInUseZenStore) override
|
|
{
|
|
bUseZenStore = bInUseZenStore;
|
|
|
|
Validate();
|
|
}
|
|
|
|
virtual bool IsUsingZenStore() const override
|
|
{
|
|
return bUseZenStore;
|
|
}
|
|
|
|
virtual void SetImportingZenSnapshot( bool Import ) override
|
|
{
|
|
if (bImportingZenSnapshot != Import)
|
|
{
|
|
bImportingZenSnapshot = Import;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual bool IsImportingZenSnapshot() const override
|
|
{
|
|
return bImportingZenSnapshot;
|
|
}
|
|
|
|
virtual void SetUseZenPakStreaming( bool UseZenPakStreaming ) override
|
|
{
|
|
if (bUseZenPakStreaming != UseZenPakStreaming)
|
|
{
|
|
bUseZenPakStreaming = UseZenPakStreaming;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual bool IsUsingZenPakStreaming() const override
|
|
{
|
|
if (CookMode == ELauncherProfileCookModes::DoNotCook)
|
|
{
|
|
return bUseZenPakStreaming;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
virtual void SetZenPakStreamingPath( const FString& Path ) override
|
|
{
|
|
if (ZenPakStreamingPath != Path)
|
|
{
|
|
ZenPakStreamingPath = Path;
|
|
|
|
Validate();
|
|
}
|
|
}
|
|
|
|
virtual FString GetZenPakStreamingPath() const override
|
|
{
|
|
return ZenPakStreamingPath;
|
|
}
|
|
|
|
virtual void SetShouldUpdateDeviceFlash(bool bInShouldUpdateFlash) override
|
|
{
|
|
bShouldUpdateFlash = bInShouldUpdateFlash;
|
|
}
|
|
|
|
/**
|
|
* Whether or not the flash image/software on the device should attempt to be updated before running
|
|
*/
|
|
virtual bool ShouldUpdateDeviceFlash() const override
|
|
{
|
|
return bShouldUpdateFlash;
|
|
}
|
|
|
|
virtual void SetDeviceIsASimulator(bool bInIsDeviceASimualtor) override
|
|
{
|
|
bIsDeviceASimulator = bInIsDeviceASimualtor;
|
|
}
|
|
|
|
/**
|
|
* Is the Launch device actually a simulator?
|
|
*/
|
|
virtual bool IsDeviceASimulator() const override
|
|
{
|
|
return bIsDeviceASimulator;
|
|
}
|
|
|
|
virtual void SetMakeBinaryConfig(bool bInMakeBinaryConfig) override
|
|
{
|
|
bMakeBinaryConfig = bInMakeBinaryConfig;
|
|
}
|
|
|
|
virtual bool MakeBinaryConfig() const override
|
|
{
|
|
return bMakeBinaryConfig;
|
|
}
|
|
|
|
virtual TArray<FString> GetExplicitBuildTargetNames() const override
|
|
{
|
|
return ExplictBuildTargetNames;
|
|
}
|
|
|
|
virtual bool RequiresExplicitBuildTargetName() const override
|
|
{
|
|
return ExplictBuildTargetNames.Num() > 0;
|
|
}
|
|
|
|
virtual void SetClientArchitectures( const TArray<FString>& InArchitectures )
|
|
{
|
|
ClientArchitectures = InArchitectures;
|
|
}
|
|
|
|
virtual const TArray<FString>& GetClientArchitectures() const override
|
|
{
|
|
return ClientArchitectures;
|
|
}
|
|
|
|
virtual void SetServerArchitectures( const TArray<FString>& InArchitectures )
|
|
{
|
|
ServerArchitectures = InArchitectures;
|
|
}
|
|
|
|
virtual const TArray<FString>& GetServerArchitectures() const override
|
|
{
|
|
return ServerArchitectures;
|
|
}
|
|
|
|
virtual void SetEditorArchitectures( const TArray<FString>& InArchitectures )
|
|
{
|
|
EditorArchitectures = InArchitectures;
|
|
}
|
|
|
|
virtual const TArray<FString>& GetEditorArchitectures() const override
|
|
{
|
|
return EditorArchitectures;
|
|
}
|
|
|
|
virtual TMap<FString,FString>& GetCustomStringProperties() override
|
|
{
|
|
return CustomStringProperties;
|
|
}
|
|
|
|
virtual TMap<FString, bool>& GetCustomBoolProperties() override
|
|
{
|
|
return CustomBoolProperties;
|
|
}
|
|
|
|
|
|
//~ End ILauncherProfile Interface
|
|
|
|
protected:
|
|
|
|
/**
|
|
* Validates the profile's current settings.
|
|
*
|
|
* Possible validation errors and warnings can be retrieved using the HasValidationError() method.
|
|
*
|
|
* @return true if the profile passed validation, false otherwise.
|
|
*/
|
|
void Validate( )
|
|
{
|
|
ValidationErrors.Reset();
|
|
|
|
// Build: a build configuration must be selected
|
|
if (BuildConfiguration == EBuildConfiguration::Unknown)
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::NoBuildConfigurationSelected);
|
|
}
|
|
|
|
// Build: a project must be selected
|
|
if (GetProjectPath().IsEmpty())
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::NoProjectSelected);
|
|
}
|
|
|
|
// Cook: at least one platform must be selected when cooking by the book
|
|
if ((CookMode == ELauncherProfileCookModes::ByTheBook) && (CookedPlatforms.Num() == 0))
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::NoPlatformSelected);
|
|
}
|
|
|
|
// Cook: at least one culture must be selected when cooking by the book
|
|
if ((CookMode == ELauncherProfileCookModes::ByTheBook) && (CookedCultures.Num() == 0))
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::NoCookedCulturesSelected);
|
|
}
|
|
|
|
// Deploy: a device group must be selected when deploying builds
|
|
if ((DeploymentMode == ELauncherProfileDeploymentModes::CopyToDevice) && !DeployedDeviceGroupId.IsValid())
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::DeployedDeviceGroupRequired);
|
|
}
|
|
|
|
// Deploy: deployment by copying to devices requires cooking by the book
|
|
if ((DeploymentMode == ELauncherProfileDeploymentModes::CopyToDevice) && ((CookMode != ELauncherProfileCookModes::ByTheBook)&&(CookMode!=ELauncherProfileCookModes::ByTheBookInEditor)) && !IsUsingZenPakStreaming())
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::CopyToDeviceRequiresCookByTheBook);
|
|
}
|
|
|
|
// Deploy: deployment by copying to devices requires no packaging
|
|
if ((DeploymentMode == ELauncherProfileDeploymentModes::CopyToDevice) && (PackagingMode != ELauncherProfilePackagingModes::DoNotPackage))
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::CopyToDeviceRequiresNoPackaging);
|
|
}
|
|
|
|
// Deploy: deployment by copying a packaged build to devices requires a package dir
|
|
if ((DeploymentMode == ELauncherProfileDeploymentModes::CopyRepository) && (PackageDir == TEXT("")))
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::NoPackageDirectorySpecified);
|
|
}
|
|
|
|
// Launch: custom launch roles are not supported yet
|
|
if (LaunchMode == ELauncherProfileLaunchModes::CustomRoles)
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::CustomRolesNotSupportedYet);
|
|
}
|
|
|
|
// Launch: when using custom launch roles, all roles must have a device assigned
|
|
if (LaunchMode == ELauncherProfileLaunchModes::CustomRoles)
|
|
{
|
|
for (int32 RoleIndex = 0; RoleIndex < LaunchRoles.Num(); ++RoleIndex)
|
|
{
|
|
if (LaunchRoles[RoleIndex]->GetAssignedDevice().IsEmpty())
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::NoLaunchRoleDeviceAssigned);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Launch: Zen pak streaming requires deployment and launch
|
|
if (IsUsingZenPakStreaming() && (LaunchMode == ELauncherProfileLaunchModes::DoNotLaunch || DeploymentMode != ELauncherProfileDeploymentModes::CopyToDevice))
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::ZenPakStreamingRequiresDeployAndLaunch);
|
|
}
|
|
|
|
if (CookUnversioned && (IncrementalCookMode == ELauncherProfileIncrementalCookMode::ModifiedOnly) && ((CookMode == ELauncherProfileCookModes::ByTheBook) || (CookMode == ELauncherProfileCookModes::ByTheBookInEditor)))
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::UnversionedAndIncremental);
|
|
}
|
|
|
|
|
|
if ( (IsGeneratingPatch() || ShouldAddPatchLevel()) && (CookMode != ELauncherProfileCookModes::ByTheBook) )
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::GeneratingPatchesCanOnlyRunFromByTheBookCookMode);
|
|
}
|
|
|
|
if (ShouldAddPatchLevel() && !IsGeneratingPatch() )
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::GeneratingMultiLevelPatchesRequiresGeneratePatch);
|
|
}
|
|
|
|
if (ShouldStageBaseReleasePaks() && BasedOnReleaseVersionName.IsEmpty())
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::StagingBaseReleasePaksWithoutABaseReleaseVersion);
|
|
}
|
|
|
|
if ( IsGeneratingChunks() && (CookMode != ELauncherProfileCookModes::ByTheBook) )
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::GeneratingChunksRequiresCookByTheBook);
|
|
}
|
|
|
|
if (IsGeneratingChunks() && !IsPackingWithUnrealPak())
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::GeneratingChunksRequiresUnrealPak);
|
|
}
|
|
|
|
if (IsGenerateHttpChunkData() && !IsGeneratingChunks() && !IsCreatingDLC())
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::GeneratingHttpChunkDataRequiresGeneratingChunks);
|
|
}
|
|
|
|
if (IsGenerateHttpChunkData() && (GetHttpChunkDataReleaseName().IsEmpty() || !FPaths::DirectoryExists(*GetHttpChunkDataDirectory())))
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::GeneratingHttpChunkDataRequiresValidDirectoryAndName);
|
|
}
|
|
|
|
// Launch: when launching, all devices that the build is launched on must have content cooked for their platform
|
|
if (LaunchMode != ELauncherProfileLaunchModes::DoNotLaunch && CookMode != ELauncherProfileCookModes::OnTheFly && CookMode != ELauncherProfileCookModes::OnTheFlyInEditor)
|
|
{
|
|
// @todo ensure that launched devices have cooked content
|
|
}
|
|
|
|
if ((CookMode == ELauncherProfileCookModes::OnTheFly) || (CookMode == ELauncherProfileCookModes::OnTheFlyInEditor))
|
|
{
|
|
if (BuildConfiguration == EBuildConfiguration::Shipping)
|
|
{
|
|
// shipping doesn't support commandline options
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::ShippingDoesntSupportCommandlineOptionsCantUseCookOnTheFly);
|
|
}
|
|
|
|
}
|
|
|
|
if (CookMode == ELauncherProfileCookModes::OnTheFly)
|
|
{
|
|
|
|
for (auto const& CookedPlatform : CookedPlatforms)
|
|
{
|
|
if (CookedPlatform.Contains("Server"))
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::CookOnTheFlyDoesntSupportServer);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
if (bArchive && ArchiveDir.IsEmpty())
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::NoArchiveDirectorySpecified);
|
|
}
|
|
|
|
if (bUseIoStore && !DeployWithUnrealPak)
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::IoStoreRequiresPakFiles);
|
|
}
|
|
|
|
ValidateBuildTarget();
|
|
ValidatePlatformSDKs();
|
|
ValidateDeviceStatus();
|
|
}
|
|
|
|
void ValidatePlatformSDKs(void)
|
|
{
|
|
ValidationErrors.Remove(ELauncherProfileValidationErrors::NoPlatformSDKInstalled);
|
|
|
|
// Cook: ensure that all platform SDKs are installed
|
|
if (CookedPlatforms.Num() > 0)
|
|
{
|
|
bool bProjectHasCode = false; // @todo: Does the project have any code?
|
|
FString NotInstalledDocLink;
|
|
for (auto PlatformName : CookedPlatforms)
|
|
{
|
|
const ITargetPlatform* Platform = GetTargetPlatformManager()->FindTargetPlatform(PlatformName);
|
|
if(!Platform || !Platform->IsSdkInstalled(bProjectHasCode, NotInstalledDocLink))
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::NoPlatformSDKInstalled);
|
|
ILauncherServicesModule& LauncherServicesModule = FModuleManager::GetModuleChecked<ILauncherServicesModule>(TEXT("LauncherServices"));
|
|
LauncherServicesModule.BroadcastLauncherServicesSDKNotInstalled(PlatformName, NotInstalledDocLink);
|
|
if (!Platform)
|
|
{
|
|
CookedPlatforms.Remove(PlatformName);
|
|
}
|
|
else
|
|
{
|
|
InvalidPlatform = PlatformName;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Deploy: ensure that all the target device SDKs are installed
|
|
if ((DeploymentMode != ELauncherProfileDeploymentModes::DoNotDeploy) && DeployedDeviceGroup.IsValid())
|
|
{
|
|
const TArray<FString>& Devices = DeployedDeviceGroup->GetDeviceIDs();
|
|
for(auto DeviceId : Devices)
|
|
{
|
|
ITargetDeviceServicesModule* TargetDeviceServicesModule = static_cast<ITargetDeviceServicesModule*>(FModuleManager::Get().LoadModule(TEXT("TargetDeviceServices")));
|
|
|
|
if (TargetDeviceServicesModule)
|
|
{
|
|
TSharedPtr<ITargetDeviceProxy> DeviceProxy = TargetDeviceServicesModule->GetDeviceProxyManager()->FindProxy(DeviceId);
|
|
|
|
if(DeviceProxy.IsValid())
|
|
{
|
|
FString const& PlatformName = DeviceProxy->GetTargetPlatformName(DeviceProxy->GetTargetDeviceVariant(DeviceId));
|
|
bool bProjectHasCode = false; // @todo: Does the project have any code?
|
|
FString NotInstalledDocLink;
|
|
const ITargetPlatform* Platform = GetTargetPlatformManager()->FindTargetPlatform(PlatformName);
|
|
if(!Platform || !Platform->IsSdkInstalled(bProjectHasCode, NotInstalledDocLink))
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::NoPlatformSDKInstalled);
|
|
ILauncherServicesModule& LauncherServicesModule = FModuleManager::GetModuleChecked<ILauncherServicesModule>(TEXT("LauncherServices"));
|
|
LauncherServicesModule.BroadcastLauncherServicesSDKNotInstalled(PlatformName, NotInstalledDocLink);
|
|
DeployedDeviceGroup->RemoveDevice(DeviceId);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ValidateDeviceStatus(void)
|
|
{
|
|
ValidationErrors.Remove(ELauncherProfileValidationErrors::LaunchDeviceIsUnauthorized);
|
|
|
|
if (DeployedDeviceGroup.IsValid())
|
|
{
|
|
const TArray<FString>& Devices = DeployedDeviceGroup->GetDeviceIDs();
|
|
for (auto DeviceId : Devices)
|
|
{
|
|
ITargetDeviceServicesModule* TargetDeviceServicesModule = static_cast<ITargetDeviceServicesModule*>(FModuleManager::Get().LoadModule(TEXT("TargetDeviceServices")));
|
|
if (TargetDeviceServicesModule)
|
|
{
|
|
TSharedPtr<ITargetDeviceProxy> DeviceProxy = TargetDeviceServicesModule->GetDeviceProxyManager()->FindProxyDeviceForTargetDevice(DeviceId);
|
|
if (DeviceProxy.IsValid())
|
|
{
|
|
if (!DeviceProxy->IsAuthorized())
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::LaunchDeviceIsUnauthorized);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ValidateBuildTarget()
|
|
{
|
|
bool bBuildTargetIsRequired = false;
|
|
bool bBuildTargetIsSelected = false;
|
|
|
|
FString BuildTarget = GetBuildTarget();
|
|
TSet<EBuildTargetType> CookTargetTypes = GetCookTargetTypes();
|
|
if (CookTargetTypes.Num() == 0)
|
|
{
|
|
CookTargetTypes.Add(EBuildTargetType::Game); // UAT defaults to 'Game' too
|
|
}
|
|
|
|
// check all build targets
|
|
const TArray<FString>& BuildTargetNames = HasProjectSpecified() ? ExplictBuildTargetNames : LauncherProfileManager->GetAllExplicitBuildTargetNames();
|
|
const TArray<FTargetInfo>& Targets = FDesktopPlatformModule::Get()->GetTargetsForProject(GetProjectPath());
|
|
for (const FTargetInfo& Target : Targets)
|
|
{
|
|
if (CookTargetTypes.Contains(Target.Type))
|
|
{
|
|
if (BuildTarget.IsEmpty())
|
|
{
|
|
// most target types can have a default build target specified in engine ini so no need to enforce this (UAT will give informative error if the ini isn't set up)
|
|
bool bSupportsDefaultBuildTarget = (Target.Type != EBuildTargetType::Program);
|
|
|
|
if (!bSupportsDefaultBuildTarget && BuildTargetNames.Contains(Target.Name))
|
|
{
|
|
bBuildTargetIsRequired = true;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Target.Name == BuildTarget)
|
|
{
|
|
bBuildTargetIsSelected = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!BuildTarget.IsEmpty() && !bBuildTargetIsSelected)
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::BuildTargetCookVariantMismatch);
|
|
}
|
|
|
|
if (bBuildTargetIsRequired)
|
|
{
|
|
if (BuildTargetSpecified)
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::BuildTargetIsRequired);
|
|
}
|
|
else
|
|
{
|
|
ValidationErrors.Add(ELauncherProfileValidationErrors::FallbackBuildTargetIsRequired);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void RefreshValidBuildTargets()
|
|
{
|
|
TArray<FString> LatestExplicitBuildTargetNames;
|
|
|
|
// collect the build targets for the current project, filtered to what we are currently wanting to cook. Do not show fallback project's build targets
|
|
if (HasProjectSpecified())
|
|
{
|
|
TSet<EBuildTargetType> CookTargetTypes = GetCookTargetTypes();
|
|
LatestExplicitBuildTargetNames = FGameProjectHelper::GetExplicitBuildTargetsForProject( GetProjectPath(), &CookTargetTypes );
|
|
}
|
|
|
|
// notify listeners if the explicitly-required build targets have changed
|
|
if (ExplictBuildTargetNames != LatestExplicitBuildTargetNames)
|
|
{
|
|
ExplictBuildTargetNames = LatestExplicitBuildTargetNames;
|
|
BuildTargetOptionsChangedDelegate.Broadcast();
|
|
}
|
|
}
|
|
|
|
|
|
TSet<EBuildTargetType> GetCookTargetTypes() const
|
|
{
|
|
TSet<EBuildTargetType> CookTargetTypes;
|
|
for ( const FString& Variant : GetCookedPlatforms() )
|
|
{
|
|
if (Variant.EndsWith(TEXT("Client")))
|
|
{
|
|
CookTargetTypes.Add(EBuildTargetType::Client);
|
|
}
|
|
else if (Variant.EndsWith(TEXT("Server")))
|
|
{
|
|
CookTargetTypes.Add(EBuildTargetType::Server);
|
|
}
|
|
else if (Variant.EndsWith(TEXT("Editor")))
|
|
{
|
|
CookTargetTypes.Add(EBuildTargetType::Editor);
|
|
}
|
|
else
|
|
{
|
|
CookTargetTypes.Add(EBuildTargetType::Game);
|
|
}
|
|
}
|
|
|
|
return MoveTemp(CookTargetTypes);
|
|
}
|
|
|
|
|
|
void OnLauncherDeviceGroupDeviceAdded(const ILauncherDeviceGroupRef& DeviceGroup, const FString& DeviceId)
|
|
{
|
|
if( DeviceGroup == DeployedDeviceGroup )
|
|
{
|
|
ValidatePlatformSDKs();
|
|
}
|
|
}
|
|
|
|
void OnLauncherDeviceGroupDeviceRemove(const ILauncherDeviceGroupRef& DeviceGroup, const FString& DeviceId)
|
|
{
|
|
if( DeviceGroup == DeployedDeviceGroup )
|
|
{
|
|
ValidatePlatformSDKs();
|
|
}
|
|
}
|
|
|
|
void OnSelectedProjectChanged()
|
|
{
|
|
RefreshValidBuildTargets();
|
|
|
|
BuildTargetName.Empty();
|
|
BuildTargetSpecified = ProjectSpecified; // if this is for 'Any Project' then it should use the fallback build target
|
|
}
|
|
|
|
private:
|
|
|
|
// Holds a reference to the launcher profile manager.
|
|
ILauncherProfileManagerRef LauncherProfileManager;
|
|
|
|
// Holds the desired build configuration (only used if creating new builds).
|
|
EBuildConfiguration BuildConfiguration;
|
|
|
|
// Holds a flag indicating whether the build target is specified by this profile.
|
|
bool BuildTargetSpecified;
|
|
|
|
// Holds the name of the target (matching a .cs file) to build. Needed when multiple targets of a type exist
|
|
FString BuildTargetName;
|
|
|
|
// Holds the build mode.
|
|
// Holds the build configuration name of the cooker.
|
|
EBuildConfiguration CookConfiguration;
|
|
|
|
// Holds additional cooker command line options.
|
|
FString CookOptions;
|
|
|
|
// Holds the cooking mode.
|
|
TEnumAsByte<ELauncherProfileCookModes::Type> CookMode;
|
|
|
|
// Holds the build mode
|
|
TEnumAsByte<ELauncherProfileBuildModes::Type> BuildMode;
|
|
|
|
// Holds a flag indicating whether UAT should be built
|
|
bool BuildUAT;
|
|
|
|
// Generate compressed content
|
|
bool Compressed;
|
|
|
|
// encrypt ini files in the pak file
|
|
bool EncryptIniFiles;
|
|
// is this build for distribution
|
|
bool ForDistribution;
|
|
|
|
// Holds the incremental cook mode indicating whether only modified content should be cooked.
|
|
TEnumAsByte<ELauncherProfileIncrementalCookMode::Type> IncrementalCookMode;
|
|
|
|
// hold a flag indicating if we want to iterate on the shared cooked build
|
|
bool IterateSharedCookedBuild;
|
|
|
|
// Holds a flag indicating whether packages should be saved without a version.
|
|
bool CookUnversioned;
|
|
|
|
bool bSkipCookingEditorContent;
|
|
|
|
// This setting is used only if cooking by the book (only used if cooking by the book).
|
|
TArray<FString> CookedCultures;
|
|
|
|
// Holds the collection of maps to cook (only used if cooking by the book).
|
|
TArray<FString> CookedMaps;
|
|
|
|
// Holds the platforms to include in the build (only used if creating new builds).
|
|
TArray<FString> CookedPlatforms;
|
|
|
|
// Holds the platforms to deploy to if no specific devices were chosen for deploy.
|
|
FName DefaultDeployPlatform;
|
|
|
|
// Holds the default role (only used if launch mode is DefaultRole).
|
|
ILauncherProfileLaunchRoleRef DefaultLaunchRole;
|
|
|
|
// Holds a flag indicating whether a streaming file server should be used.
|
|
bool DeployStreamingServer;
|
|
|
|
// Holds a flag indicating whether content should be packaged with UnrealPak.
|
|
bool DeployWithUnrealPak;
|
|
|
|
// Flag to indicate if game prerequisites should be included
|
|
bool IncludePrerequisites;
|
|
|
|
// Flag indicating if content should be split into chunks
|
|
bool bGenerateChunks;
|
|
|
|
// Flag indicating if chunked content should be used to generate HTTPChunkInstall data
|
|
bool bGenerateHttpChunkData;
|
|
|
|
// Where to store HTTPChunkInstall data
|
|
FString HttpChunkDataDirectory;
|
|
|
|
// Version name of the HTTPChunkInstall data
|
|
FString HttpChunkDataReleaseName;
|
|
|
|
// if present, iostore container creation will try to use existing compressed blocks
|
|
// instead of compressing new ones, to avoid patches from compressor version changes,
|
|
// and to speed up iostore container creation time. See IoStoreUtilities.cpp ReferenceContainerGlobalFileName.
|
|
FString ReferenceContainerGlobalFileName;
|
|
|
|
// If ReferenceContainerGlobalFileName refers to encrypted containers, this is the filename of
|
|
// the json file containing the keys.
|
|
FString ReferenceContainerCryptoKeysFileName;
|
|
|
|
// create a release version of the content (this can be used to base dlc / patches from)
|
|
bool CreateReleaseVersion;
|
|
|
|
// name of the release version
|
|
FString CreateReleaseVersionName;
|
|
|
|
// name of the release version to base this dlc / patch on
|
|
FString BasedOnReleaseVersionName;
|
|
|
|
// name of the original release version
|
|
FString OriginalReleaseVersionName;
|
|
|
|
// This build generate a patch based on some source content seealso PatchSourceContentPath
|
|
bool GeneratePatch;
|
|
|
|
// This build generates a new tier patch file for modified content
|
|
bool AddPatchLevel;
|
|
|
|
// This build stages pak files from the release version it is based on (deprecated)
|
|
bool StageBaseReleasePaks;
|
|
|
|
// This build will cook content for dlc See also DLCName
|
|
bool CreateDLC;
|
|
|
|
// name of the dlc we are going to build (the name of the dlc plugin)
|
|
FString DLCName;
|
|
|
|
// should the dlc include engine content in the current dlc
|
|
// engine content which was not referenced by original release
|
|
// otherwise error on any access of engine content during dlc cook
|
|
bool DLCIncludeEngineContent;
|
|
|
|
// Holds a flag indicating whether to use incremental deployment
|
|
bool DeployIncremental;
|
|
|
|
// Holds the device group to deploy to.
|
|
ILauncherDeviceGroupPtr DeployedDeviceGroup;
|
|
|
|
// Delegate handles for registered DeployedDeviceGroup event handlers.
|
|
FDelegateHandle OnLauncherDeviceGroupDeviceAddedDelegateHandle;
|
|
FDelegateHandle OnLauncherDeviceGroupDeviceRemoveDelegateHandle;
|
|
|
|
// Holds the identifier of the deployed device group.
|
|
FGuid DeployedDeviceGroupId;
|
|
|
|
// Holds the deployment mode.
|
|
TEnumAsByte<ELauncherProfileDeploymentModes::Type> DeploymentMode;
|
|
|
|
// Holds a flag indicating whether the file server's console window should be hidden.
|
|
bool HideFileServerWindow;
|
|
|
|
// Holds the profile's unique identifier.
|
|
FGuid Id;
|
|
|
|
// Holds the launch mode.
|
|
TEnumAsByte<ELauncherProfileLaunchModes::Type> LaunchMode;
|
|
|
|
// Holds the launch roles (only used if launch mode is UsingRoles).
|
|
TArray<ILauncherProfileLaunchRolePtr> LaunchRoles;
|
|
|
|
// Holds the profile's name.
|
|
FString Name;
|
|
|
|
// Holds the profile's description.
|
|
FString Description;
|
|
|
|
// Holds the packaging mode.
|
|
TEnumAsByte<ELauncherProfilePackagingModes::Type> PackagingMode;
|
|
|
|
// Holds the package directory
|
|
FString PackageDir;
|
|
|
|
// Whether to run archive step
|
|
bool bArchive;
|
|
|
|
// Holds the archive directory
|
|
FString ArchiveDir;
|
|
|
|
// Holds a flag indicating whether the project is specified by this profile.
|
|
bool ProjectSpecified;
|
|
|
|
// Holds the full absolute path to the Unreal project used by this profile.
|
|
FString FullProjectPath;
|
|
|
|
// Holds the path that might be shareable between people. Only works if the project is under the UE root.
|
|
// otherwise this is an absolute path.
|
|
FString ShareableProjectPath;
|
|
|
|
// Holds the full path to a folder to use for Zen pak streaming
|
|
FString ZenPakStreamingPath;
|
|
|
|
// Holds the collection of validation errors.
|
|
TArray<ELauncherProfileValidationErrors::Type> ValidationErrors;
|
|
FString InvalidPlatform;
|
|
|
|
// Holds the time out time for the cook on the fly server
|
|
uint32 Timeout;
|
|
|
|
// Holds the close value for the cook on the fly server
|
|
bool ForceClose;
|
|
|
|
// Path to the editor executable to pass to UAT, for cooking, etc... May be empty.
|
|
FString EditorExe;
|
|
|
|
// Profile is for an internal project
|
|
bool bNotForLicensees;
|
|
|
|
// Additional command line parameters to set for the application when it launches
|
|
FString AdditionalCommandLineParameters;
|
|
|
|
// Use I/O store.
|
|
bool bUseIoStore;
|
|
|
|
// Use Zen storage server
|
|
bool bUseZenStore;
|
|
|
|
// Import a Zen snapshot before cooking
|
|
bool bImportingZenSnapshot;
|
|
|
|
// Use Zen pak streaming
|
|
bool bUseZenPakStreaming;
|
|
|
|
// Make binary config.
|
|
bool bMakeBinaryConfig;
|
|
|
|
// Update flash on device before running
|
|
bool bShouldUpdateFlash;
|
|
|
|
// Is the launch device actually a Simulator
|
|
bool bIsDeviceASimulator;
|
|
|
|
// Architectures to build (x64, arm64 etc)
|
|
TArray<FString> ClientArchitectures;
|
|
TArray<FString> ServerArchitectures;
|
|
TArray<FString> EditorArchitectures;
|
|
|
|
// Key-Value pairs for extsibility. Not user-facing.
|
|
TMap<FString,FString> CustomStringProperties;
|
|
TMap<FString, bool> CustomBoolProperties;
|
|
|
|
private:
|
|
|
|
// cook in the editor callbacks (not valid for any other cook mode)
|
|
FIsCookFinishedDelegate IsCookFinishedDelegate;
|
|
FCookCanceledDelegate CookCanceledDelegate;
|
|
|
|
// Holds a delegate to be invoked when changing the device group to deploy to.
|
|
FOnLauncherProfileDeployedDeviceGroupChanged DeployedDeviceGroupChangedDelegate;
|
|
|
|
// Holds a delegate to be invoked when the project has changed
|
|
FOnProfileProjectChanged ProjectChangedDelegate;
|
|
|
|
// Holds a delegate to be invoked when the project build target options have changed
|
|
FOnProfileBuildTargetOptionsChanged BuildTargetOptionsChangedDelegate;
|
|
|
|
// Cached build target options (not serialized)
|
|
TArray<FString> ExplictBuildTargetNames;
|
|
};
|