public static void ApplyStagingManifest(ProjectParams Params, DeploymentContext SC)
    {
        MaybeConvertToLowerCase(Params, SC);
        if (SC.Stage && !Params.NoCleanStage && !Params.SkipStage)
        {
            DeleteDirectory(SC.StageDirectory);
        }
        if (ShouldCreatePak(Params, SC))
        {
            if (Params.Manifests && DoesChunkPakManifestExist(Params, SC))
            {
                CreatePaksUsingChunkManifests(Params, SC);
            }
            else
            {
                CreatePakUsingStagingManifest(Params, SC);
            }
        }
        if (!SC.Stage || Params.SkipStage)
        {
            return;
        }
        DumpManifest(SC, CombinePaths(CmdEnv.LogFolder, "FinalCopy" + (SC.DedicatedServer ? "_Server" : "")), !Params.UsePak(SC.StageTargetPlatform));
        CopyUsingStagingManifest(Params, SC);

        var ThisPlatform = SC.StageTargetPlatform;
        ThisPlatform.PostStagingFileCopy(Params, SC);
    }
    public static void ApplyStagingManifest(ProjectParams Params, DeploymentContext SC)
    {
        MaybeConvertToLowerCase(Params, SC);
        if (SC.Stage && !Params.NoCleanStage && !Params.SkipStage && !Params.IterativeDeploy)
        {
            try
            {
                DeleteDirectory(SC.StageDirectory);
            }
            catch (Exception Ex)
            {
                // Delete cooked data (if any) as it may be incomplete / corrupted.
                Log("Failed to delete staging directory "+SC.StageDirectory);
                AutomationTool.ErrorReporter.Error("Stage Failed.", (int)AutomationTool.ErrorCodes.Error_FailedToDeleteStagingDirectory);
                throw Ex;
            }
        }
        else
        {
            try
            {
                // delete old pak files
                DeletePakFiles(SC.StageDirectory);
            }
            catch (Exception Ex)
            {
                // Delete cooked data (if any) as it may be incomplete / corrupted.
                Log("Failed to delete pak files in "+SC.StageDirectory);
                AutomationTool.ErrorReporter.Error("Stage Failed.", (int)AutomationTool.ErrorCodes.Error_FailedToDeleteStagingDirectory);
                throw Ex;
            }
        }
        if (ShouldCreatePak(Params, SC))
        {
            if (Params.Manifests && DoesChunkPakManifestExist(Params, SC))
            {
                CreatePaksUsingChunkManifests(Params, SC);
            }
            else
            {
                CreatePakUsingStagingManifest(Params, SC);
            }
        }
        if (!SC.Stage || Params.SkipStage)
        {
            return;
        }
        DumpManifest(SC, CombinePaths(CmdEnv.LogFolder, "FinalCopy" + (SC.DedicatedServer ? "_Server" : "")), !Params.UsePak(SC.StageTargetPlatform));
        CopyUsingStagingManifest(Params, SC);

        var ThisPlatform = SC.StageTargetPlatform;
        ThisPlatform.PostStagingFileCopy(Params, SC);
    }
    public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC)
    {
        List<string> Exes = GetExecutableNames(SC);
        foreach (var Exe in Exes)
        {
            if (Exe.StartsWith(CombinePaths(SC.RuntimeProjectRootDir, "Binaries", SC.PlatformDir)))
            {
                StageAppBundle(SC, CombinePaths(SC.ProjectRoot, "Binaries", SC.PlatformDir, Path.GetFileNameWithoutExtension(Exe) + ".app"), CombinePaths(SC.ShortProjectName, "Binaries", SC.PlatformDir, Path.GetFileNameWithoutExtension(Exe) + ".app"));
            }
            else if (Exe.StartsWith(CombinePaths(SC.RuntimeRootDir, "Engine/Binaries", SC.PlatformDir)))
            {
                StageAppBundle(SC, CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir, Path.GetFileNameWithoutExtension(Exe) + ".app"), CombinePaths("Engine/Binaries", SC.PlatformDir, Path.GetFileNameWithoutExtension(Exe) + ".app"));
            }
        }

        // Copy the splash screen, Mac specific
        SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Content/Splash"), "Splash.bmp", false, null, null, true);

        SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.LocalRoot, "Engine/Content/Localization/ICU"), "*", true, null, null, false, !Params.UsePak(SC.StageTargetPlatform));
    }
	public static void CopyUsingStagingManifest(ProjectParams Params, DeploymentContext SC)
	{
		CopyManifestFilesToStageDir(SC.NonUFSStagingFiles, SC.StageDirectory, "NonUFSFiles", SC.StageTargetPlatform.GetFilesForCRCCheck());

		if (!Params.NoDebugInfo)
		{
			CopyManifestFilesToStageDir(SC.NonUFSStagingFilesDebug, SC.StageDirectory, "DebugFiles", SC.StageTargetPlatform.GetFilesForCRCCheck());
		}

		bool bStageUnrealFileSystemFiles = !Params.CookOnTheFly && !Params.UsePak(SC.StageTargetPlatform) && !Params.FileServer;
		if (bStageUnrealFileSystemFiles)
		{
			CopyManifestFilesToStageDir(SC.UFSStagingFiles, SC.StageDirectory, "UFSFiles", SC.StageTargetPlatform.GetFilesForCRCCheck());
		}
	}
	public static void CreateStagingManifest(ProjectParams Params, DeploymentContext SC)
	{
		if (!Params.Stage)
		{
			return;
		}
		var ThisPlatform = SC.StageTargetPlatform;

		LogConsole("Creating Staging Manifest...");

        if (Params.HasDLCName)
        {
            string DLCName = Params.DLCName;

            // Making a plugin, grab the binaries too
            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Plugins", DLCName), "*.uplugin", true, null, null, true);
            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Plugins", DLCName, "Binaries"), "libUE4-*.so", true, null, null, true);
            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Plugins", DLCName, "Binaries"), "UE4-*.dll", true, null, null, true);
            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Plugins", DLCName, "Binaries"), "libUE4Server-*.so", true, null, null, true);
            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Plugins", DLCName, "Binaries"), "UE4Server-*.dll", true, null, null, true);

            // Put all of the cooked dir into the staged dir
            // Dedicated server cook doesn't save shaders so no Engine dir is created
            if ((!SC.DedicatedServer) && (!Params.DLCIncludeEngineContent))
            {
                if (Directory.Exists(CombinePaths(SC.ProjectRoot, "Plugins", DLCName, "Saved", "Cooked", SC.CookPlatform, "Engine")))
                {
                    SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.ProjectRoot, "Plugins", DLCName, "Saved", "Cooked", SC.CookPlatform), "*", true, new[] { CommandUtils.CombinePaths("Engine", "*") }, "", true, !Params.UsePak(SC.StageTargetPlatform));
                }
            }
            
            SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.ProjectRoot, "Plugins", DLCName, "Saved", "Cooked", SC.CookPlatform), "*", true, new[] { "AssetRegistry.bin" }, "", true, !Params.UsePak(SC.StageTargetPlatform));

            return;
        }


		ThisPlatform.GetFilesToDeployOrStage(Params, SC);


		// Stage any extra runtime dependencies from the receipts
		foreach(TargetReceipt Receipt in SC.StageTargetReceipts)
		{
			SC.StageRuntimeDependenciesFromReceipt(Receipt);
		}

		// Get the build.properties file
		// this file needs to be treated as a UFS file for casing, but NonUFS for being put into the .pak file
		// @todo: Maybe there should be a new category - UFSNotForPak
		string BuildPropertiesPath = CombinePaths(SC.LocalRoot, "Engine/Build");
		if (SC.StageTargetPlatform.DeployLowerCaseFilenames(true))
		{
			BuildPropertiesPath = BuildPropertiesPath.ToLowerInvariant();
		}
		SC.StageFiles(StagedFileType.NonUFS, BuildPropertiesPath, "Build.version", false, null, null, true);

		// move the UE4Commandline.txt file to the root of the stage
		// this file needs to be treated as a UFS file for casing, but NonUFS for being put into the .pak file
		// @todo: Maybe there should be a new category - UFSNotForPak
		string CommandLineFile = "UE4CommandLine.txt";
		if (SC.StageTargetPlatform.DeployLowerCaseFilenames(true))
		{
			CommandLineFile = CommandLineFile.ToLowerInvariant();
		}
		SC.StageFiles(StagedFileType.NonUFS, GetIntermediateCommandlineDir(SC), CommandLineFile, false, null, "", true, false);

        ConfigCacheIni PlatformGameConfig = new ConfigCacheIni(SC.StageTargetPlatform.PlatformType, "Game", CommandUtils.GetDirectoryName(Params.RawProjectPath));
        var ProjectContentRoot = CombinePaths(SC.ProjectRoot, "Content");
        var StageContentRoot = CombinePaths(SC.RelativeProjectRootForStage, "Content");
        
        if (!Params.CookOnTheFly && !Params.SkipCookOnTheFly) // only stage the UFS files if we are not using cook on the fly
        {


            // Initialize internationalization preset.
            string InternationalizationPreset = null;

            // Use parameters if provided.
            if (string.IsNullOrEmpty(InternationalizationPreset))
            {
                InternationalizationPreset = Params.InternationalizationPreset;
            }

            // Use configuration if otherwise lacking an internationalization preset.
            if (string.IsNullOrEmpty(InternationalizationPreset))
            {
                if (PlatformGameConfig != null)
                {
                    PlatformGameConfig.GetString("/Script/UnrealEd.ProjectPackagingSettings", "InternationalizationPreset", out InternationalizationPreset);
                }
            }

            // Error if no preset has been provided.
            if (string.IsNullOrEmpty(InternationalizationPreset))
            {
                throw new AutomationException("No internationalization preset was specified for packaging. This will lead to fatal errors when launching. Specify preset via commandline (-I18NPreset=) or project packaging settings (InternationalizationPreset).");
            }

            // Initialize cultures to stage.
            List<string> CulturesToStage = null;

            // Use parameters if provided.
            if (Params.CulturesToCook != null && Params.CulturesToCook.Count > 0)
            {
                CulturesToStage = Params.CulturesToCook;
            }

            // Use configuration if otherwise lacking cultures to stage.
            if (CulturesToStage == null || CulturesToStage.Count == 0)
            {
                if (PlatformGameConfig != null)
                {
                    PlatformGameConfig.GetArray("/Script/UnrealEd.ProjectPackagingSettings", "CulturesToStage", out CulturesToStage);
                }
            }

            // Error if no cultures have been provided.
            if (CulturesToStage == null || CulturesToStage.Count == 0)
            {
                throw new AutomationException("No cultures were specified for cooking and packaging. This will lead to fatal errors when launching. Specify culture codes via commandline (-CookCultures=) or using project packaging settings (+CulturesToStage).");
            }

            // Stage ICU internationalization data from Engine.
            SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.LocalRoot, "Engine", "Content", "Internationalization", InternationalizationPreset), "*", true, null, CombinePaths("Engine", "Content", "Internationalization"), true, !Params.UsePak(SC.StageTargetPlatform));

            // Engine ufs (content)
            SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.LocalRoot, "Engine/Config"), "*", true, null, null, false, !Params.UsePak(SC.StageTargetPlatform)); // TODO: Exclude localization data generation config files.

            // Stat prefix/suffix files (used for FPSChart, etc...)
            //@TODO: Avoid packaging stat files in shipping builds (only 6 KB, but still more than zero)
            SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.LocalRoot, "Engine/Content/Stats"), "*", true, null, null, false, !Params.UsePak(SC.StageTargetPlatform));

            if (Params.bUsesSlate)
            {
                if (Params.bUsesSlateEditorStyle)
                {
                    SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.LocalRoot, "Engine/Content/Editor/Slate"), "*", true, null, null, false, !Params.UsePak(SC.StageTargetPlatform));
                }
                SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.LocalRoot, "Engine/Content/Slate"), "*", true, null, null, false, !Params.UsePak(SC.StageTargetPlatform));
                SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.ProjectRoot, "Content/Slate"), "*", true, new string[] { "*.uasset" }, CombinePaths(SC.RelativeProjectRootForStage, "Content/Slate"), true, !Params.UsePak(SC.StageTargetPlatform));
            }
            foreach (string Culture in CulturesToStage)
            {
                StageLocalizationDataForCulture(SC, Culture, CombinePaths(SC.LocalRoot, "Engine/Content/Localization/Engine"), null, !Params.UsePak(SC.StageTargetPlatform));
            }
			
			// Engine & Game Plugins. Push the Engine/Source working directory so UBT code has a correct RelativeEnginePath in ReadAvailablePlugins
			ProjectDescriptor Project = ProjectDescriptor.FromFile(SC.RawProjectPath);
			Log("Searching for plugins with CurrentWorkingDir: " + Directory.GetCurrentDirectory());
			Log("Searching for plugins in: " + SC.RawProjectPath);
			List<PluginInfo> AvailablePlugins = Plugins.ReadAvailablePlugins(CombinePaths(SC.LocalRoot, "Engine"), SC.RawProjectPath);
			foreach (PluginInfo Plugin in AvailablePlugins)
			{
				Log("Considering Plugin for Stage: " + Plugin.FileName);
				if (UProjectInfo.IsPluginEnabledForProject(Plugin, Project, SC.StageTargetPlatform.PlatformType))
				{
					Log("EnabledPlugin: " + Plugin.FileName);
					SC.StageFiles(StagedFileType.UFS, Plugin.Directory, "*.uplugin", false, null, null, true, !Params.UsePak(SC.StageTargetPlatform), null, true, false);
				}
			}

            // Game ufs (content)

            SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.ProjectRoot), "*.uproject", false, null, CombinePaths(SC.RelativeProjectRootForStage), true, !Params.UsePak(SC.StageTargetPlatform));
			if (SC.StageTargetPlatform.PlatformType != UnrealTargetPlatform.HTML5 && SC.bUseWebsocketNetDriver)
			{
				var EngineIniPath = Path.Combine(SC.ProjectRoot, "Config", "DefaultEngine.ini");
				var IntermediateEngineIniDir = Path.Combine(GetIntermediateCommandlineDir(SC), SC.RelativeProjectRootForStage, "Config");
				Directory.CreateDirectory(IntermediateEngineIniDir);
				var IntermediateEngineIniPath = Path.Combine(IntermediateEngineIniDir, "DefaultEngine.ini");
				List<String> IniLines = new List<String>();
				if (File.Exists(EngineIniPath))
				{
					IniLines = File.ReadAllLines(EngineIniPath).ToList();
				}
				IniLines.Add("[/Script/Engine.GameEngine]");
				IniLines.Add("!NetDriverDefinitions=ClearArray");
				IniLines.Add("+NetDriverDefinitions=(DefName=\"GameNetDriver\", DriverClassName=\"/Script/HTML5Networking.WebSocketNetDriver\", DriverClassNameFallback=\"/Script/HTML5Networking.WebSocketNetDriver\")");
				File.WriteAllLines(IntermediateEngineIniPath, IniLines);
				SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.ProjectRoot, "Config"), "*", true, new string[] {"DefaultEngine.ini"}, CombinePaths(SC.RelativeProjectRootForStage, "Config"), true, !Params.UsePak(SC.StageTargetPlatform)); // TODO: Exclude localization data generation config files.
				SC.StageFiles(StagedFileType.UFS, IntermediateEngineIniDir, "*.ini", true, null, CombinePaths(SC.RelativeProjectRootForStage, "Config"), true, !Params.UsePak(SC.StageTargetPlatform)); // TODO: Exclude localization data generation config files.
			}
			else
			{
				SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.ProjectRoot, "Config"), "*", true, null, CombinePaths(SC.RelativeProjectRootForStage, "Config"), true, !Params.UsePak(SC.StageTargetPlatform)); // TODO: Exclude localization data generation config files.
			}
            foreach (string Culture in CulturesToStage)
            {
                StageLocalizationDataForCulture(SC, Culture, CombinePaths(SC.ProjectRoot, "Content/Localization/Game"), CombinePaths(SC.RelativeProjectRootForStage, "Content/Localization/Game"), !Params.UsePak(SC.StageTargetPlatform));
            }

            // Stage any additional UFS and NonUFS paths specified in the project ini files; these dirs are relative to the game content directory
            if (PlatformGameConfig != null)
            {
                List<string> ExtraUFSDirs;
                if (PlatformGameConfig.GetArray("/Script/UnrealEd.ProjectPackagingSettings", "DirectoriesToAlwaysStageAsUFS", out ExtraUFSDirs))
                {
                    // Each string has the format '(Path="TheDirToStage")'
                    foreach (var PathStr in ExtraUFSDirs)
                    {
                        var PathParts = PathStr.Split('"');
                        if (PathParts.Length == 3)
                        {
                            var RelativePath = PathParts[1];
                            SC.StageFiles(StagedFileType.UFS, CombinePaths(ProjectContentRoot, RelativePath), "*", true, null, CombinePaths(StageContentRoot, RelativePath), true, !Params.UsePak(SC.StageTargetPlatform));
                        }
                        else if (PathParts.Length == 1)
                        {
                            var RelativePath = PathParts[0];
                            SC.StageFiles(StagedFileType.UFS, CombinePaths(ProjectContentRoot, RelativePath), "*", true, null, CombinePaths(StageContentRoot, RelativePath), true, !Params.UsePak(SC.StageTargetPlatform));
                        }
                    }
                }

                List<string> ExtraNonUFSDirs;
                if (PlatformGameConfig.GetArray("/Script/UnrealEd.ProjectPackagingSettings", "DirectoriesToAlwaysStageAsNonUFS", out ExtraNonUFSDirs))
                {
                    // Each string has the format '(Path="TheDirToStage")'
                    foreach (var PathStr in ExtraNonUFSDirs)
                    {
                        var PathParts = PathStr.Split('"');
                        if (PathParts.Length == 3)
                        {
                            var RelativePath = PathParts[1];
                            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(ProjectContentRoot, RelativePath));
                        }
                        else if (PathParts.Length == 1)
                        {
                            var RelativePath = PathParts[0];
                            SC.StageFiles(StagedFileType.UFS, CombinePaths(ProjectContentRoot, RelativePath), "*", true, null, CombinePaths(StageContentRoot, RelativePath), true, !Params.UsePak(SC.StageTargetPlatform));
                        }
                    }
                }
            }

            StagedFileType StagedFileTypeForMovies = StagedFileType.NonUFS;
            if (Params.FileServer)
            {
                // UFS is required when using a file server
                StagedFileTypeForMovies = StagedFileType.UFS;
            }

            if (SC.StageTargetPlatform.StageMovies)
            {
                SC.StageFiles(StagedFileTypeForMovies, CombinePaths(SC.LocalRoot, "Engine/Content/Movies"), "*", true, new string[] { "*.uasset", "*.umap" }, CombinePaths(SC.RelativeProjectRootForStage, "Engine/Content/Movies"), true, !Params.UsePak(SC.StageTargetPlatform));
                SC.StageFiles(StagedFileTypeForMovies, CombinePaths(SC.ProjectRoot, "Content/Movies"), "*", true, new string[] { "*.uasset", "*.umap" }, CombinePaths(SC.RelativeProjectRootForStage, "Content/Movies"), true, !Params.UsePak(SC.StageTargetPlatform));
            }

            // eliminate the sand box
            SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.ProjectRoot, "Saved", "Cooked", SC.CookPlatform), "*", true, new string[] { "*.json" }, "", true, !Params.UsePak(SC.StageTargetPlatform));

            // CrashReportClient is a standalone slate app that does not look in the generated pak file, so it needs the Content/Slate and Shaders/StandaloneRenderer folders Non-UFS
            // @todo Make CrashReportClient more portable so we don't have to do this
            if (SC.bStageCrashReporter && UnrealBuildTool.UnrealBuildTool.PlatformSupportsCrashReporter(SC.StageTargetPlatform.PlatformType) && !SC.DedicatedServer)
            {
                //If the .dat file needs to be staged as NonUFS for non-Windows/Linux hosts we need to change the casing as we do with the build properties file above.
                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Content/Slate"));
                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Shaders/StandaloneRenderer"));

                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine", "Content", "Internationalization", InternationalizationPreset), "*", true, null, CombinePaths("Engine", "Content", "Internationalization"), false, true);

                // Linux platform stages ICU in GetFilesToDeployOrStage(), accounting for the actual architecture
                if (SC.StageTargetPlatform.PlatformType == UnrealTargetPlatform.Win64 ||
                    SC.StageTargetPlatform.PlatformType == UnrealTargetPlatform.Win32 ||
                    SC.StageTargetPlatform.PlatformType == UnrealTargetPlatform.Mac)
                {
                    SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/ICU"));
                }

                // SSL libraries are only available for Win64 builds.
                // @see FPerforceSourceControlProvider::LoadSSLLibraries
                if (SC.StageTargetPlatform.PlatformType == UnrealTargetPlatform.Win64)
                {
                    SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/OpenSSL"));
                }
            }
        }
        else
        {
            if (PlatformGameConfig != null)
            {
                List<string> ExtraNonUFSDirs;
                if (PlatformGameConfig.GetArray("/Script/UnrealEd.ProjectPackagingSettings", "DirectoriesToAlwaysStageAsNonUFS", out ExtraNonUFSDirs))
                {
                    // Each string has the format '(Path="TheDirToStage")'
                    foreach (var PathStr in ExtraNonUFSDirs)
                    {
                        var PathParts = PathStr.Split('"');
                        if (PathParts.Length == 3)
                        {
                            var RelativePath = PathParts[1];
                            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(ProjectContentRoot, RelativePath));
                        }
                        else if (PathParts.Length == 1)
                        {
                            var RelativePath = PathParts[0];
                            SC.StageFiles(StagedFileType.UFS, CombinePaths(ProjectContentRoot, RelativePath), "*", true, null, CombinePaths(StageContentRoot, RelativePath), true, !Params.UsePak(SC.StageTargetPlatform));
                        }
                    }
                }
            }
        }
	}
	public static void MaybeConvertToLowerCase(ProjectParams Params, DeploymentContext SC)
	{
		var BuildPlatform = SC.StageTargetPlatform;

		if (BuildPlatform.DeployLowerCaseFilenames(false))
		{
			SC.NonUFSStagingFiles = ConvertToLower(SC.NonUFSStagingFiles);
			SC.NonUFSStagingFilesDebug = ConvertToLower(SC.NonUFSStagingFilesDebug);
		}
		if (Params.UsePak(SC.StageTargetPlatform) && BuildPlatform.DeployPakInternalLowerCaseFilenames())
		{
			SC.UFSStagingFiles = ConvertToLower(SC.UFSStagingFiles);
		}
		else if (!Params.UsePak(SC.StageTargetPlatform) && BuildPlatform.DeployLowerCaseFilenames(true))
		{
			SC.UFSStagingFiles = ConvertToLower(SC.UFSStagingFiles);
		}
	}
	private static ProcessResult RunDedicatedServer(ProjectParams Params, string ServerLogFile, string AdditionalCommandLine)
	{
		ProjectParams ServerParams = new ProjectParams(Params);
		ServerParams.Device = Params.ServerDevice;

		if (ServerParams.ServerTargetPlatforms.Count == 0)
		{
			throw new AutomationException("No ServerTargetPlatform set for RunDedicatedServer.");
		}

		var DeployContextList = CreateDeploymentContext(ServerParams, true);

		if (DeployContextList.Count == 0)
		{
			throw new AutomationException("No DeployContextList for RunDedicatedServer.");
		}

		var SC = DeployContextList[0];

		var ServerApp = CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/Win64/UE4Editor.exe");
		if (ServerParams.Cook)
		{
			List<string> Exes = SC.StageTargetPlatform.GetExecutableNames(SC);
			ServerApp = Exes[0];
		}
		var Args = ServerParams.Cook ? "" : (SC.ProjectArgForCommandLines + " ");
		Console.WriteLine(Params.ServerDeviceAddress);
		UnrealTargetPlatform ServerPlatform = ServerParams.ServerTargetPlatforms[0];
		if (ServerParams.Cook && ServerPlatform == UnrealTargetPlatform.Linux && !String.IsNullOrEmpty(ServerParams.ServerDeviceAddress))
		{
			ServerApp = @"C:\Windows\system32\cmd.exe";

			string plinkPath = CombinePaths(Environment.GetEnvironmentVariable("LINUX_ROOT"), "bin/PLINK.exe ");
			string exePath = CombinePaths(SC.ShortProjectName, "Binaries", ServerPlatform.ToString(), SC.ShortProjectName + "Server");
			if (ServerParams.ServerConfigsToBuild[0] != UnrealTargetConfiguration.Development)
			{
				exePath += "-" + ServerPlatform.ToString() + "-" + ServerParams.ServerConfigsToBuild[0].ToString();
			}
			exePath = CombinePaths("LinuxServer", exePath.ToLower()).Replace("\\", "/");
			Args = String.Format("/k {0} -batch -ssh -t -i {1} {2}@{3} {4} {5} {6} -server -Messaging", plinkPath, ServerParams.DevicePassword, ServerParams.DeviceUsername, ServerParams.ServerDeviceAddress, exePath, Args, ServerParams.MapToRun);
		}
		else
		{
			var Map = ServerParams.MapToRun;
			if (!String.IsNullOrEmpty(ServerParams.AdditionalServerMapParams))
			{
				Map += ServerParams.AdditionalServerMapParams;
			}
			if (Params.FakeClient)
			{
				Map += "?fake";
			}
			Args += String.Format("{0} -server -abslog={1}  -unattended -FORCELOGFLUSH -log -Messaging -nomcp", Map, CommandUtils.MakePathSafeToUseWithCommandLine(ServerLogFile));
		}

		if (ServerParams.UsePak(SC.StageTargetPlatform) || ServerParams.SignedPak)
		{
			if (ServerParams.SignedPak)
			{
				Args += " -signedpak";
			}
			else
			{
				Args += " -pak";
			}
		}
		if (IsBuildMachine || Params.Unattended)
		{
			Args += " -buildmachine";
		}
		Args += " -CrashForUAT";
		Args += " " + AdditionalCommandLine;


		if (ServerParams.Cook && ServerPlatform == UnrealTargetPlatform.Linux && !String.IsNullOrEmpty(ServerParams.ServerDeviceAddress))
		{
			Args += String.Format(" 2>&1 > {0}", ServerLogFile);
		}

		PushDir(Path.GetDirectoryName(ServerApp));
		var Result = Run(ServerApp, Args, null, ERunOptions.AllowSpew | ERunOptions.NoWaitForExit | ERunOptions.AppMustExist | ERunOptions.NoStdOutRedirect);
		PopDir();

		return Result;
	}
	private static void SetupClientParams(List<DeploymentContext> DeployContextList, ProjectParams Params, string ClientLogFile, out ERunOptions ClientRunFlags, out string ClientApp, out string ClientCmdLine)
	{
		if (Params.ClientTargetPlatforms.Count == 0)
		{
			throw new AutomationException("No ClientTargetPlatform set for SetupClientParams.");
		}

		//		var DeployContextList = CreateDeploymentContext(Params, false);

		if (DeployContextList.Count == 0)
		{
			throw new AutomationException("No DeployContextList for SetupClientParams.");
		}

		var SC = DeployContextList[0];

		// Get client app name and command line.
		ClientRunFlags = ERunOptions.AllowSpew | ERunOptions.AppMustExist;
		ClientApp = "";
		ClientCmdLine = "";
		string TempCmdLine = "";
		var PlatformName = Params.ClientTargetPlatforms[0].ToString();
		if (Params.Cook || Params.CookOnTheFly)
		{
			List<string> Exes = SC.StageTargetPlatform.GetExecutableNames(SC, true);
			ClientApp = Exes[0];
			if (SC.StageTargetPlatform.PlatformType != UnrealTargetPlatform.IOS)
			{
				TempCmdLine += SC.ProjectArgForCommandLines + " ";
			}
			TempCmdLine += Params.MapToRun + " ";

			if (Params.CookOnTheFly || Params.FileServer)
			{
				TempCmdLine += "-filehostip=";
				bool FirstParam = true;
				if (UnrealBuildTool.BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac)
				{
					NetworkInterface[] Interfaces = NetworkInterface.GetAllNetworkInterfaces();
					foreach (NetworkInterface adapter in Interfaces)
					{
						if (adapter.NetworkInterfaceType != NetworkInterfaceType.Loopback)
						{
							IPInterfaceProperties IP = adapter.GetIPProperties();
							for (int Index = 0; Index < IP.UnicastAddresses.Count; ++Index)
							{
								if (IP.UnicastAddresses[Index].IsDnsEligible && IP.UnicastAddresses[Index].Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
								{
									if (!IsNullOrEmpty(Params.Port))
									{
										foreach (var Port in Params.Port)
										{
											if (!FirstParam)
											{
												TempCmdLine += "+";
											}
											FirstParam = false;
											string[] PortProtocol = Port.Split(new char[] { ':' });
											if (PortProtocol.Length > 1)
											{
												TempCmdLine += String.Format("{0}://{1}:{2}", PortProtocol[0], IP.UnicastAddresses[Index].Address.ToString(), PortProtocol[1]);
											}
											else
											{
												TempCmdLine += IP.UnicastAddresses[Index].Address.ToString();
												TempCmdLine += ":";
												TempCmdLine += Params.Port;
											}
										}
									}
                                    else
                                    {
										if (!FirstParam)
										{
											TempCmdLine += "+";
										}
										FirstParam = false;
										
										// use default port
                                        TempCmdLine += IP.UnicastAddresses[Index].Address.ToString();
                                    }
								}
							}
						}
					}
				}
				else
				{
					NetworkInterface[] Interfaces = NetworkInterface.GetAllNetworkInterfaces();
					foreach (NetworkInterface adapter in Interfaces)
					{
						if (adapter.OperationalStatus == OperationalStatus.Up)
						{
							IPInterfaceProperties IP = adapter.GetIPProperties();
							for (int Index = 0; Index < IP.UnicastAddresses.Count; ++Index)
							{
								if (IP.UnicastAddresses[Index].IsDnsEligible)
								{
									if (!IsNullOrEmpty(Params.Port))
									{
										foreach (var Port in Params.Port)
										{
											if (!FirstParam)
											{
												TempCmdLine += "+";
											}
											FirstParam = false;
											string[] PortProtocol = Port.Split(new char[] { ':' });
											if (PortProtocol.Length > 1)
											{
												TempCmdLine += String.Format("{0}://{1}:{2}", PortProtocol[0], IP.UnicastAddresses[Index].Address.ToString(), PortProtocol[1]);
											}
											else
											{
												TempCmdLine += IP.UnicastAddresses[Index].Address.ToString();
												TempCmdLine += ":";
												TempCmdLine += Params.Port;
											}
										}
									}
                                    else
                                    {
										if (!FirstParam)
										{
											TempCmdLine += "+";
										}
										FirstParam = false;
										
										// use default port
                                        TempCmdLine += IP.UnicastAddresses[Index].Address.ToString();
                                    }
								}
							}
						}
					}
				}

				const string LocalHost = "127.0.0.1";

				if (!IsNullOrEmpty(Params.Port))
				{
					foreach (var Port in Params.Port)
					{
						if (!FirstParam)
						{
							TempCmdLine += "+";
						}
						FirstParam = false;
						string[] PortProtocol = Port.Split(new char[] { ':' });
						if (PortProtocol.Length > 1)
						{
							TempCmdLine += String.Format("{0}://{1}:{2}", PortProtocol[0], LocalHost, PortProtocol[1]);
						}
						else
						{
							TempCmdLine += LocalHost;
							TempCmdLine += ":";
							TempCmdLine += Params.Port;
						}

					}
				}
                else
                {
					if (!FirstParam)
					{
						TempCmdLine += "+";
					}
					FirstParam = false;
					
					// use default port
                    TempCmdLine += LocalHost;
                }
				TempCmdLine += " ";

				if (Params.CookOnTheFlyStreaming)
				{
					TempCmdLine += "-streaming ";
				}
				else if (SC.StageTargetPlatform.PlatformType != UnrealTargetPlatform.IOS)
				{
					// per josh, allowcaching is deprecated/doesn't make sense for iOS.
					TempCmdLine += "-allowcaching ";
				}
			}
			else if (Params.UsePak(SC.StageTargetPlatform) || Params.SignedPak)
			{
				if (Params.SignedPak)
				{
					TempCmdLine += "-signedpak ";
				}
				else
				{
					TempCmdLine += "-pak ";
				}
			}
			else if (!Params.Stage)
			{
				var SandboxPath = CombinePaths(SC.RuntimeProjectRootDir, "Saved", "Cooked", SC.CookPlatform);
				if (!SC.StageTargetPlatform.LaunchViaUFE)
				{
					TempCmdLine += "-sandbox=" + CommandUtils.MakePathSafeToUseWithCommandLine(SandboxPath) + " ";
				}
				else
				{
					TempCmdLine += "-sandbox=\'" + SandboxPath + "\' ";
				}
			}
		}
		else
		{
			ClientApp = CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries", PlatformName, "UE4Editor.exe");
			TempCmdLine += SC.ProjectArgForCommandLines + " ";
			if (!Params.EditorTest)
			{
				TempCmdLine += "-game " + Params.MapToRun + " ";
			}
		}
		if (Params.LogWindow)
		{
			// Without NoStdOutRedirect '-log' doesn't log anything to the window
			ClientRunFlags |= ERunOptions.NoStdOutRedirect;
			TempCmdLine += "-log ";
		}
		else
		{
			TempCmdLine += "-stdout ";
		}
		if (Params.Unattended)
		{
			TempCmdLine += "-unattended ";
		}
		if (IsBuildMachine || Params.Unattended)
		{
			TempCmdLine += "-buildmachine ";
		}
		if (Params.CrashIndex > 0)
		{
			int RealIndex = Params.CrashIndex - 1;
			if (RealIndex < 0 || RealIndex >= CrashCommands.Count())
			{
				throw new AutomationException("CrashIndex {0} is out of range...max={1}", Params.CrashIndex, CrashCommands.Count());
			}
			TempCmdLine += String.Format("-execcmds=\"debug {0}\" ", CrashCommands[RealIndex]);
		}
		else if (Params.RunAutomationTest != "")
		{
			TempCmdLine += "-execcmds=\"automation list;runtests " + Params.RunAutomationTest + "\" ";
		}
		else if (Params.RunAutomationTests)
		{
			TempCmdLine += "-execcmds=\"automation list;runall\" ";
		}
		if (SC.StageTargetPlatform.UseAbsLog)
		{
			TempCmdLine += "-abslog=" + CommandUtils.MakePathSafeToUseWithCommandLine(ClientLogFile) + " ";
		}
		if (SC.StageTargetPlatform.PlatformType != UnrealTargetPlatform.IOS)
		{
			TempCmdLine += "-Messaging -nomcp -Windowed ";
		}
		else
		{
			// skip arguments which don't make sense for iOS
			TempCmdLine += "-Messaging -nomcp ";
		}
		if (Params.NullRHI && SC.StageTargetPlatform.PlatformType != UnrealTargetPlatform.Mac) // all macs have GPUs, and currently the mac dies with nullrhi
		{
			TempCmdLine += "-nullrhi ";
		}
		if (Params.Deploy && SC.StageTargetPlatform.PlatformType == UnrealTargetPlatform.PS4)
		{
			TempCmdLine += "-deployedbuild ";
		}

		TempCmdLine += "-CrashForUAT ";
		TempCmdLine += Params.RunCommandline;

		// todo: move this into the platform
		if (SC.StageTargetPlatform.LaunchViaUFE)
		{
			ClientCmdLine = "-run=Launch ";
			ClientCmdLine += "-Device=" + Params.Device + " ";
			ClientCmdLine += "-Exe=\"" + ClientApp + "\" ";
			ClientCmdLine += "-Targetplatform=" + Params.ClientTargetPlatforms[0].ToString() + " ";
			ClientCmdLine += "-Params=\"" + TempCmdLine + "\"";
			ClientApp = CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/Win64/UnrealFrontend.exe");

			LogConsole("Launching via UFE:");
			LogConsole("\tClientCmdLine: " + ClientCmdLine + "");
		}
		else
		{
			ClientCmdLine = TempCmdLine;
		}
	}
    public static void CreateStagingManifest(ProjectParams Params, DeploymentContext SC)
    {
        if (!Params.Stage)
        {
            return;
        }
        var ThisPlatform = SC.StageTargetPlatform;

        ThisPlatform.GetFilesToDeployOrStage(Params, SC);

        // Get the build.properties file
        // this file needs to be treated as a UFS file for casing, but NonUFS for being put into the .pak file
        // @todo: Maybe there should be a new category - UFSNotForPak
        string BuildPropertiesPath = CombinePaths(SC.LocalRoot, "Engine/Build");
        if (SC.StageTargetPlatform.DeployLowerCaseFilenames(true))
        {
            BuildPropertiesPath = BuildPropertiesPath.ToLower();
        }
        SC.StageFiles(StagedFileType.NonUFS, BuildPropertiesPath, "build.properties", false, null, null, true);

        // move the UE4Commandline.txt file to the root of the stage
        // this file needs to be treated as a UFS file for casing, but NonUFS for being put into the .pak file
        // @todo: Maybe there should be a new category - UFSNotForPak
        string CommandLineFile = "UE4CommandLine.txt";
        if (SC.StageTargetPlatform.DeployLowerCaseFilenames(true))
        {
            CommandLineFile = CommandLineFile.ToLower();
        }
        SC.StageFiles(StagedFileType.NonUFS, GetIntermediateCommandlineDir(SC), CommandLineFile, false, null, "", true, false);

        if (!Params.CookOnTheFly && !Params.SkipCookOnTheFly) // only stage the UFS files if we are not using cook on the fly
        {
            ConfigCacheIni PlatformGameConfig = new ConfigCacheIni(SC.StageTargetPlatform.PlatformType, "Game", CommandUtils.GetDirectoryName(Params.RawProjectPath));

            // Initialize cultures to stage.
            List<string> CulturesToStage = null;

            // Use parameters if provided.
            if (Params.CulturesToCook != null && Params.CulturesToCook.Count > 0)
            {
                CulturesToStage = Params.CulturesToCook;
            }

            // Use configuration if otherwise lacking cultures to stage.
            if (CulturesToStage == null || CulturesToStage.Count == 0)
            {
                if (PlatformGameConfig != null)
                {
                    PlatformGameConfig.GetArray("/Script/UnrealEd.ProjectPackagingSettings", "CulturesToStage", out CulturesToStage);
                }
            }

            // Error if no cultures have been provided.
            if (CulturesToStage == null || CulturesToStage.Count == 0)
            {
                throw new AutomationException("No cultures were specified for cooking and packaging. This will lead to fatal errors when launching. Specify culture codes via commandline (-CookCultures=) or using project packaging settings (+CulturesToStage).");
            }

            // Engine ufs (content)
            SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.LocalRoot, "Engine/Config"), "*", true, null, null, false, !Params.UsePak(SC.StageTargetPlatform)); // TODO: Exclude localization data generation config files.

            if (Params.bUsesSlate)
            {
                if (Params.bUsesSlateEditorStyle)
                {
                    SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.LocalRoot, "Engine/Content/Editor/Slate"), "*", true, null, null, false, !Params.UsePak(SC.StageTargetPlatform));
                }
                SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.LocalRoot, "Engine/Content/Slate"), "*", true, null, null, false, !Params.UsePak(SC.StageTargetPlatform));
                SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.ProjectRoot, "Content/Slate"), "*", true, null, CombinePaths(SC.RelativeProjectRootForStage, "Content/Slate"), true, !Params.UsePak(SC.StageTargetPlatform));
            }
            foreach (string Culture in CulturesToStage)
            {
                StageLocalizationDataForCulture(SC, Culture, CombinePaths(SC.LocalRoot, "Engine/Content/Localization/Engine"), null, !Params.UsePak(SC.StageTargetPlatform));
            }
            SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.LocalRoot, "Engine/Plugins"), "*.uplugin", true, null, null, true, !Params.UsePak(SC.StageTargetPlatform));

            // Game ufs (content)

            SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.ProjectRoot), "*.uproject", false, null, CombinePaths(SC.RelativeProjectRootForStage), true, !Params.UsePak(SC.StageTargetPlatform));
            SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.ProjectRoot, "Config"), "*", true, null, CombinePaths(SC.RelativeProjectRootForStage, "Config"), true, !Params.UsePak(SC.StageTargetPlatform)); // TODO: Exclude localization data generation config files.
            SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.ProjectRoot, "Plugins"), "*.uplugin", true, null, null, true, !Params.UsePak(SC.StageTargetPlatform));
            foreach (string Culture in CulturesToStage)
            {
                StageLocalizationDataForCulture(SC, Culture, CombinePaths(SC.ProjectRoot, "Content/Localization/Game"), CombinePaths(SC.RelativeProjectRootForStage, "Content/Localization/Game"), !Params.UsePak(SC.StageTargetPlatform));
            }

            // Stage any additional UFS and NonUFS paths specified in the project ini files; these dirs are relative to the game content directory
            if (PlatformGameConfig != null)
            {
                var ProjectContentRoot = CombinePaths(SC.ProjectRoot, "Content");
                var StageContentRoot = CombinePaths(SC.RelativeProjectRootForStage, "Content");
                List<string> ExtraUFSDirs;
                if (PlatformGameConfig.GetArray("/Script/UnrealEd.ProjectPackagingSettings", "DirectoriesToAlwaysStageAsUFS", out ExtraUFSDirs))
                {
                    // Each string has the format '(Path="TheDirToStage")'
                    foreach (var PathStr in ExtraUFSDirs)
                    {
                        var PathParts = PathStr.Split('"');
                        if (PathParts.Length == 3)
                        {
                            var RelativePath = PathParts[1];
                            SC.StageFiles(StagedFileType.UFS, CombinePaths(ProjectContentRoot, RelativePath), "*", true, null, CombinePaths(StageContentRoot, RelativePath), true, !Params.UsePak(SC.StageTargetPlatform));
                        }
                    }
                }

                List<string> ExtraNonUFSDirs;
                if (PlatformGameConfig.GetArray("/Script/UnrealEd.ProjectPackagingSettings", "DirectoriesToAlwaysStageAsNonUFS", out ExtraNonUFSDirs))
                {
                    // Each string has the format '(Path="TheDirToStage")'
                    foreach (var PathStr in ExtraNonUFSDirs)
                    {
                        var PathParts = PathStr.Split('"');
                        if (PathParts.Length == 3)
                        {
                            var RelativePath = PathParts[1];
                            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(ProjectContentRoot, RelativePath));
                        }
                    }
                }
            }

            StagedFileType StagedFileTypeForMovies = StagedFileType.NonUFS;
            if (Params.FileServer)
            {
                // UFS is required when using a file server
                StagedFileTypeForMovies = StagedFileType.UFS;
            }

            if (SC.StageTargetPlatform.StageMovies)
            {
                SC.StageFiles(StagedFileTypeForMovies, CombinePaths(SC.LocalRoot, "Engine/Content/Movies"), "*", true, null, CombinePaths(SC.RelativeProjectRootForStage, "Engine/Content/Movies"), true, !Params.UsePak(SC.StageTargetPlatform));
                SC.StageFiles(StagedFileTypeForMovies, CombinePaths(SC.ProjectRoot, "Content/Movies"), "*", true, null, CombinePaths(SC.RelativeProjectRootForStage, "Content/Movies"), true, !Params.UsePak(SC.StageTargetPlatform));
            }

            // eliminate the sand box
            SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.ProjectRoot, "Saved", "Cooked", SC.CookPlatform), "*", true, null, "", true, !Params.UsePak(SC.StageTargetPlatform));

            // CrashReportClient is a standalone slate app that does not look in the generated pak file, so it needs the Content/Slate and Shaders/StandaloneRenderer folders Non-UFS
            // @todo Make CrashReportClient more portable so we don't have to do this
            if (SC.bStageCrashReporter && UnrealBuildTool.UnrealBuildTool.PlatformSupportsCrashReporter(SC.StageTargetPlatform.PlatformType) && !SC.DedicatedServer)
            {
                //If the .dat file needs to be staged as NonUFS for non-Windows/Linux hosts we need to change the casing as we do with the build properties file above.
                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Content/Slate"));
                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Shaders/StandaloneRenderer"));

                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Content/Localization/ICU"));
                // Linux platform stages ICU in GetFilesToDeployOrStage(), accounting for the actual architecture
                if (SC.StageTargetPlatform.PlatformType == UnrealTargetPlatform.Win64 ||
                    SC.StageTargetPlatform.PlatformType == UnrealTargetPlatform.Win32 ||
                    SC.StageTargetPlatform.PlatformType == UnrealTargetPlatform.Mac)
                {
                    SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/ICU"));
                }

                // SSL libraries are only available for Win64 builds.
                // @see FPerforceSourceControlProvider::LoadSSLLibraries
                if (SC.StageTargetPlatform.PlatformType == UnrealTargetPlatform.Win64)
                {
                    SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/OpenSSL"));
                }
            }
        }
    }
    /// <summary>
    /// Deploy the application on the current platform
    /// </summary>
    /// <param name="Params"></param>
    /// <param name="SC"></param>
    public override void Deploy(ProjectParams Params, DeploymentContext SC)
    {
        if (!String.IsNullOrEmpty(Params.ServerDeviceAddress))
        {
            string sourcePath = CombinePaths(Params.BaseStageDirectory, GetCookPlatform(Params.DedicatedServer, false, ""));
            string destPath = Params.DeviceUsername + "@" + Params.ServerDeviceAddress + ":.";
            RunAndLog(CmdEnv, pscpPath, String.Format("-batch -i {0} -r {1} {2}", Params.DevicePassword, sourcePath, destPath));

            List<string> Exes = GetExecutableNames(SC);

            string binPath = CombinePaths(GetCookPlatform(Params.DedicatedServer, false, ""), SC.RelativeProjectRootForStage, "Binaries", SC.PlatformDir, Path.GetFileName(Exes[0])).Replace("\\", "/");
            string iconPath = CombinePaths(GetCookPlatform(Params.DedicatedServer, false, ""), SC.RelativeProjectRootForStage, SC.ShortProjectName + ".png").Replace("\\", "/");

            string DesiredGLVersion = "4.3";

            // Begin Bash Shell Script
            string script = String.Format(@"#!/bin/bash
        # Check for OpenGL4 support
        glarg=''
        if command -v glxinfo >/dev/null 2>&1 ; then
        export DISPLAY="":0""
        glversion=$(glxinfo | grep ""OpenGL version string:"" | sed 's/[^0-9.]*\([0-9.]*\).*/\1/')
        glmatch=$(echo -e ""$glversion\n{0}"" | sort -Vr | head -1)
        [[ ""$glmatch"" = ""$glversion"" ]] && glarg=' -opengl4'
        fi

        # Create .desktop file
        cat > $HOME/Desktop/{1}.desktop << EOF
        [Desktop Entry]
        Type=Application
        Name={2}
        Comment=UE4 Game
        Exec=$HOME/{3}{4}$glarg
        Icon=$HOME/{5}
        Terminal=false
        Categories=Game;
        EOF

        # Set permissions
        chmod 755 $HOME/{3}
        chmod 700 $HOME/Desktop/{1}.desktop", DesiredGLVersion, SC.ShortProjectName, SC.ShortProjectName, binPath, (Params.UsePak(SC.StageTargetPlatform) ? " -pak" : ""), iconPath);
            // End Bash Shell Script

            string scriptFile = Path.GetTempFileName();
            File.WriteAllText(scriptFile, script);
            RunAndLog(CmdEnv, plinkPath, String.Format("-ssh -t -batch -l {0} -i {1} {2} -m {3}", Params.DeviceUsername, Params.DevicePassword, Params.ServerDeviceAddress, scriptFile));
            File.Delete(scriptFile);
        }
    }
	public static void CreateStagingManifest(ProjectParams Params, DeploymentContext SC)
	{
		if (!Params.Stage)
		{
			return;
		}
		var ThisPlatform = SC.StageTargetPlatform;

		Log("Creating Staging Manifest...");

        if (Params.HasDLCName)
        {
            string DLCName = Params.DLCName;

            // Making a plugin, grab the binaries too
            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Plugins", DLCName), "*.uplugin", false, null, null, true);
            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Plugins", DLCName, "Binaries"), "libUE4-*.so", true, null, null, true);
            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Plugins", DLCName, "Binaries"), "UE4-*.dll", true, null, null, true);
            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Plugins", DLCName, "Binaries"), "libUE4Server-*.so", true, null, null, true);
            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Plugins", DLCName, "Binaries"), "UE4Server-*.dll", true, null, null, true);

            // Put all of the cooked dir into the staged dir
            string PlatformCookDir = CombinePaths(SC.ProjectRoot, "Plugins", DLCName, "Saved", "Cooked", SC.CookPlatform);
            string[] ExcludeWildCards = {"AssetRegistry.bin"};

            // Stage any loose files in the root folder
			SC.StageFiles(StagedFileType.UFS, PlatformCookDir, "*", false, ExcludeWildCards, SC.RelativeProjectRootForStage, true, !Params.UsePak(SC.StageTargetPlatform));

			// Stage each sub directory separately so that we can skip Engine if need be
			string[] SubDirs = CommandUtils.FindDirectories(true, "*", false, new string[] { PlatformCookDir });

            foreach (string SubDir in SubDirs)
            {
                // Dedicated server cook doesn't save shaders so no Engine dir is created
                if ((!SC.DedicatedServer) && (!Params.DLCIncludeEngineContent) && CommandUtils.GetLastDirectoryName(SubDir).Equals("Engine", StringComparison.InvariantCultureIgnoreCase))
                {
                    continue;
                }
				// SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.ProjectRoot, "Plugins", DLCName, "Saved", "Cooked", SC.CookPlatform), "*", true, new[] { CommandUtils.CombinePaths("Engine", "*") }, "", true, !Params.UsePak(SC.StageTargetPlatform));
				string MountPoint = SubDir.Substring(PlatformCookDir.Length);
				if ( MountPoint.StartsWith("\\") || MountPoint.StartsWith("/") )
				{
					MountPoint = MountPoint.Substring(1);
				}
				SC.StageFiles(StagedFileType.UFS, SubDir, "*", true, ExcludeWildCards, MountPoint, true, !Params.UsePak(SC.StageTargetPlatform));
				//SC.StageFiles(StagedFileType.UFS, SubDir, "*", true, ExcludeWildCards, SC.RelativeProjectRootForStage, true, !Params.UsePak(SC.StageTargetPlatform));
			}

            return;
        }


		ThisPlatform.GetFilesToDeployOrStage(Params, SC);


		// Stage any extra runtime dependencies from the receipts
		foreach(StageTarget Target in SC.StageTargets)
		{
			SC.StageRuntimeDependenciesFromReceipt(Target.Receipt, Target.RequireFilesExist, Params.UsePak(SC.StageTargetPlatform));
		}

		// Get the build.properties file
		// this file needs to be treated as a UFS file for casing, but NonUFS for being put into the .pak file
		// @todo: Maybe there should be a new category - UFSNotForPak
		string BuildPropertiesPath = CombinePaths(SC.LocalRoot, "Engine/Build");
		if (SC.StageTargetPlatform.DeployLowerCaseFilenames(true))
		{
			BuildPropertiesPath = BuildPropertiesPath.ToLowerInvariant();
		}
		SC.StageFiles(StagedFileType.NonUFS, BuildPropertiesPath, "Build.version", false, null, null, true);

		// move the UE4Commandline.txt file to the root of the stage
		// this file needs to be treated as a UFS file for casing, but NonUFS for being put into the .pak file
		// @todo: Maybe there should be a new category - UFSNotForPak
		string CommandLineFile = "UE4CommandLine.txt";
		if (SC.StageTargetPlatform.DeployLowerCaseFilenames(true))
		{
			CommandLineFile = CommandLineFile.ToLowerInvariant();
		}
		SC.StageFiles(StagedFileType.NonUFS, GetIntermediateCommandlineDir(SC), CommandLineFile, false, null, "", true, false);

        ConfigCacheIni PlatformGameConfig = ConfigCacheIni.CreateConfigCacheIni(SC.StageTargetPlatform.IniPlatformType, "Game", new DirectoryReference(CommandUtils.GetDirectoryName(Params.RawProjectPath.FullName)));
        var ProjectContentRoot = CombinePaths(SC.ProjectRoot, "Content");
        var StageContentRoot = CombinePaths(SC.RelativeProjectRootForStage, "Content");
        
        if (!Params.CookOnTheFly && !Params.SkipCookOnTheFly) // only stage the UFS files if we are not using cook on the fly
        {


            // Initialize internationalization preset.
            string InternationalizationPreset = null;

            // Use parameters if provided.
            if (string.IsNullOrEmpty(InternationalizationPreset))
            {
                InternationalizationPreset = Params.InternationalizationPreset;
            }

            // Use configuration if otherwise lacking an internationalization preset.
            if (string.IsNullOrEmpty(InternationalizationPreset))
            {
                if (PlatformGameConfig != null)
                {
                    PlatformGameConfig.GetString("/Script/UnrealEd.ProjectPackagingSettings", "InternationalizationPreset", out InternationalizationPreset);
                }
            }

            // Error if no preset has been provided.
            if (string.IsNullOrEmpty(InternationalizationPreset))
            {
                throw new AutomationException("No internationalization preset was specified for packaging. This will lead to fatal errors when launching. Specify preset via commandline (-I18NPreset=) or project packaging settings (InternationalizationPreset).");
            }

            // Initialize cultures to stage.
            List<string> CulturesToStage = null;

            // Use parameters if provided.
            if (Params.CulturesToCook != null && Params.CulturesToCook.Count > 0)
            {
                CulturesToStage = Params.CulturesToCook;
            }

            // Use configuration if otherwise lacking cultures to stage.
            if (CulturesToStage == null || CulturesToStage.Count == 0)
            {
                if (PlatformGameConfig != null)
                {
                    PlatformGameConfig.GetArray("/Script/UnrealEd.ProjectPackagingSettings", "CulturesToStage", out CulturesToStage);
                }
            }

            // Error if no cultures have been provided.
            if (CulturesToStage == null || CulturesToStage.Count == 0)
            {
                throw new AutomationException("No cultures were specified for cooking and packaging. This will lead to fatal errors when launching. Specify culture codes via commandline (-CookCultures=) or using project packaging settings (+CulturesToStage).");
            }

            // Stage ICU internationalization data from Engine.
            SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.LocalRoot, "Engine", "Content", "Internationalization", InternationalizationPreset), "*", true, null, CombinePaths("Engine", "Content", "Internationalization"), true, !Params.UsePak(SC.StageTargetPlatform));

            // Engine ufs (content)
            SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.LocalRoot, "Engine/Config"), "*", true, null, null, false, !Params.UsePak(SC.StageTargetPlatform)); // TODO: Exclude localization data generation config files.

            foreach (string Culture in CulturesToStage)
            {
                StageLocalizationDataForCulture(SC, Culture, CombinePaths(SC.LocalRoot, "Engine/Content/Localization/Engine"), null, !Params.UsePak(SC.StageTargetPlatform));
            }
			
            // Game ufs (content)
			SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.ProjectRoot), "*.uproject", false, null, CombinePaths(SC.RelativeProjectRootForStage), true, !Params.UsePak(SC.StageTargetPlatform));

			if (SC.StageTargetPlatform.PlatformType != UnrealTargetPlatform.HTML5 && SC.bUseWebsocketNetDriver)
			{
				var EngineIniPath = Path.Combine(SC.ProjectRoot, "Config", "DefaultEngine.ini");
				var IntermediateEngineIniDir = Path.Combine(GetIntermediateCommandlineDir(SC), SC.RelativeProjectRootForStage, "Config");
				Directory.CreateDirectory(IntermediateEngineIniDir);
				var IntermediateEngineIniPath = Path.Combine(IntermediateEngineIniDir, "DefaultEngine.ini");
				List<String> IniLines = new List<String>();
				if (File.Exists(EngineIniPath))
				{
					IniLines = File.ReadAllLines(EngineIniPath).ToList();
				}
				IniLines.Add("[/Script/Engine.GameEngine]");
				IniLines.Add("!NetDriverDefinitions=ClearArray");
				IniLines.Add("+NetDriverDefinitions=(DefName=\"GameNetDriver\", DriverClassName=\"/Script/HTML5Networking.WebSocketNetDriver\", DriverClassNameFallback=\"/Script/HTML5Networking.WebSocketNetDriver\")");
				File.WriteAllLines(IntermediateEngineIniPath, IniLines);
				SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.ProjectRoot, "Config"), "*", true, new string[] {"DefaultEngine.ini"}, CombinePaths(SC.RelativeProjectRootForStage, "Config"), true, !Params.UsePak(SC.StageTargetPlatform)); // TODO: Exclude localization data generation config files.
				SC.StageFiles(StagedFileType.UFS, IntermediateEngineIniDir, "*.ini", true, null, CombinePaths(SC.RelativeProjectRootForStage, "Config"), true, !Params.UsePak(SC.StageTargetPlatform)); // TODO: Exclude localization data generation config files.
			}
			else
			{
				SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.ProjectRoot, "Config"), "*", true, null, CombinePaths(SC.RelativeProjectRootForStage, "Config"), true, !Params.UsePak(SC.StageTargetPlatform)); // TODO: Exclude localization data generation config files.
			}

			// Stage all project localization targets
			{
				var ProjectLocRootDirectory = CombinePaths(SC.ProjectRoot, "Content/Localization");
				if (DirectoryExists(ProjectLocRootDirectory))
				{
					string[] ProjectLocTargetDirectories = CommandUtils.FindDirectories(true, "*", false, new string[] { ProjectLocRootDirectory });
					foreach (string ProjectLocTargetDirectory in ProjectLocTargetDirectories)
					{
						foreach (string Culture in CulturesToStage)
						{
							StageLocalizationDataForCulture(SC, Culture, ProjectLocTargetDirectory, null, !Params.UsePak(SC.StageTargetPlatform));
						}
					}
				}
			}

			// Stage all plugin localization targets
			{
				ProjectDescriptor Project = ProjectDescriptor.FromFile(SC.RawProjectPath.FullName);

				List<PluginInfo> AvailablePlugins = Plugins.ReadAvailablePlugins(new DirectoryReference(CombinePaths(SC.LocalRoot, "Engine")), new FileReference(CombinePaths(SC.ProjectRoot, Params.ShortProjectName + ".uproject")), Project.AdditionalPluginDirectories);
				foreach (var Plugin in AvailablePlugins)
				{
					if (!UProjectInfo.IsPluginEnabledForProject(Plugin, Project, SC.StageTargetPlatform.PlatformType, TargetRules.TargetType.Game) &&
						UProjectInfo.IsPluginEnabledForProject(Plugin, Project, SC.StageTargetPlatform.PlatformType, TargetRules.TargetType.Client))
					{
						// skip editor plugins
						continue;
					}

					if (Plugin.Descriptor.LocalizationTargets == null || Plugin.Descriptor.LocalizationTargets.Length == 0)
					{
						// skip plugins with no localization targets
						continue;
					}

					foreach (var LocalizationTarget in Plugin.Descriptor.LocalizationTargets)
					{
						if (LocalizationTarget.LoadingPolicy != LocalizationTargetDescriptorLoadingPolicy.Always && LocalizationTarget.LoadingPolicy != LocalizationTargetDescriptorLoadingPolicy.Game)
						{
							// skip targets not loaded by the game
							continue;
						}

						var PluginLocTargetDirectory = CombinePaths(Plugin.Directory.FullName, "Content", "Localization", LocalizationTarget.Name);
						if (DirectoryExists(PluginLocTargetDirectory))
						{
							foreach (string Culture in CulturesToStage)
							{
								StageLocalizationDataForCulture(SC, Culture, PluginLocTargetDirectory, null, !Params.UsePak(SC.StageTargetPlatform));
							}
						}
					}
				}
			}

            // Stage any additional UFS and NonUFS paths specified in the project ini files; these dirs are relative to the game content directory
            if (PlatformGameConfig != null)
            {
                List<string> ExtraUFSDirs;
                if (PlatformGameConfig.GetArray("/Script/UnrealEd.ProjectPackagingSettings", "DirectoriesToAlwaysStageAsUFS", out ExtraUFSDirs))
                {
                    // Each string has the format '(Path="TheDirToStage")'
                    foreach (var PathStr in ExtraUFSDirs)
                    {
                        var PathParts = PathStr.Split('"');
                        if (PathParts.Length == 3)
                        {
                            var RelativePath = PathParts[1];
                            SC.StageFiles(StagedFileType.UFS, CombinePaths(ProjectContentRoot, RelativePath), "*", true, new string[] { "*.uasset", "*.umap" }, CombinePaths(StageContentRoot, RelativePath), true, !Params.UsePak(SC.StageTargetPlatform));
                        }
                        else if (PathParts.Length == 1)
                        {
                            var RelativePath = PathParts[0];
                            SC.StageFiles(StagedFileType.UFS, CombinePaths(ProjectContentRoot, RelativePath), "*", true, new string[] { "*.uasset", "*.umap" }, CombinePaths(StageContentRoot, RelativePath), true, !Params.UsePak(SC.StageTargetPlatform));
                        }
                    }
                }

                List<string> ExtraNonUFSDirs;
                if (PlatformGameConfig.GetArray("/Script/UnrealEd.ProjectPackagingSettings", "DirectoriesToAlwaysStageAsNonUFS", out ExtraNonUFSDirs))
                {
                    // Each string has the format '(Path="TheDirToStage")'
					// NonUFS files are never in pak files and should always be remapped
                    foreach (var PathStr in ExtraNonUFSDirs)
                    {
						var PathParts = PathStr.Split('"');
						if (PathParts.Length == 3)
						{
							var RelativePath = PathParts[1];
							SC.StageFiles(StagedFileType.NonUFS, CombinePaths(ProjectContentRoot, RelativePath), "*", true, null, CombinePaths(StageContentRoot, RelativePath), true, true);
						}
						else if (PathParts.Length == 1)
						{
							var RelativePath = PathParts[0];
							SC.StageFiles(StagedFileType.NonUFS, CombinePaths(ProjectContentRoot, RelativePath), "*", true, null, CombinePaths(StageContentRoot, RelativePath), true, true);
						}
                    }
                }
            }

            StagedFileType StagedFileTypeForMovies = StagedFileType.NonUFS;
            if (Params.FileServer)
            {
                // UFS is required when using a file server
                StagedFileTypeForMovies = StagedFileType.UFS;
            }

            if (SC.StageTargetPlatform.StageMovies && !SC.DedicatedServer)
            {
                bool bRemap = (StagedFileTypeForMovies == StagedFileType.NonUFS);
				SC.StageFiles(StagedFileTypeForMovies, CombinePaths(SC.LocalRoot, "Engine/Content/Movies"), "*", true, new string[] { "*.uasset", "*.umap" }, CombinePaths(SC.RelativeProjectRootForStage, "Engine/Content/Movies"), true, bRemap);
                SC.StageFiles(StagedFileTypeForMovies, CombinePaths(SC.ProjectRoot, "Content/Movies"), "*", true, new string[] { "*.uasset", "*.umap" }, CombinePaths(SC.RelativeProjectRootForStage, "Content/Movies"), true, bRemap);
            }

            // eliminate the sand box
            SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.ProjectRoot, "Saved", "Cooked", SC.CookPlatform), "*", true, new string[] { "*.json" }, "", true, !Params.UsePak(SC.StageTargetPlatform));

            // CrashReportClient is a standalone slate app that does not look in the generated pak file, so it needs the Content/Slate and Shaders/StandaloneRenderer folders Non-UFS
            // @todo Make CrashReportClient more portable so we don't have to do this
            if (SC.bStageCrashReporter && UnrealBuildTool.UnrealBuildTool.PlatformSupportsCrashReporter(SC.StageTargetPlatform.PlatformType))
            {
                //If the .dat file needs to be staged as NonUFS for non-Windows/Linux hosts we need to change the casing as we do with the build properties file above.
                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Content/Slate"));
                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Shaders/StandaloneRenderer"));

                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine", "Content", "Internationalization", InternationalizationPreset), "*", true, null, CombinePaths("Engine", "Content", "Internationalization"), false, true);

                // Get the architecture in use
                string Architecture = Params.SpecifiedArchitecture;
                if (string.IsNullOrEmpty(Architecture))
                {
                    Architecture = "";
                    var BuildPlatform = UEBuildPlatform.GetBuildPlatform(SC.StageTargetPlatform.PlatformType, true);
                    if (BuildPlatform != null)
                    {
                        Architecture = BuildPlatform.CreateContext(Params.RawProjectPath).GetActiveArchitecture();
                    }
                }

                // Get the target receipt path for CrashReportClient
                DirectoryReference EngineDir = new DirectoryReference(CombinePaths(SC.LocalRoot, "Engine"));
                string ReceiptFileName = TargetReceipt.GetDefaultPath(EngineDir.FullName, "CrashReportClient", SC.StageTargetPlatform.PlatformType, UnrealTargetConfiguration.Shipping, Architecture);
                if (!File.Exists(ReceiptFileName))
                {
                    throw new AutomationException(ExitCode.Error_MissingExecutable, "Stage Failed. Missing receipt '{0}'. Check that this target has been built.", Path.GetFileName(ReceiptFileName));
                }

                // Read the receipt for this target
                TargetReceipt Receipt;
                if (!TargetReceipt.TryRead(ReceiptFileName, out Receipt))
                {
                    throw new AutomationException("Missing or invalid target receipt ({0})", ReceiptFileName);
                }

                // Stage any runtime dependencies for CrashReportClient
                Receipt.ExpandPathVariables(EngineDir, EngineDir);
                SC.StageRuntimeDependenciesFromReceipt(Receipt, true, Params.UsePak(SC.StageTargetPlatform));

				// Add config files.
				SC.StageFiles( StagedFileType.NonUFS, CombinePaths( SC.LocalRoot, "Engine/Programs/CrashReportClient/Config" ) );
			}
        }
        else
        {
            if (PlatformGameConfig != null)
            {
                List<string> ExtraNonUFSDirs;
                if (PlatformGameConfig.GetArray("/Script/UnrealEd.ProjectPackagingSettings", "DirectoriesToAlwaysStageAsNonUFS", out ExtraNonUFSDirs))
                {
                    // Each string has the format '(Path="TheDirToStage")'
                    foreach (var PathStr in ExtraNonUFSDirs)
                    {
                        var PathParts = PathStr.Split('"');
                        if (PathParts.Length == 3)
                        {
                            var RelativePath = PathParts[1];
                            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(ProjectContentRoot, RelativePath));
                        }
                        else if (PathParts.Length == 1)
                        {
                            var RelativePath = PathParts[0];
                            SC.StageFiles(StagedFileType.UFS, CombinePaths(ProjectContentRoot, RelativePath), "*", true, null, CombinePaths(StageContentRoot, RelativePath), true, !Params.UsePak(SC.StageTargetPlatform));
                        }
                    }
                }
            }
        }
	}
    public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC)
    {
        if (UnrealBuildTool.BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac)
        {
            // copy the icons/launch screens from the engine
            {
                string SourcePath = CombinePaths(SC.LocalRoot, "Engine", "Build", "IOS", "Resources", "Graphics");
                SC.StageFiles(StagedFileType.NonUFS, SourcePath, "*.png", false, null, "", true, false);
            }

            // copy any additional framework assets that will be needed at runtime
            {
                string SourcePath = CombinePaths( ( SC.IsCodeBasedProject ? SC.ProjectRoot : SC.LocalRoot + "\\Engine" ), "Intermediate", "IOS", "FrameworkAssets" );
                if ( Directory.Exists( SourcePath ) )
                {
                    SC.StageFiles( StagedFileType.NonUFS, SourcePath, "*.*", true, null, "", true, false );
                }
            }

            // copy the icons/launch screens from the game (may stomp the engine copies)
            {
                string SourcePath = CombinePaths(SC.ProjectRoot, "Build", "IOS", "Resources", "Graphics");
                SC.StageFiles(StagedFileType.NonUFS, SourcePath, "*.png", false, null, "", true, false);
            }

            // copy the plist (only if code signing, as it's protected by the code sign blob in the executable and can't be modified independently)
            if (GetCodeSignDesirability(Params))
            {
                string SourcePListFile = CombinePaths(SC.LocalRoot, "Engine", "Build", "IOS", "UE4Game-Info.plist");
                if (File.Exists(SC.ProjectRoot + "/Build/IOS/Info.plist"))
                {
                    SourcePListFile = CombinePaths(SC.ProjectRoot, "Build", "IOS", "Info.plist");
                }
                else if (File.Exists(SC.ProjectRoot + "/Build/IOS/" + SC.ShortProjectName + "-Info.plist"))
                {
                    SourcePListFile = CombinePaths(SC.ProjectRoot, "Build", "IOS", SC.ShortProjectName + "-Info.plist");
                }
                else if (Directory.Exists(SC.ProjectRoot + "/Build/IOS"))
                {
                    // look for any plist file
                    string[] Plists = Directory.GetFiles(SC.ProjectRoot + "/Build/IOS", "*.plist");
                    if (Plists.Length > 0)
                    {
                        SourcePListFile = Plists[0];
                    }
                }

                //@TODO: This is writing to the engine directory!
                string SourcePath = CombinePaths((SC.IsCodeBasedProject ? SC.ProjectRoot : SC.LocalRoot + "\\Engine"), "Intermediate", "IOS");
                string TargetPListFile = Path.Combine(SourcePath, (SC.IsCodeBasedProject ? SC.ShortProjectName : "UE4Game") + "-Info.plist");

                Dictionary<string, string> Replacements = new Dictionary<string, string>();
                Replacements.Add("${EXECUTABLE_NAME}", (SC.IsCodeBasedProject ? SC.ShortProjectName : "UE4Game"));
                Replacements.Add("${BUNDLE_IDENTIFIER}", SC.ShortProjectName.Replace("_", ""));
                CopyFileWithReplacements(SourcePListFile, TargetPListFile, Replacements);

                SC.StageFiles(StagedFileType.NonUFS, SourcePath, Path.GetFileName(TargetPListFile), false, null, "", false, false, "Info.plist");
            }
        }

        // copy the movies from the project
        {
            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Build/IOS/Resources/Movies"), "*", false, null, "", true, false);
            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Content/Movies"), "*", true, null, "", true, false);
        }

        // stage required icu files
        SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.LocalRoot, "Engine/Content/Localization/ICU"), "*", true, null, null, false, !Params.UsePak(SC.StageTargetPlatform));
    }
    public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC)
    {
        // Engine non-ufs (binaries)

        if (SC.bStageCrashReporter)
        {
            StageExecutable("exe", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir), "CrashReportClient.");
        }

        //todo we need to support shipping and test executables
        //todo this should all be partially based on UBT manifests and not hard coded
        //monolithic assumption
        StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/Ogg", SC.PlatformDir), "*.", true);
        StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/Vorbis", SC.PlatformDir), "*.", true);
        string PhysXVer = "VS" + WindowsPlatform.GetVisualStudioCompilerVersionName();
        string ApexVer = "VS" + WindowsPlatform.GetVisualStudioCompilerVersionName();
        string PhysXMaskForDebugConfiguration = Params.bDebugBuildsActuallyUseDebugCRT ? "*DEBUG*.*" : "*PROFILE*.*";
        if (SC.StageTargetConfigurations.Contains(UnrealTargetConfiguration.Debug) && !Params.Rocket)
        {
            StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/PhysX/APEX-1.3", SC.PlatformDir, ApexVer), PhysXMaskForDebugConfiguration, true);
            StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/PhysX/PhysX-3.3", SC.PlatformDir, PhysXVer), PhysXMaskForDebugConfiguration, true);
            StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/PhysX/PhysX-3.3", SC.PlatformDir, PhysXVer), "nvToolsExt*.", true);
        }
        if (SC.StageTargetConfigurations.Any(x => x != UnrealTargetConfiguration.Debug) || Params.Rocket)
        {
            StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/PhysX/APEX-1.3", SC.PlatformDir, ApexVer), "*.", true, new string[] { "*DEBUG*.*", "*CHECKED*.*" });
            StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/PhysX/PhysX-3.3", SC.PlatformDir, PhysXVer), "*.", true, new string[] { "*DEBUG*.*", "*CHECKED*.*" });
        }

        if (Params.bUsesSteam)
        {
            string SteamVersion = "Steamv130";

            // Check that the TPS directory exists. We don't distribute binaries for Steam in Rocket.
            if (Directory.Exists(CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/Steamworks/" + SteamVersion)))
            {
                if (SC.StageTargetPlatform.PlatformType == UnrealTargetPlatform.Win32)
                {
                    StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/Steamworks/" + SteamVersion, SC.PlatformDir), "steam_api.");
                    if (SC.DedicatedServer)
                    {
                        StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/Steamworks/" + SteamVersion, SC.PlatformDir), "steamclient.");
                        StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/Steamworks/" + SteamVersion, SC.PlatformDir), "tier0_s.");
                        StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/Steamworks/" + SteamVersion, SC.PlatformDir), "vstdlib_s.");
                    }
                }
                else
                {
                    StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/Steamworks/" + SteamVersion, SC.PlatformDir), "steam_api64.");
                    if (SC.DedicatedServer)
                    {
                        StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/Steamworks/" + SteamVersion, SC.PlatformDir), "steamclient64.");
                        StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/Steamworks/" + SteamVersion, SC.PlatformDir), "tier0_s64.");
                        StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/Steamworks/" + SteamVersion, SC.PlatformDir), "vstdlib_s64.");
                    }
                }
            }
        }

        // Copy the splash screen, windows specific
        SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Content/Splash"), "Splash.bmp", false, null, null, true);

        SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.LocalRoot, "Engine/Content/Localization/ICU"), "*", true, null, null, false, !Params.UsePak(SC.StageTargetPlatform));

        if (Params.StageNonMonolithic)
        {
            if (SC.DedicatedServer)
            {
                StageExecutable("exe", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir), "UE4Server.");
                StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir), "UE4Server-*.");
                StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Plugins"), "UE4Server-*.", true);
                StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.ProjectRoot, "Binaries", SC.PlatformDir), "UE4Server-*.");
                StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.ProjectRoot, "Plugins"), "UE4Server-*.", true);

                StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/ICU/icu4c-53_1", SC.PlatformDir, "VS2013"), "*.");
            }
            else
            {
                StageExecutable("exe", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir), "UE4.");
                StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir), "UE4-*.");
                StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Plugins"), "UE4-*.", true);
                StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.ProjectRoot, "Binaries", SC.PlatformDir), "UE4-*.");
                StageExecutable("dll", SC, CommandUtils.CombinePaths(SC.ProjectRoot, "Plugins"), "UE4-*.", true);
            }
        }
        else
        {
            List<string> Exes = GetExecutableNames(SC);

            // the first exe is the "main" one, the rest are marked as debug files
            StagedFileType WorkingFileType = StagedFileType.NonUFS;

            foreach (var Exe in Exes)
            {
                if (Exe.StartsWith(CombinePaths(SC.RuntimeProjectRootDir, "Binaries", SC.PlatformDir)))
                {
                    // remap the project root.
                    string SourceFile = CombinePaths(SC.ProjectRoot, "Binaries", SC.PlatformDir, Path.GetFileName(Exe));
                    StageExecutable("exe", SC, Path.GetDirectoryName(SourceFile), Path.GetFileNameWithoutExtension(SourceFile) + ".", true, null, CommandUtils.CombinePaths(SC.RelativeProjectRootForStage, "Binaries", SC.PlatformDir), false, WorkingFileType);
                    if(Exe == Exes[0])
                    {
                        StageBootstrapExecutable(SC, SourceFile, CombinePaths(SC.RelativeProjectRootForStage, "Binaries", SC.PlatformDir, Path.GetFileName(Exe)), "");
                    }
                }
                else if (Exe.StartsWith(CombinePaths(SC.RuntimeRootDir, "Engine/Binaries", SC.PlatformDir)))
                {
                    // keep it in the engine directory.
                    string SourceFile = CombinePaths(SC.LocalRoot, "Engine", "Binaries", SC.PlatformDir, Path.GetFileName(Exe));
                    StageExecutable("exe", SC, CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir), Path.GetFileNameWithoutExtension(SourceFile) + ".", true, null, null, false, WorkingFileType);
                    if(Exe == Exes[0])
                    {
                        StageBootstrapExecutable(SC, SourceFile, CombinePaths("Engine", "Binaries", SC.PlatformDir, Path.GetFileName(Exe)), String.Format("..\\..\\..\\{0}\\{0}.uproject", SC.ShortProjectName));
                    }
                }
                else
                {
                    throw new AutomationException("Can't stage the exe {0} because it doesn't start with {1} or {2}", Exe, CombinePaths(SC.RuntimeProjectRootDir, "Binaries", SC.PlatformDir), CombinePaths(SC.RuntimeRootDir, "Engine/Binaries", SC.PlatformDir));
                }
                // the first exe is the "main" one, the rest are marked as debug files
                WorkingFileType = StagedFileType.DebugNonUFS;
            }
        }
    }
    public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC)
    {
        if (SC.bStageCrashReporter)
        {
            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir), "CrashReportClient", false);
        }

        {
            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/ICU/icu4c-53_1/", SC.PlatformDir, "x86_64-unknown-linux-gnu"), Params.bDebugBuildsActuallyUseDebugCRT ? "*d.so*" : "*.so*", false, new[] { Params.bDebugBuildsActuallyUseDebugCRT ? "*.so*" : "*d.so*" }, CombinePaths("Engine/Binaries", SC.PlatformDir));
        }

        // assume that we always have to deploy Steam (FIXME: should be automatic)
        {
            string SteamVersion = "Steamv130";

            // Check if the Steam directory exists. We need it for Steam controller support, so we include it whenever we can.
            if (Directory.Exists(CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/Steamworks/" + SteamVersion)))
            {
                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/Steamworks/" + SteamVersion, SC.PlatformDir), "libsteam_api.so", false, null, CombinePaths("Engine/Binaries", SC.PlatformDir));
            }

            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Config"), "controller.vdf", false, null, CommandUtils.CombinePaths(SC.RelativeProjectRootForStage, "Saved/Config"));
            // copy optional perfcounters definition file
            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Config"), "PerfCounters.json", false, null, CommandUtils.CombinePaths(SC.RelativeProjectRootForStage, "Saved/Config"), true);
        }

        // assume that we always have to deploy OpenAL (FIXME: should be automatic)
        {
            SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/OpenAL/", SC.PlatformDir), "libopenal.so.1", false, null, CombinePaths("Engine/Binaries", SC.PlatformDir));
        }

        SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Content/Splash"), "Splash.bmp", false, null, null, true);
        SC.StageFiles(StagedFileType.UFS, CombinePaths(SC.LocalRoot, "Engine/Content/Localization/ICU"), "*", true, null, null, false, !Params.UsePak(SC.StageTargetPlatform));

        if (Params.StageNonMonolithic)
        {
            if (SC.DedicatedServer)
            {
                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir), "UE4Server");
                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir), "libUE4Server-*.so");
                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Plugins"), "libUE4Server-*.so", true, null, null, true);
                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Binaries", SC.PlatformDir), "libUE4Server-*.so");
                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Plugins"), "libUE4Server-*.so", true, null, null, true);
            }
            else
            {
                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir), "UE4");
                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir), "libUE4-*.so");
                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Plugins"), "libUE4-*.so", true, null, null, true);
                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Binaries", SC.PlatformDir), "libUE4-*.so");
                SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Plugins"), "libUE4-*.so", true, null, null, true);
            }
        }
        else
        {
            List<string> Exes = GetExecutableNames(SC);

            foreach (var Exe in Exes)
            {

                if (Exe.StartsWith(CombinePaths(SC.RuntimeProjectRootDir, "Binaries", SC.PlatformDir)))
                {
                    // remap the project root. For content-only projects, rename the executable to the project name.
                    if (!Params.IsCodeBasedProject && Exe == Exes[0])
                    {
                        SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Binaries", SC.PlatformDir), Path.GetFileNameWithoutExtension(Exe), true, null, CommandUtils.CombinePaths(SC.RelativeProjectRootForStage, "Binaries", SC.PlatformDir), false, true, SC.ShortProjectName);
                    }
                    else
                    {
                        SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Binaries", SC.PlatformDir), Path.GetFileNameWithoutExtension(Exe), true, null, CommandUtils.CombinePaths(SC.RelativeProjectRootForStage, "Binaries", SC.PlatformDir), false);
                    }
                }
                else if (Exe.StartsWith(CombinePaths(SC.RuntimeRootDir, "Engine/Binaries", SC.PlatformDir)))
                {
                    // Move the executable for content-only projects into the project directory, using the project name, so it can figure out the UProject to look for and is consistent with code projects.
                    if (!Params.IsCodeBasedProject && Exe == Exes[0])
                    {
                        SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir), Path.GetFileNameWithoutExtension(Exe), true, null, CommandUtils.CombinePaths(SC.RelativeProjectRootForStage, "Binaries", SC.PlatformDir), false, true, SC.ShortProjectName);
                    }
                    else
                    {
                        SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir), Path.GetFileNameWithoutExtension(Exe), true, null, null, false);
                    }
                }
                else
                {
                    throw new AutomationException("Can't stage the exe {0} because it doesn't start with {1} or {2}", Exe, CombinePaths(SC.RuntimeProjectRootDir, "Binaries", SC.PlatformDir), CombinePaths(SC.RuntimeRootDir, "Engine/Binaries", SC.PlatformDir));
                }
            }
        }
    }