public override void Package(ProjectParams Params, DeploymentContext SC, int WorkingCL) { if (SC.StageTargetConfigurations.Count != 1) { throw new AutomationException(ExitCode.Error_OnlyOneTargetConfigurationSupported, "XXX is currently only able to package one target configuration at a time, but StageTargetConfigurations contained {0} configurations", SC.StageTargetConfigurations.Count); } string BatchPath = GetBatchPath(Params, SC); File.WriteAllText(BatchPath, string.Format("notepad {0}", Params.GetProjectExeForPlatform(UnrealTargetPlatform.XXX).ToString())); PrintRunTime(); }
// -------------------------------------------------------------------------------- // ArchiveCommand.Automation.cs public override void GetFilesToArchive(ProjectParams Params, DeploymentContext SC) { if (SC.StageTargetConfigurations.Count != 1) { throw new AutomationException("iOS is currently only able to package one target configuration at a time, but StageTargetConfigurations contained {0} configurations", SC.StageTargetConfigurations.Count); } // copy to archive directory string PackagePath = Path.Combine(Path.GetDirectoryName(Params.RawProjectPath.FullName), "Binaries", "HTML5"); string UE4GameBasename = Path.GetFileNameWithoutExtension(Params.GetProjectExeForPlatform(UnrealTargetPlatform.HTML5).ToString()); string ProjectBasename = Params.ShortProjectName; string ProjectConfiguration = Params.ClientConfigsToBuild[0].ToString(); if (ProjectConfiguration != "Development") { UE4GameBasename += "-HTML5-" + ProjectConfiguration; ProjectBasename += "-HTML5-" + ProjectConfiguration; } SC.ArchiveFiles(PackagePath, UE4GameBasename + ".wasm"); // MAIN game code SC.ArchiveFiles(PackagePath, UE4GameBasename + ".js"); // MAIN js file (emscripten) SC.ArchiveFiles(PackagePath, UE4GameBasename + ".js.symbols"); // symbols file SC.ArchiveFiles(PackagePath, "Utility.js"); // utilities SC.ArchiveFiles(PackagePath, ProjectBasename + ".data"); // DATA file SC.ArchiveFiles(PackagePath, ProjectBasename + ".data.js"); // DATA file js driver (emscripten) SC.ArchiveFiles(PackagePath, ProjectBasename + ".UE4.js"); // UE4 js file SC.ArchiveFiles(PackagePath, ProjectBasename + ".css"); // UE4 css file SC.ArchiveFiles(PackagePath, ProjectBasename + ".html"); // landing page. // Archive HTML5 Server and a Readme. SC.ArchiveFiles(CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/DotNET/"), "HTML5LaunchHelper.exe"); SC.ArchiveFiles(CombinePaths(CmdEnv.LocalRoot, "Engine/Build/HTML5/"), "Readme.txt"); SC.ArchiveFiles(PackagePath, "RunMacHTML5LaunchHelper.command"); SC.ArchiveFiles(PackagePath, ".htaccess"); if (Compressed) { SC.ArchiveFiles(PackagePath, UE4GameBasename + ".wasmgz"); SC.ArchiveFiles(PackagePath, UE4GameBasename + ".jsgz"); SC.ArchiveFiles(PackagePath, UE4GameBasename + ".js.symbolsgz"); SC.ArchiveFiles(PackagePath, "Utility.jsgz"); SC.ArchiveFiles(PackagePath, ProjectBasename + ".datagz"); SC.ArchiveFiles(PackagePath, ProjectBasename + ".data.jsgz"); SC.ArchiveFiles(PackagePath, ProjectBasename + ".UE4.jsgz"); SC.ArchiveFiles(PackagePath, ProjectBasename + ".cssgz"); } else { // nuke old compressed files to prevent using stale files File.Delete(UE4GameBasename + ".wasmgz"); File.Delete(UE4GameBasename + ".jsgz"); File.Delete(UE4GameBasename + ".js.symbolsgz"); File.Delete("Utility.jsgz"); File.Delete(ProjectBasename + ".datagz"); File.Delete(ProjectBasename + ".data.jsgz"); File.Delete(ProjectBasename + ".UE4.jsgz"); File.Delete(ProjectBasename + ".cssgz"); } if (HTMLPakAutomation.CanCreateMapPaks(Params)) { // find all paks. string[] Files = Directory.GetFiles(Path.Combine(PackagePath, Params.ShortProjectName), "*", SearchOption.AllDirectories); foreach (string PakFile in Files) { SC.ArchivedFiles.Add(PakFile, Path.GetFileName(PakFile)); } } UploadToS3(SC, ProjectBasename + ".html"); }
public override void Package(ProjectParams Params, DeploymentContext SC, int WorkingCL) { LogInformation("Package {0}", Params.RawProjectPath); LogInformation("Setting Emscripten SDK for packaging.."); HTML5SDKInfo.SetupEmscriptenTemp(); HTML5SDKInfo.SetUpEmscriptenConfigFile(); // ---------------------------------------- // ini configurations ConfigHierarchy ConfigCache = UnrealBuildTool.ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Params.RawProjectPath), UnrealTargetPlatform.HTML5); // Debug and Development builds are not compressed to: // - speed up iteration times // - ensure (IndexedDB) data are not cached/used // Shipping builds "can be": // - compressed // - (IndexedDB) cached string ProjectConfiguration = Params.ClientConfigsToBuild[0].ToString(); if (ProjectConfiguration == "Shipping") { ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "Compressed", out Compressed); ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableIndexedDB", out enableIndexedDB); } LogInformation("HTML5Platform.Automation: Compressed = " + Compressed); LogInformation("HTML5Platform.Automation: EnableIndexedDB = " + enableIndexedDB); // ---------------------------------------- // package directory string PackagePath = Path.Combine(Path.GetDirectoryName(Params.RawProjectPath.FullName), "Binaries", "HTML5"); if (!Directory.Exists(PackagePath)) { Directory.CreateDirectory(PackagePath); } string _ProjectNameExtra = ProjectConfiguration != "Development" ? "-HTML5-" + ProjectConfiguration : ""; string _ProjectFullpath = Params.GetProjectExeForPlatform(UnrealTargetPlatform.HTML5).ToString(); string _ProjectFilename = Path.GetFileNameWithoutExtension(_ProjectFullpath) + _ProjectNameExtra; string SrcUE4GameBasename = Path.Combine(Path.GetDirectoryName(_ProjectFullpath), _ProjectFilename); string UE4GameBasename = Path.Combine(PackagePath, _ProjectFilename); string ProjectBasename = Path.Combine(PackagePath, Params.ShortProjectName + _ProjectNameExtra); // ---------------------------------------- // packaging if (HTMLPakAutomation.CanCreateMapPaks(Params)) { HTMLPakAutomation PakAutomation = new HTMLPakAutomation(Params, SC); // Create Necessary Paks. PakAutomation.CreateEnginePak(); PakAutomation.CreateGamePak(); PakAutomation.CreateContentDirectoryPak(); // Create Emscripten Package from Necessary Paks. - This will be the VFS. PakAutomation.CreateEmscriptenDataPackage(PackagePath, ProjectBasename + ".data"); // Create All Map Paks which will be downloaded on the fly. PakAutomation.CreateMapPak(); // Create Delta Paks if setup. List <string> Paks = new List <string>(); ConfigCache.GetArray("/Script/HTML5PlatformEditor.HTML5TargetSettings", "LevelTransitions", out Paks); if (Paks != null) { foreach (var Pak in Paks) { var Matched = Regex.Matches(Pak, "\"[^\"]+\"", RegexOptions.IgnoreCase); string MapFrom = Path.GetFileNameWithoutExtension(Matched[0].ToString().Replace("\"", "")); string MapTo = Path.GetFileNameWithoutExtension(Matched[1].ToString().Replace("\"", "")); PakAutomation.CreateDeltaMapPaks(MapFrom, MapTo); } } } else { // we need to operate in the root string PythonPath = HTML5SDKInfo.Python(); string EmPackagerPath = HTML5SDKInfo.EmscriptenPackager(); using (new ScopedEnvVar("EM_CONFIG", HTML5SDKInfo.DOT_EMSCRIPTEN)) { using (new PushedDirectory(Path.Combine(Params.BaseStageDirectory, "HTML5"))) { string CmdLine = string.Format("\"{0}\" \"{1}\" --preload . --js-output=\"{1}.js\" --no-heap-copy", EmPackagerPath, ProjectBasename + ".data"); RunAndLog(CmdEnv, PythonPath, CmdLine); } } } // ---------------------------------------- // copy to package directory // ensure the ue4game binary exists, if applicable if (!FileExists_NoExceptions(SrcUE4GameBasename + ".js")) { LogInformation("Failed to find game application " + SrcUE4GameBasename + ".js"); throw new AutomationException(ExitCode.Error_MissingExecutable, "Stage Failed. Could not find application {0}. You may need to build the UE4 project with your target configuration and platform.", SrcUE4GameBasename + ".js"); } if (!Params.IsCodeBasedProject) { // template project - need to copy over UE4Game.* File.Copy(SrcUE4GameBasename + ".wasm", UE4GameBasename + ".wasm", true); File.Copy(SrcUE4GameBasename + ".js", UE4GameBasename + ".js", true); File.Copy(SrcUE4GameBasename + ".js.symbols", UE4GameBasename + ".js.symbols", true); File.SetAttributes(UE4GameBasename + ".wasm", FileAttributes.Normal); File.SetAttributes(UE4GameBasename + ".js", FileAttributes.Normal); File.SetAttributes(UE4GameBasename + ".js.symbols", FileAttributes.Normal); } // else, c++ projects will compile "to" PackagePath // note: ( ProjectBasename + ".data" ) already created above (!HTMLPakAutomation.CanCreateMapPaks()) // ---------------------------------------- // generate HTML files to the package directory // custom HTML, JS (if any), and CSS (if any) template files string LocalBuildPath = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/HTML5"); string BuildPath = Path.Combine(Path.GetDirectoryName(Params.RawProjectPath.FullName), "Build", "HTML5"); string TemplateFile = CombinePaths(BuildPath, "project_template.html"); if (!File.Exists(TemplateFile)) { // fall back to default UE4 template files BuildPath = LocalBuildPath; TemplateFile = CombinePaths(BuildPath, "project_template.html"); } GenerateFileFromTemplate(TemplateFile, ProjectBasename + ".html", Params, ConfigCache); TemplateFile = CombinePaths(BuildPath, "project_template.js"); if (File.Exists(TemplateFile)) { GenerateFileFromTemplate(TemplateFile, ProjectBasename + ".UE4.js", Params, ConfigCache); } TemplateFile = CombinePaths(BuildPath, "project_template.css"); if (File.Exists(TemplateFile)) { GenerateFileFromTemplate(TemplateFile, ProjectBasename + ".css", Params, ConfigCache); } // ---------------------------------------- // (development) support files string MacBashTemplateFile = CombinePaths(LocalBuildPath, "RunMacHTML5LaunchHelper_template.command"); string MacBashOutputFile = Path.Combine(PackagePath, "RunMacHTML5LaunchHelper.command"); string MonoPath = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/BatchFiles/Mac/SetupMono.sh"); GenerateMacCommandFromTemplate(MacBashTemplateFile, MacBashOutputFile, MonoPath); // ........................................ string htaccesspath = Path.Combine(PackagePath, ".htaccess"); if (File.Exists(htaccesspath)) { FileAttributes attributes = File.GetAttributes(htaccesspath); if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) { attributes &= ~FileAttributes.ReadOnly; File.SetAttributes(htaccesspath, attributes); } } File.Copy(CombinePaths(LocalBuildPath, "htaccess_template.txt"), htaccesspath, true); // ---------------------------------------- // final copies // Gather utlity .js files and combine into one file string DestinationFile = PackagePath + "/Utility.js"; File.Delete(DestinationFile); // spelling this out - one file at a time (i.e. don't slurp in project_template.js) File.AppendAllText(DestinationFile, File.ReadAllText(CombinePaths(LocalBuildPath, "json2.js"))); File.AppendAllText(DestinationFile, File.ReadAllText(CombinePaths(LocalBuildPath, "jstorage.js"))); File.AppendAllText(DestinationFile, File.ReadAllText(CombinePaths(LocalBuildPath, "moz_binarystring.js"))); if (Compressed) { LogInformation("Build configuration is " + ProjectConfiguration + ", so (gzip) compressing files for web servers."); // Compress all files. These are independent tasks which can be threaded. List <Task> CompressionTasks = new List <Task>(); CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(UE4GameBasename + ".wasm", UE4GameBasename + ".wasmgz"))); // main game code CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(UE4GameBasename + ".js", UE4GameBasename + ".jsgz"))); // main js (emscripten) CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(UE4GameBasename + ".js.symbols", UE4GameBasename + ".js.symbolsgz"))); // symbols fil. CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(PackagePath + "/Utility.js", PackagePath + "/Utility.jsgz"))); // Utility CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(ProjectBasename + ".data", ProjectBasename + ".datagz"))); // DATA file CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(ProjectBasename + ".data.js", ProjectBasename + ".data.jsgz"))); // DATA file .js driver (emscripten) if (File.Exists(ProjectBasename + ".UE4.js")) { CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(ProjectBasename + ".UE4.js", ProjectBasename + ".UE4.jsgz"))); // UE4 js } if (File.Exists(ProjectBasename + ".css")) { CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(ProjectBasename + ".css", ProjectBasename + ".cssgz"))); // UE4 css } Task.WaitAll(CompressionTasks.ToArray()); } else { LogInformation("Build configuration is " + ProjectConfiguration + ", so not compressing. Build Shipping configuration to compress files to save space."); // nuke old compressed files to prevent using stale files File.Delete(UE4GameBasename + ".wasmgz"); File.Delete(UE4GameBasename + ".jsgz"); File.Delete(UE4GameBasename + ".js.symbolsgz"); File.Delete(PackagePath + "/Utility.jsgz"); File.Delete(ProjectBasename + ".datagz"); File.Delete(ProjectBasename + ".data.jsgz"); File.Delete(ProjectBasename + ".UE4.jsgz"); File.Delete(ProjectBasename + ".cssgz"); } File.Copy(CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/DotNET/HTML5LaunchHelper.exe"), CombinePaths(PackagePath, "HTML5LaunchHelper.exe"), true); // Task.WaitAll(CompressionTasks); PrintRunTime(); }
public override void Package(ProjectParams Params, DeploymentContext SC, int WorkingCL) { LogInformation("Package {0}", Params.RawProjectPath); LogInformation("Setting Emscripten SDK for packaging.."); HTML5SDKInfo.SetupEmscriptenTemp(); HTML5SDKInfo.SetUpEmscriptenConfigFile(); string PackagePath = Path.Combine(Path.GetDirectoryName(Params.RawProjectPath.FullName), "Binaries", "HTML5"); if (!Directory.Exists(PackagePath)) { Directory.CreateDirectory(PackagePath); } // ini configurations var ConfigCache = UnrealBuildTool.ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Params.RawProjectPath), UnrealTargetPlatform.HTML5); bool targetWebGL1 = false; // inverted checked - this will be going away soon... if (ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "TargetWebGL1", out targetWebGL1)) { targetWebGL2 = !targetWebGL1; } // Debug and Development builds are not uncompressed to: // - speed up iteration times // - ensure (IndexedDB) data are not cached/used // Shipping builds "can be": // - compressed // - (IndexedDB) cached if (Params.ClientConfigsToBuild[0].ToString() == "Shipping") { ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "Compressed", out Compressed); ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableIndexedDB", out enableIndexedDB); } LogInformation("HTML5Platform.Automation: TargetWebGL2 = " + targetWebGL2); LogInformation("HTML5Platform.Automation: Compressed = " + Compressed); LogInformation("HTML5Platform.Automation: EnableIndexedDB = " + enableIndexedDB); string FinalDataLocation = Path.Combine(PackagePath, Params.ShortProjectName) + ".data"; if (HTMLPakAutomation.CanCreateMapPaks(Params)) { HTMLPakAutomation PakAutomation = new HTMLPakAutomation(Params, SC); // Create Necessary Paks. PakAutomation.CreateEnginePak(); PakAutomation.CreateGamePak(); PakAutomation.CreateContentDirectoryPak(); // Create Emscripten Package from Necessary Paks. - This will be the VFS. PakAutomation.CreateEmscriptenDataPackage(PackagePath, FinalDataLocation); // Create All Map Paks which will be downloaded on the fly. PakAutomation.CreateMapPak(); // Create Delta Paks if setup. List <string> Paks = new List <string>(); ConfigCache.GetArray("/Script/HTML5PlatformEditor.HTML5TargetSettings", "LevelTransitions", out Paks); if (Paks != null) { foreach (var Pak in Paks) { var Matched = Regex.Matches(Pak, "\"[^\"]+\"", RegexOptions.IgnoreCase); string MapFrom = Path.GetFileNameWithoutExtension(Matched[0].ToString().Replace("\"", "")); string MapTo = Path.GetFileNameWithoutExtension(Matched[1].ToString().Replace("\"", "")); PakAutomation.CreateDeltaMapPaks(MapFrom, MapTo); } } } else { // we need to operate in the root string PythonPath = HTML5SDKInfo.Python(); string PackagerPath = HTML5SDKInfo.EmscriptenPackager(); using (new ScopedEnvVar("EM_CONFIG", HTML5SDKInfo.DOT_EMSCRIPTEN)) { using (new PushedDirectory(Path.Combine(Params.BaseStageDirectory, "HTML5"))) { string CmdLine = string.Format("\"{0}\" \"{1}\" --preload . --js-output=\"{1}.js\" --no-heap-copy", PackagerPath, FinalDataLocation); RunAndLog(CmdEnv, PythonPath, CmdLine); } } } // copy the "Executable" to the package directory string ProjectGameExeFilename = Params.GetProjectExeForPlatform(UnrealTargetPlatform.HTML5).ToString(); string GameBasename = Path.GetFileNameWithoutExtension(ProjectGameExeFilename); if (Params.ClientConfigsToBuild[0].ToString() != "Development") { GameBasename += "-HTML5-" + Params.ClientConfigsToBuild[0].ToString(); } // no extension string GameBasepath = Path.GetDirectoryName(ProjectGameExeFilename); string FullGameBasePath = Path.Combine(GameBasepath, GameBasename); string FullPackageGameBasePath = Path.Combine(PackagePath, GameBasename); // with extension string GameExe = GameBasename + ".js"; string FullGameExePath = Path.Combine(GameBasepath, GameExe); string FullPackageGameExePath = Path.Combine(PackagePath, GameExe); // ensure the ue4game binary exists, if applicable if (!FileExists_NoExceptions(FullGameExePath)) { LogInformation("Failed to find game application " + FullGameExePath); throw new AutomationException(ExitCode.Error_MissingExecutable, "Stage Failed. Could not find application {0}. You may need to build the UE4 project with your target configuration and platform.", FullGameExePath); } if (FullGameExePath != FullPackageGameExePath) // TODO: remove this check { File.Copy(FullGameExePath + ".symbols", FullPackageGameExePath + ".symbols", true); File.Copy(FullGameBasePath + ".wasm", FullPackageGameBasePath + ".wasm", true); File.Copy(FullGameExePath, FullPackageGameExePath, true); } File.SetAttributes(FullPackageGameExePath + ".symbols", FileAttributes.Normal); File.SetAttributes(FullPackageGameBasePath + ".wasm", FileAttributes.Normal); File.SetAttributes(FullPackageGameExePath, FileAttributes.Normal); // put the HTML file to the package directory string TemplateFile = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/HTML5/GameX.html.template"); string OutputFile = Path.Combine(PackagePath, (Params.ClientConfigsToBuild[0].ToString() != "Development" ? (Params.ShortProjectName + "-HTML5-" + Params.ClientConfigsToBuild[0].ToString()) : Params.ShortProjectName)) + ".html"; string CanvasScaleMode; ConfigCache.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "CanvasScalingMode", out CanvasScaleMode); GenerateFileFromTemplate(TemplateFile, OutputFile, Params.ShortProjectName, Params.ClientConfigsToBuild[0].ToString(), // Params.StageCommandline, !Params.IsCodeBasedProject, HTML5SDKInfo.HeapSize(ConfigCache, Params.ClientConfigsToBuild[0].ToString()), CanvasScaleMode ); string MacBashTemplateFile = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/HTML5/RunMacHTML5LaunchHelper.command.template"); string MacBashOutputFile = Path.Combine(PackagePath, "RunMacHTML5LaunchHelper.command"); string MonoPath = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/BatchFiles/Mac/SetupMono.sh"); GenerateMacCommandFromTemplate(MacBashTemplateFile, MacBashOutputFile, MonoPath); string htaccessTemplate = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/HTML5/htaccess.template"); string htaccesspath = Path.Combine(PackagePath, ".htaccess"); if (File.Exists(htaccesspath)) { FileAttributes attributes = File.GetAttributes(htaccesspath); if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) { attributes &= ~FileAttributes.ReadOnly; File.SetAttributes(htaccesspath, attributes); } } File.Copy(htaccessTemplate, htaccesspath, true); string JSDir = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/HTML5"); string OutDir = PackagePath; // Gather utlity .js files and combine into one file string[] UtilityJavaScriptFiles = Directory.GetFiles(JSDir, "*.js"); string DestinationFile = OutDir + "/Utility.js"; File.Delete(DestinationFile); foreach (var UtilityFile in UtilityJavaScriptFiles) { string Data = File.ReadAllText(UtilityFile); File.AppendAllText(DestinationFile, Data); } if (Compressed) { LogInformation("Build configuration is " + Params.ClientConfigsToBuild[0].ToString() + ", so (gzip) compressing files for web servers."); // Compress all files. These are independent tasks which can be threaded. List <Task> CompressionTasks = new List <Task>(); // data file CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(FinalDataLocation, FinalDataLocation + "gz"))); // data file .js driver. CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(FinalDataLocation + ".js", FinalDataLocation + ".jsgz"))); // main game code CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(FullPackageGameBasePath + ".wasm", FullPackageGameBasePath + ".wasmgz"))); // main js. CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(FullPackageGameExePath, FullPackageGameExePath + "gz"))); // symbols file. CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(FullPackageGameExePath + ".symbols", FullPackageGameExePath + ".symbolsgz"))); // Utility CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(OutDir + "/Utility.js", OutDir + "/Utility.jsgz"))); Task.WaitAll(CompressionTasks.ToArray()); } else { LogInformation("Build configuration is " + Params.ClientConfigsToBuild[0].ToString() + ", so not compressing. Build Shipping configuration to compress files to save space."); // nuke old compressed files to prevent using stale files File.Delete(FinalDataLocation + "gz"); File.Delete(FinalDataLocation + ".jsgz"); File.Delete(FullPackageGameExePath + "gz"); File.Delete(FullPackageGameBasePath + ".wasmgz"); File.Delete(FullPackageGameExePath + ".symbolsgz"); File.Delete(OutDir + "/Utility.jsgz"); } File.Copy(CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/DotNET/HTML5LaunchHelper.exe"), CombinePaths(OutDir, "HTML5LaunchHelper.exe"), true); // Task.WaitAll(CompressionTasks); PrintRunTime(); }