Example #1
0
        private InstalledPlatformInfo()
        {
            List <string>  InstalledPlatforms;
            ConfigCacheIni Ini = ConfigCacheIni.CreateConfigCacheIni(UnrealTargetPlatform.Unknown, "Engine", (DirectoryReference)null);

            if (Ini.GetArray("InstalledPlatforms", "InstalledPlatformConfigurations", out InstalledPlatforms))
            {
                foreach (string InstalledPlatform in InstalledPlatforms)
                {
                    ParsePlatformConfiguration(InstalledPlatform);
                }
            }
        }
    public override void Package(ProjectParams Params, DeploymentContext SC, int WorkingCL)
    {
        Log("Package {0}", Params.RawProjectPath);

        Log("Setting Emscripten SDK for packaging..");
        HTML5SDKInfo.SetupEmscriptenTemp();
        HTML5SDKInfo.SetUpEmscriptenConfigFile();

        string PackagePath = Path.Combine(Path.GetDirectoryName(Params.RawProjectPath), "Binaries", "HTML5");
        if (!Directory.Exists(PackagePath))
        {
            Directory.CreateDirectory(PackagePath);
        }
        string FinalDataLocation = Path.Combine(PackagePath, Params.ShortProjectName) + ".data";

        var ConfigCache = new UnrealBuildTool.ConfigCacheIni(UnrealTargetPlatform.HTML5, "Engine", Path.GetDirectoryName(Params.RawProjectPath), CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine"));

        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\"", PackagerPath, FinalDataLocation);
                    RunAndLog(CmdEnv, PythonPath, CmdLine);
                }
            }
        }

        // copy the "Executable" to the package directory
        string GameExe = Path.GetFileNameWithoutExtension(Params.ProjectGameExeFilename);
        if (Params.ClientConfigsToBuild[0].ToString() != "Development")
        {
            GameExe += "-HTML5-" + Params.ClientConfigsToBuild[0].ToString();
        }
        GameExe += ".js";

        // ensure the ue4game binary exists, if applicable
        string FullGameExePath = Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe);
        if (!SC.IsCodeBasedProject && !FileExists_NoExceptions(FullGameExePath))
        {
            Log("Failed to find game application " + FullGameExePath);
            throw new AutomationException(ErrorCodes.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 (Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe) != Path.Combine(PackagePath, GameExe))
        {
            File.Copy(Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe), Path.Combine(PackagePath, GameExe), true);
            File.Copy(Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe) + ".mem", Path.Combine(PackagePath, GameExe) + ".mem", true);
            File.Copy(Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe) + ".symbols", Path.Combine(PackagePath, GameExe) + ".symbols", true);
        }

        File.SetAttributes(Path.Combine(PackagePath, GameExe), FileAttributes.Normal);
        File.SetAttributes(Path.Combine(PackagePath, GameExe) + ".mem", FileAttributes.Normal);
        File.SetAttributes(Path.Combine(PackagePath, GameExe) + ".symbols", FileAttributes.Normal);

        // put the HTML file to the package directory
        string TemplateFileName = "GameX.html.template";
        string TemplateFile = Path.Combine(CombinePaths(CmdEnv.LocalRoot, "Engine"), "Build", "HTML5", TemplateFileName);
        string OutputFile = Path.Combine(PackagePath, (Params.ClientConfigsToBuild[0].ToString() != "Development" ? (Params.ShortProjectName + "-HTML5-" + Params.ClientConfigsToBuild[0].ToString()) : Params.ShortProjectName)) + ".html";

        // find Heap Size.
        ulong HeapSize;

        int ConfigHeapSize = 0;
        // Valuer set by Editor UI
        var bGotHeapSize = ConfigCache.GetInt32("/Script/HTML5PlatformEditor.HTML5TargetSettings", "HeapSize" + Params.ClientConfigsToBuild[0].ToString(), out ConfigHeapSize);

        // Fallback if the previous method failed
        if (!bGotHeapSize && !ConfigCache.GetInt32("BuildSettings", "HeapSize" + Params.ClientConfigsToBuild[0].ToString(), out ConfigHeapSize)) // in Megs.
        {
            // we couldn't find a per config heap size, look for a common one.
            if (!ConfigCache.GetInt32("BuildSettings", "HeapSize", out ConfigHeapSize))
            {
                ConfigHeapSize = Params.IsCodeBasedProject ? 1024 : 512;
                Log("Could not find Heap Size setting in .ini for Client config {0}", Params.ClientConfigsToBuild[0].ToString());
            }
        }

        HeapSize = (ulong)ConfigHeapSize * 1024L * 1024L; // convert to bytes.
        Log("Setting Heap size to {0} Mb ", ConfigHeapSize);

        GenerateFileFromTemplate(TemplateFile, OutputFile, Params.ShortProjectName, Params.ClientConfigsToBuild[0].ToString(), Params.StageCommandline, !Params.IsCodeBasedProject, HeapSize);

        string MacBashTemplateFile = Path.Combine(CombinePaths(CmdEnv.LocalRoot, "Engine"), "Build", "HTML5", "RunMacHTML5LaunchHelper.command.template");
        string MacBashOutputFile = Path.Combine(PackagePath, "RunMacHTML5LaunchHelper.command");
        string MonoPath = Path.Combine(CombinePaths(CmdEnv.LocalRoot, "Engine"), "Build", "BatchFiles", "Mac", "SetupMono.sh");
        GenerateMacCommandFromTemplate(MacBashTemplateFile, MacBashOutputFile, MonoPath);

        string JSDir = Path.Combine(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";
        foreach( var UtilityFile in UtilityJavaScriptFiles)
        {
            string Data = File.ReadAllText(UtilityFile);
            File.AppendAllText(DestinationFile, Data);
        }

        // Compress all files. These are independent tasks which can be threaded.
        Task[] CompressionTasks = new Task[6];
        //data file.
        CompressionTasks[0] = Task.Factory.StartNew( () => CompressFile(FinalDataLocation, FinalDataLocation + ".gz"));
        // data file .js driver.
        CompressionTasks[1] = Task.Factory.StartNew( () => CompressFile(FinalDataLocation + ".js" , FinalDataLocation + ".js.gz"));
        // main js.
        CompressionTasks[2] = Task.Factory.StartNew(() => CompressFile(Path.Combine(PackagePath, GameExe), Path.Combine(PackagePath, GameExe) + ".gz"));
        // mem init file.
        CompressionTasks[3] = Task.Factory.StartNew(() => CompressFile(Path.Combine(PackagePath, GameExe) + ".mem", Path.Combine(PackagePath, GameExe) + ".mem.gz"));
        // symbols file.
        CompressionTasks[4] = Task.Factory.StartNew(() => CompressFile(Path.Combine(PackagePath, GameExe) + ".symbols", Path.Combine(PackagePath, GameExe) + ".symbols.gz"));
        // Utility
        CompressionTasks[5] = Task.Factory.StartNew(() => CompressFile(OutDir + "/Utility.js", OutDir + "/Utility.js.gz"));

        File.Copy(CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/DotNET/HTML5LaunchHelper.exe"),CombinePaths(OutDir, "HTML5LaunchHelper.exe"),true);
        Task.WaitAll(CompressionTasks);
        PrintRunTime();
    }
    public override ProcessResult RunClient(ERunOptions ClientRunFlags, string ClientApp, string ClientCmdLine, ProjectParams Params)
    {
        // look for browser
        var           ConfigCache = new UnrealBuildTool.ConfigCacheIni(UnrealTargetPlatform.HTML5, "Engine", Path.GetDirectoryName(Params.RawProjectPath), CombinePaths(CmdEnv.LocalRoot, "Engine"));
        bool          ok          = false;
        List <string> Devices;
        string        browserPath = "";
        string        DeviceName  = Params.Device.Split('@')[1];

        DeviceName = DeviceName.Substring(0, DeviceName.LastIndexOf(" on "));

        if (ConfigCache.GetArray("/Script/HTML5PlatformEditor.HTML5SDKSettings", "DeviceMap", out Devices))
        {
            foreach (var Dev in Devices)
            {
                var Matched = Regex.Match(Dev, "\\(DeviceName=\"(.*)\",DevicePath=\\(FilePath=\"(.*)\"\\)\\)", RegexOptions.IgnoreCase);
                if (Matched.Success && Matched.Groups[1].ToString() == DeviceName)
                {
                    browserPath = Matched.Groups[2].ToString();
                    ok          = true;
                    break;
                }
            }
        }

        if (!ok && HTML5SDKInfo.bAllowFallbackSDKSettings)
        {
            string DeviceSection;

            if (Utils.IsRunningOnMono)
            {
                DeviceSection = "HTML5DevicesMac";
            }
            else
            {
                DeviceSection = "HTML5DevicesWindows";
            }

            ok = ConfigCache.GetString(DeviceSection, DeviceName, out browserPath);
        }

        if (!ok)
        {
            throw new System.Exception("Incorrect browser configuration in HTML5Engine.ini ");
        }

        // open the webpage
        Int32 ServerPort = 8000;

        ConfigCache.GetInt32("/Script/HTML5PlatformEditor.HTML5TargetSettings", "DeployServerPort", out ServerPort);
        string WorkingDirectory = Path.GetDirectoryName(ClientApp);
        string url  = Path.GetFileName(ClientApp) + ".html";
        string args = "-m ";
        // Are we running via cook on the fly server?
        // find our http url - This is awkward because RunClient doesn't have real information that NFS is running or not.
        bool IsCookOnTheFly = false;

        // 9/24/2014 @fixme - All this is convoluted, clean up.
        // looks like cookonthefly commandline stopped adding protocol or the port :/ hard coding to DEFAULT_TCP_FILE_SERVING_PORT+1 (DEFAULT_HTTP_FILE_SERVING_PORT)
        // This will fail if the NFS server is started with a different port - we need to modify driver .cs script to pass in IP/Port data correctly.

        if (ClientCmdLine.Contains("filehostip"))
        {
            IsCookOnTheFly = true;
            url            = "http://127.0.0.1:41898/" + url;
        }

        if (IsCookOnTheFly)
        {
            url += "?cookonthefly=true";
        }
        else
        {
            url   = String.Format("http://127.0.0.1:{0}/{1}", ServerPort, url);
            args += String.Format("-h -s {0} ", ServerPort);
        }

        // Check HTML5LaunchHelper source for command line args
        var LowerBrowserPath = browserPath.ToLower();

        args += String.Format("-b \"{0}\" -p \"{1}\" -w \"{2}\" ", browserPath, HTML5SDKInfo.PythonPath(), WorkingDirectory);
        args += url + " ";
        var ProfileDirectory = Path.Combine(Utils.GetUserSettingDirectory(), "UE4_HTML5", "user");

        if (LowerBrowserPath.Contains("chrome"))
        {
            args += String.Format("--user-data-dir=\"{0}\" --enable-logging --no-first-run", Path.Combine(ProfileDirectory, "chrome"));
        }
        else if (LowerBrowserPath.Contains("firefox"))
        {
            args += String.Format("-no-remote -profile \"{0}\" -jsconsole", Path.Combine(ProfileDirectory, "firefox"));
        }
        //else if (browserPath.Contains("Safari")) {}

        var           LaunchHelperPath = CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/DotNET/HTML5LaunchHelper.exe");
        ProcessResult BrowserProcess   = Run(LaunchHelperPath, args, null, ClientRunFlags | ERunOptions.NoWaitForExit);

        return(BrowserProcess);
    }
	public override ProcessResult RunClient(ERunOptions ClientRunFlags, string ClientApp, string ClientCmdLine, ProjectParams Params)
	{
		// look for browser
		var ConfigCache = new UnrealBuildTool.ConfigCacheIni(UnrealTargetPlatform.HTML5, "Engine", Path.GetDirectoryName(Params.RawProjectPath), CombinePaths(CmdEnv.LocalRoot, "Engine"));
		bool ok = false;
		List<string> Devices;
		string browserPath = "";
		string DeviceName = Params.Device.Split('@')[1];
		DeviceName = DeviceName.Substring(0, DeviceName.LastIndexOf(" on "));

		if (ConfigCache.GetArray("/Script/HTML5PlatformEditor.HTML5SDKSettings", "DeviceMap", out Devices))
		{
			foreach (var Dev in Devices)
			{
				var Matched = Regex.Match(Dev, "\\(DeviceName=\"(.*)\",DevicePath=\\(FilePath=\"(.*)\"\\)\\)", RegexOptions.IgnoreCase);
				if (Matched.Success && Matched.Groups[1].ToString() == DeviceName)
				{
					browserPath = Matched.Groups[2].ToString();
					ok = true;
					break;
				}
			}
		}

		if (!ok && HTML5SDKInfo.bAllowFallbackSDKSettings)
		{
			string DeviceSection;

			if (Utils.IsRunningOnMono)
			{
				DeviceSection = "HTML5DevicesMac";
			}
			else
			{
				DeviceSection = "HTML5DevicesWindows";
			}

			ok = ConfigCache.GetString(DeviceSection, DeviceName, out browserPath);
		}

		if (!ok)
		{
			throw new System.Exception("Incorrect browser configuration in HTML5Engine.ini ");
		}

		// open the webpage
		Int32 ServerPort = 8000;
		ConfigCache.GetInt32("/Script/HTML5PlatformEditor.HTML5TargetSettings", "DeployServerPort", out ServerPort);
		string WorkingDirectory = Path.GetDirectoryName(ClientApp);
		string url = Path.GetFileName(ClientApp) +".html";
		// Are we running via cook on the fly server?
		// find our http url - This is awkward because RunClient doesn't have real information that NFS is running or not.
		bool IsCookOnTheFly = false;

		// 9/24/2014 @fixme - All this is convoluted, clean up.
		// looks like cookonthefly commandline stopped adding protocol or the port :/ hard coding to DEFAULT_TCP_FILE_SERVING_PORT+1 (DEFAULT_HTTP_FILE_SERVING_PORT)
		// This will fail if the NFS server is started with a different port - we need to modify driver .cs script to pass in IP/Port data correctly. 

		if (ClientCmdLine.Contains("filehostip"))
		{
			IsCookOnTheFly = true; 
			url = "http://127.0.0.1:41898/" + url; 
		}

		if (IsCookOnTheFly)
		{
			url += "?cookonthefly=true";
		}
		else
		{
			url = String.Format("http://{2}:{0}/{1}", ServerPort, url, Environment.MachineName);
		}

		// Check HTML5LaunchHelper source for command line args

		var LowerBrowserPath = browserPath.ToLower();
		var ProfileDirectory = Path.Combine(Utils.GetUserSettingDirectory(), "UE4_HTML5", "user");

		string BrowserCommandline = url; 

		if (LowerBrowserPath.Contains("chrome"))
		{
			BrowserCommandline  += "  " + String.Format("--user-data-dir=\"{0}\" --enable-logging --no-first-run", Path.Combine(ProfileDirectory, "chrome"));
		}
		else if (LowerBrowserPath.Contains("firefox"))
		{
			BrowserCommandline += "  " +  String.Format("-no-remote -profile \"{0}\"", Path.Combine(ProfileDirectory, "firefox"));
		}

		string LauncherArguments = string.Format( " -Browser=\"{0}\" + -BrowserCommandLine=\"{1}\" -ServerPort=\"{2}\" -ServerRoot=\"{3}\" ", new object[] { browserPath,BrowserCommandline,ServerPort,WorkingDirectory });

		var LaunchHelperPath = CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/DotNET/HTML5LaunchHelper.exe");
		ProcessResult BrowserProcess = Run(LaunchHelperPath, LauncherArguments, null, ClientRunFlags | ERunOptions.NoWaitForExit);
	
		return BrowserProcess;

	}
Example #5
0
    public override void Package(ProjectParams Params, DeploymentContext SC, int WorkingCL)
    {
        Log("Package {0}", Params.RawProjectPath);

        Log("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);
        }
        string FinalDataLocation = Path.Combine(PackagePath, Params.ShortProjectName) + ".data";

        var ConfigCache = new UnrealBuildTool.ConfigCacheIni(UnrealTargetPlatform.HTML5, "Engine", Path.GetDirectoryName(Params.RawProjectPath.FullName), CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine"));

        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\"", PackagerPath, FinalDataLocation);
                    RunAndLog(CmdEnv, PythonPath, CmdLine);
                }
            }
        }

        // copy the "Executable" to the package directory
        string GameExe = Path.GetFileNameWithoutExtension(Params.ProjectGameExeFilename);

        if (Params.ClientConfigsToBuild[0].ToString() != "Development")
        {
            GameExe += "-HTML5-" + Params.ClientConfigsToBuild[0].ToString();
        }
        GameExe += ".js";

        // ensure the ue4game binary exists, if applicable
        string FullGameExePath = Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe);

        if (!SC.IsCodeBasedProject && !FileExists_NoExceptions(FullGameExePath))
        {
            Log("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 (Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe) != Path.Combine(PackagePath, GameExe))
        {
            File.Copy(Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe), Path.Combine(PackagePath, GameExe), true);
            File.Copy(Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe) + ".mem", Path.Combine(PackagePath, GameExe) + ".mem", true);
            File.Copy(Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe) + ".symbols", Path.Combine(PackagePath, GameExe) + ".symbols", true);
        }

        File.SetAttributes(Path.Combine(PackagePath, GameExe), FileAttributes.Normal);
        File.SetAttributes(Path.Combine(PackagePath, GameExe) + ".mem", FileAttributes.Normal);
        File.SetAttributes(Path.Combine(PackagePath, GameExe) + ".symbols", FileAttributes.Normal);


        // put the HTML file to the package directory
        string TemplateFileName = "GameX.html.template";
        string TemplateFile     = Path.Combine(CombinePaths(CmdEnv.LocalRoot, "Engine"), "Build", "HTML5", TemplateFileName);
        string OutputFile       = Path.Combine(PackagePath, (Params.ClientConfigsToBuild[0].ToString() != "Development" ? (Params.ShortProjectName + "-HTML5-" + Params.ClientConfigsToBuild[0].ToString()) : Params.ShortProjectName)) + ".html";

        // find Heap Size.
        ulong HeapSize;

        int ConfigHeapSize = 0;
        // Valuer set by Editor UI
        var bGotHeapSize = ConfigCache.GetInt32("/Script/HTML5PlatformEditor.HTML5TargetSettings", "HeapSize" + Params.ClientConfigsToBuild[0].ToString(), out ConfigHeapSize);

        // Fallback if the previous method failed
        if (!bGotHeapSize && !ConfigCache.GetInt32("/Script/BuildSettings.BuildSettings", "HeapSize" + Params.ClientConfigsToBuild[0].ToString(), out ConfigHeapSize))         // in Megs.
        {
            // we couldn't find a per config heap size, look for a common one.
            if (!ConfigCache.GetInt32("/Script/BuildSettings.BuildSettings", "HeapSize", out ConfigHeapSize))
            {
                ConfigHeapSize = Params.IsCodeBasedProject ? 1024 : 512;
                Log("Could not find Heap Size setting in .ini for Client config {0}", Params.ClientConfigsToBuild[0].ToString());
            }
        }

        HeapSize = (ulong)ConfigHeapSize * 1024L * 1024L;         // convert to bytes.
        Log("Setting Heap size to {0} Mb ", ConfigHeapSize);


        GenerateFileFromTemplate(TemplateFile, OutputFile, Params.ShortProjectName, Params.ClientConfigsToBuild[0].ToString(), Params.StageCommandline, !Params.IsCodeBasedProject, HeapSize);

        string MacBashTemplateFile = Path.Combine(CombinePaths(CmdEnv.LocalRoot, "Engine"), "Build", "HTML5", "RunMacHTML5LaunchHelper.command.template");
        string MacBashOutputFile   = Path.Combine(PackagePath, "RunMacHTML5LaunchHelper.command");
        string MonoPath            = Path.Combine(CombinePaths(CmdEnv.LocalRoot, "Engine"), "Build", "BatchFiles", "Mac", "SetupMono.sh");

        GenerateMacCommandFromTemplate(MacBashTemplateFile, MacBashOutputFile, MonoPath);

        string htaccessTemplate = Path.Combine(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  = Path.Combine(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);
        }

        // Compress all files. These are independent tasks which can be threaded.
        Task[] CompressionTasks = new Task[6];
        //data file.
        CompressionTasks[0] = Task.Factory.StartNew(() => CompressFile(FinalDataLocation, FinalDataLocation + "gz"));
        // data file .js driver.
        CompressionTasks[1] = Task.Factory.StartNew(() => CompressFile(FinalDataLocation + ".js", FinalDataLocation + ".jsgz"));
        // main js.
        CompressionTasks[2] = Task.Factory.StartNew(() => CompressFile(Path.Combine(PackagePath, GameExe), Path.Combine(PackagePath, GameExe) + "gz"));
        // mem init file.
        CompressionTasks[3] = Task.Factory.StartNew(() => CompressFile(Path.Combine(PackagePath, GameExe) + ".mem", Path.Combine(PackagePath, GameExe) + ".memgz"));
        // symbols file.
        CompressionTasks[4] = Task.Factory.StartNew(() => CompressFile(Path.Combine(PackagePath, GameExe) + ".symbols", Path.Combine(PackagePath, GameExe) + ".symbolsgz"));
        // Utility
        CompressionTasks[5] = Task.Factory.StartNew(() => CompressFile(OutDir + "/Utility.js", OutDir + "/Utility.jsgz"));

        File.Copy(CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/DotNET/HTML5LaunchHelper.exe"), CombinePaths(OutDir, "HTML5LaunchHelper.exe"), true);
        Task.WaitAll(CompressionTasks);
        PrintRunTime();
    }
	public override void Package(ProjectParams Params, DeploymentContext SC, int WorkingCL)
	{
        Log("Package {0}", Params.RawProjectPath);
        
        string PackagePath = Path.Combine(Path.GetDirectoryName(Params.RawProjectPath), "Binaries", "HTML5");
        if (!Directory.Exists(PackagePath))
        {
            Directory.CreateDirectory(PackagePath);
        }
        string FinalDataLocation = Path.Combine(PackagePath, Params.ShortProjectName) + ".data";

        var ConfigCache = new UnrealBuildTool.ConfigCacheIni(UnrealTargetPlatform.HTML5, "Engine", Path.GetDirectoryName(Params.RawProjectPath), CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine"));

        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
            using (new PushedDirectory(Path.Combine(Params.BaseStageDirectory, "HTML5")))
            {
                string PythonPath = HTML5SDKInfo.PythonPath();
                string PackagerPath = HTML5SDKInfo.EmscriptenPackager();

                string CmdLine = string.Format("\"{0}\" \"{1}\" --preload . --js-output=\"{1}.js\"", PackagerPath, FinalDataLocation);
                RunAndLog(CmdEnv, PythonPath, CmdLine);
            }
        }

		// packaging created 2 files - .data.js and .data file. lets compress them.

		CompressFile(FinalDataLocation, FinalDataLocation);
		CompressFile(FinalDataLocation + ".js", FinalDataLocation + ".js.gz");
		File.Delete(FinalDataLocation + ".js");

        // copy the "Executable" to the package directory
        string GameExe = Path.GetFileNameWithoutExtension(Params.ProjectGameExeFilename);
        if (Params.ClientConfigsToBuild[0].ToString() != "Development")
        {
            GameExe += "-HTML5-" + Params.ClientConfigsToBuild[0].ToString();
        }
        GameExe += ".js";
			
        // ensure the ue4game binary exists, if applicable
        string FullGameExePath = Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe);
        if (!SC.IsCodeBasedProject && !FileExists_NoExceptions(FullGameExePath))
        {
	        Log("Failed to find game application " + FullGameExePath);
	        AutomationTool.ErrorReporter.Error("Stage Failed.", (int)AutomationTool.ErrorCodes.Error_MissingExecutable);
	        throw new AutomationException("Could not find application {0}. You may need to build the UE4 project with your target configuration and platform.", FullGameExePath);
        }

        if (Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe) != Path.Combine(PackagePath, GameExe))
        {
			// compress all javascript files in place. 
			Log("Compressing and Copying main js executable");
			CompressFile(FullGameExePath, Path.Combine(PackagePath, GameExe) + ".gz");
			Log("Compressing and copying memory Initialization file");
			CompressFile(Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe) + ".mem", (Path.Combine(PackagePath, GameExe) + ".mem"));
			File.Copy(Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe) + ".symbols", Path.Combine(PackagePath, GameExe) + ".symbols", true);
        }

		File.SetAttributes(Path.Combine(PackagePath, GameExe) + ".symbols", FileAttributes.Normal);

        // put the HTML file to the package directory

        bool UseExperimentalTemplate = false;
        ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "UseExperimentalTemplate", out UseExperimentalTemplate);
        string TemplateFileName = UseExperimentalTemplate ? "GameX.html.template" : "Game.html.template";

        string TemplateFile = Path.Combine(CombinePaths(CmdEnv.LocalRoot, "Engine"), "Build", "HTML5", TemplateFileName);
        string OutputFile = Path.Combine(PackagePath, (Params.ClientConfigsToBuild[0].ToString() != "Development" ? (Params.ShortProjectName + "-HTML5-" + Params.ClientConfigsToBuild[0].ToString()) : Params.ShortProjectName)) + ".html";

        // find Heap Size.
        ulong HeapSize;

        int ConfigHeapSize = 0;
        // Valuer set by Editor UI
        var bGotHeapSize = ConfigCache.GetInt32("/Script/HTML5PlatformEditor.HTML5TargetSettings", "HeapSize" + Params.ClientConfigsToBuild[0].ToString(), out ConfigHeapSize);

        // Fallback if the previous method failed
        if (!bGotHeapSize && !ConfigCache.GetInt32("BuildSettings", "HeapSize" + Params.ClientConfigsToBuild[0].ToString(), out ConfigHeapSize)) // in Megs.
        {
            // we couldn't find a per config heap size, look for a common one.
            if (!ConfigCache.GetInt32("BuildSettings", "HeapSize", out ConfigHeapSize))
            {
                ConfigHeapSize = Params.IsCodeBasedProject ? 1024 : 512;
                Log("Could not find Heap Size setting in .ini for Client config {0}", Params.ClientConfigsToBuild[0].ToString());
            }
        }

        HeapSize = (ulong)ConfigHeapSize * 1024L * 1024L; // convert to bytes.
        Log("Setting Heap size to {0} Mb ", ConfigHeapSize);


        GenerateFileFromTemplate(TemplateFile, OutputFile, Params.ShortProjectName, Params.ClientConfigsToBuild[0].ToString(), Params.StageCommandline, !Params.IsCodeBasedProject, HeapSize);

        string JSDir = Path.Combine(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";
		foreach( var UtilityFile in UtilityJavaScriptFiles)
		{
			string Data = File.ReadAllText(UtilityFile);
			File.AppendAllText(DestinationFile, Data);
		}

		CompressFile(DestinationFile, DestinationFile + ".gz");

		// delete uncompressed file.
		if (File.Exists(DestinationFile))
		{
			File.Delete(DestinationFile);
		}

        PrintRunTime();
	}
    public override void Package(ProjectParams Params, DeploymentContext SC, int WorkingCL)
    {
        Log("Package {0}", Params.RawProjectPath);

        string PackagePath = Path.Combine(Path.GetDirectoryName(Params.RawProjectPath), "Binaries", "HTML5");

        if (!Directory.Exists(PackagePath))
        {
            Directory.CreateDirectory(PackagePath);
        }
        string FinalDataLocation = Path.Combine(PackagePath, Params.ShortProjectName) + ".data";

        var ConfigCache = new UnrealBuildTool.ConfigCacheIni(UnrealTargetPlatform.HTML5, "Engine", Path.GetDirectoryName(Params.RawProjectPath), CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine"));

        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
            using (new PushedDirectory(Path.Combine(Params.BaseStageDirectory, "HTML5")))
            {
                string PythonPath   = HTML5SDKInfo.PythonPath();
                string PackagerPath = HTML5SDKInfo.EmscriptenPackager();

                string CmdLine = string.Format("\"{0}\" \"{1}\" --preload . --js-output=\"{1}.js\"", PackagerPath, FinalDataLocation);
                RunAndLog(CmdEnv, PythonPath, CmdLine);
            }
        }

        // copy the "Executable" to the package directory
        string GameExe = Path.GetFileNameWithoutExtension(Params.ProjectGameExeFilename);

        if (Params.ClientConfigsToBuild[0].ToString() != "Development")
        {
            GameExe += "-HTML5-" + Params.ClientConfigsToBuild[0].ToString();
        }
        GameExe += ".js";

        // ensure the ue4game binary exists, if applicable
        string FullGameExePath = Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe);

        if (!SC.IsCodeBasedProject && !FileExists_NoExceptions(FullGameExePath))
        {
            Log("Failed to find game application " + FullGameExePath);
            AutomationTool.ErrorReporter.Error("Stage Failed.", (int)AutomationTool.ErrorCodes.Error_MissingExecutable);
            throw new AutomationException("Could not find application {0}. You may need to build the UE4 project with your target configuration and platform.", FullGameExePath);
        }

        if (Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe) != Path.Combine(PackagePath, GameExe))
        {
            File.Copy(Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe), Path.Combine(PackagePath, GameExe), true);
            File.Copy(Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe) + ".mem", Path.Combine(PackagePath, GameExe) + ".mem", true);
            File.Copy(Path.Combine(Path.GetDirectoryName(Params.ProjectGameExeFilename), GameExe) + ".symbols", Path.Combine(PackagePath, GameExe) + ".symbols", true);
        }
        File.SetAttributes(Path.Combine(PackagePath, GameExe), FileAttributes.Normal);
        File.SetAttributes(Path.Combine(PackagePath, GameExe) + ".mem", FileAttributes.Normal);
        File.SetAttributes(Path.Combine(PackagePath, GameExe) + ".symbols", FileAttributes.Normal);


        // put the HTML file to the package directory

        bool UseExperimentalTemplate = false;

        ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "UseExperimentalTemplate", out UseExperimentalTemplate);
        string TemplateFileName = UseExperimentalTemplate ? "GameX.html.template" : "Game.html.template";

        string TemplateFile = Path.Combine(CombinePaths(CmdEnv.LocalRoot, "Engine"), "Build", "HTML5", TemplateFileName);
        string OutputFile   = Path.Combine(PackagePath, (Params.ClientConfigsToBuild[0].ToString() != "Development" ? (Params.ShortProjectName + "-HTML5-" + Params.ClientConfigsToBuild[0].ToString()) : Params.ShortProjectName)) + ".html";

        // find Heap Size.
        ulong HeapSize;

        int ConfigHeapSize = 0;
        // Valuer set by Editor UI
        var bGotHeapSize = ConfigCache.GetInt32("/Script/HTML5PlatformEditor.HTML5TargetSettings", "HeapSize" + Params.ClientConfigsToBuild[0].ToString(), out ConfigHeapSize);

        // Fallback if the previous method failed
        if (!bGotHeapSize && !ConfigCache.GetInt32("BuildSettings", "HeapSize" + Params.ClientConfigsToBuild[0].ToString(), out ConfigHeapSize)) // in Megs.
        {
            // we couldn't find a per config heap size, look for a common one.
            if (!ConfigCache.GetInt32("BuildSettings", "HeapSize", out ConfigHeapSize))
            {
                ConfigHeapSize = Params.IsCodeBasedProject ? 1024 : 512;
                Log("Could not find Heap Size setting in .ini for Client config {0}", Params.ClientConfigsToBuild[0].ToString());
            }
        }

        HeapSize = (ulong)ConfigHeapSize * 1024L * 1024L; // convert to bytes.
        Log("Setting Heap size to {0} Mb ", ConfigHeapSize);


        GenerateFileFromTemplate(TemplateFile, OutputFile, Params.ShortProjectName, Params.ClientConfigsToBuild[0].ToString(), Params.StageCommandline, !Params.IsCodeBasedProject, HeapSize);

        // copy the jstorage files to the binaries directory
        string JSDir  = Path.Combine(CombinePaths(CmdEnv.LocalRoot, "Engine"), "Build", "HTML5");
        string OutDir = PackagePath;

        File.Copy(JSDir + "/json2.js", OutDir + "/json2.js", true);
        File.SetAttributes(OutDir + "/json2.js", FileAttributes.Normal);
        File.Copy(JSDir + "/jStorage.js", OutDir + "/jStorage.js", true);
        File.SetAttributes(OutDir + "/jStorage.js", FileAttributes.Normal);
        File.Copy(JSDir + "/moz_binarystring.js", OutDir + "/moz_binarystring.js", true);
        File.SetAttributes(OutDir + "/moz_binarystring.js", FileAttributes.Normal);
        PrintRunTime();
    }