diff --git a/OpenRA.Mods.RA/Widgets/Delegates/GameInitDelegate.cs b/OpenRA.Mods.RA/Widgets/Delegates/GameInitDelegate.cs index 2ad138e890..f9c466bff2 100755 --- a/OpenRA.Mods.RA/Widgets/Delegates/GameInitDelegate.cs +++ b/OpenRA.Mods.RA/Widgets/Delegates/GameInitDelegate.cs @@ -18,6 +18,7 @@ using System; using System.Net; using System.ComponentModel; using System.IO; +using System.Threading; namespace OpenRA.Mods.RA.Widgets.Delegates { @@ -69,22 +70,64 @@ namespace OpenRA.Mods.RA.Widgets.Delegates { window = Widget.OpenWindow("INIT_CHOOSEINSTALL"); window.GetWidget("DOWNLOAD").OnMouseUp = mi => { ShowDownloadDialog(); return true; }; - window.GetWidget("FROMCD").OnMouseUp = mi => - { - PromptFilepathAsync("Select CD", "Select the {0} CD".F(Info.GameTitle), true, path => System.Console.WriteLine(path)); - return true; - }; + window.GetWidget("FROMCD").OnMouseUp = mi => PromptForCD(); window.GetWidget("QUIT").OnMouseUp = mi => { Game.Exit(); return true; }; } + bool PromptForCD() + { + PromptFilepathAsync("Select CD", "Select the {0} CD".F(Info.GameTitle), true, path => + { + if (!string.IsNullOrEmpty(path)) + Game.RunAfterTick(() => InstallFromCD(path)); + }); + return true; + } + + void InstallFromCD(string path) + { + window = Widget.OpenWindow("INIT_COPY"); + var status = window.GetWidget("STATUS"); + var progress = window.GetWidget("PROGRESS"); + + // TODO: Handle cancelling copy + // TODO: Make the progress bar indeterminate + window.GetWidget("CANCEL").OnMouseUp = mi => { ShowInstallMethodDialog(); return true; }; + window.GetWidget("RETRY").OnMouseUp = mi => PromptForCD(); + window.GetWidget("CANCEL").IsVisible = () => false; + + status.GetText = () => "Copying..."; + var error = false; + Action parseOutput = s => + { + if (s.Substring(0,5) == "Error") + { + error = true; + ShowDownloadError(s); + } + if (s.Substring(0,6) == "Status") + window.GetWidget("STATUS").GetText = () => s.Substring(7).Trim(); + }; + + Action onComplete = () => + { + if (!error) + Game.RunAfterTick(() => ContinueLoading(Info)); + }; + + if (Info.InstallMode == "ra") + CopyRAFiles(path, parseOutput, onComplete); + else + ShowDownloadError("Installing from CD not supported"); + } + void ShowDownloadDialog() { - window = Widget.OpenWindow("INIT_DOWNLOAD"); + window = Widget.OpenWindow("INIT_DOWNLOAD"); var status = window.GetWidget("STATUS"); status.GetText = () => "Initializing..."; var progress = window.GetWidget("PROGRESS"); - // Save the package to a temp file var file = Path.GetTempPath() + Path.DirectorySeparatorChar + Path.GetRandomFileName(); Action onDownloadChange = i => @@ -102,18 +145,24 @@ namespace OpenRA.Mods.RA.Widgets.Delegates // Automatically extract status.GetText = () => "Extracting..."; var error = false; - Game.RunAfterTick(() => ExtractZip(file, Info.PackagePath, - s => - { - if (s.Substring(0,5) == "Error") - { - error = true; - ShowDownloadError(s); - } - if (s.Substring(0,6) == "Status") - window.GetWidget("STATUS").GetText = () => s.Substring(7).Trim(); - }, - () => {if (!error) Game.RunAfterTick(() => ContinueLoading(Info));})); + Action parseOutput = s => + { + if (s.Substring(0,5) == "Error") + { + error = true; + ShowDownloadError(s); + } + if (s.Substring(0,6) == "Status") + window.GetWidget("STATUS").GetText = () => s.Substring(7).Trim(); + }; + + Action onComplete = () => + { + if (!error) + Game.RunAfterTick(() => ContinueLoading(Info)); + }; + + Game.RunAfterTick(() => ExtractZip(file, Info.PackagePath, parseOutput, onComplete)); } }; @@ -188,6 +237,35 @@ namespace OpenRA.Mods.RA.Widgets.Delegates onComplete(); } + public static void CopyRAFiles(string cdPath, Action parseOutput, Action onComplete) + { + + Process p = new Process(); + p.StartInfo.FileName = "OpenRA.Utility.exe"; + p.StartInfo.Arguments = "\"--install-ra-packages={0}\"".F(cdPath); + p.StartInfo.UseShellExecute = false; + p.StartInfo.CreateNoWindow = true; + p.StartInfo.RedirectStandardOutput = true; + p.Start(); + + var t = new Thread( _ => + { + using (var reader = p.StandardOutput) + { + // This is wrong, chrisf knows why + while (!p.HasExited) + { + string s = reader.ReadLine(); + if (string.IsNullOrEmpty(s)) continue; + parseOutput(s); + } + } + onComplete(); + }) { IsBackground = true }; + t.Start(); + + } + public static void PromptFilepathAsync(string title, string message, bool directory, Action withPath) { Process p = new Process(); @@ -195,10 +273,11 @@ namespace OpenRA.Mods.RA.Widgets.Delegates p.StartInfo.Arguments = "--filepicker --title \"{0}\" --message \"{1}\" {2} --button-text \"Select\"".F(title, message, directory ? "--require-directory" : ""); p.StartInfo.UseShellExecute = false; p.StartInfo.CreateNoWindow = true; + p.StartInfo.RedirectStandardOutput = true; p.EnableRaisingEvents = true; p.Exited += (_,e) => { - withPath(p.StandardOutput.ReadToEnd()); + withPath(p.StandardOutput.ReadToEnd().Trim()); }; p.Start(); } diff --git a/OpenRA.Mods.RA/Widgets/GameInitInfoWidget.cs b/OpenRA.Mods.RA/Widgets/GameInitInfoWidget.cs index af23c32c5e..885d780f01 100755 --- a/OpenRA.Mods.RA/Widgets/GameInitInfoWidget.cs +++ b/OpenRA.Mods.RA/Widgets/GameInitInfoWidget.cs @@ -20,6 +20,7 @@ namespace OpenRA.Mods.RA.Widgets public string GameTitle; public string PackageURL; public string PackagePath; + public string InstallMode; public override void DrawInner() {} } diff --git a/mods/cnc/chrome/gameinit.yaml b/mods/cnc/chrome/gameinit.yaml index 708617861d..4cca7d4c2a 100644 --- a/mods/cnc/chrome/gameinit.yaml +++ b/mods/cnc/chrome/gameinit.yaml @@ -4,6 +4,7 @@ GameInitInfo@INIT_SETUP: GameTitle: Command & Conquer PackageURL:http://open-ra.org/get-dependency.php?file=cnc-packages PackagePath:cnc/packages/ + InstallMode:cnc Delegate:GameInitDelegate Background@INIT_CHOOSEINSTALL: @@ -33,7 +34,7 @@ Background@INIT_CHOOSEINSTALL: Y:70 Width:PARENT_RIGHT Height:25 - Text:Content can be downloaded automatically or installed from CD. + Text:Content can be downloaded, or copied from the install CD. Align:Center Button@DOWNLOAD: Id:DOWNLOAD @@ -113,4 +114,50 @@ Background@INIT_DOWNLOAD: Height:25 Visible: false Text:Extract + Bold:True + +Background@INIT_COPY: + Id:INIT_COPY + X:(WINDOW_RIGHT - WIDTH)/2 + Y:(WINDOW_BOTTOM - HEIGHT)/2 + Width:500 + Height:160 + Children: + Label@TITLE: + X:0 + Y:20 + Width:PARENT_RIGHT + Height:25 + Text:Copying C&C Content + Align:Center + Bold:True + ProgressBar@PROGRESS: + Id:PROGRESS + X:50 + Y:55 + Width:PARENT_RIGHT - 100 + Height:25 + Label@STATUS: + Id:STATUS + X:50 + Y:80 + Width:PARENT_RIGHT - 100 + Height:25 + Align:Left + Button@RETRY: + Id:RETRY + X:PARENT_RIGHT - 280 + Y:PARENT_BOTTOM - 45 + Width:120 + Height:25 + Visible: false + Text:Retry + Bold:True + Button@CANCEL: + Id:CANCEL + X:PARENT_RIGHT - 140 + Y:PARENT_BOTTOM - 45 + Width:120 + Height:25 + Text:Cancel Bold:True \ No newline at end of file diff --git a/mods/ra/chrome/gameinit.yaml b/mods/ra/chrome/gameinit.yaml index f520ee03e8..32feaff111 100644 --- a/mods/ra/chrome/gameinit.yaml +++ b/mods/ra/chrome/gameinit.yaml @@ -4,6 +4,7 @@ GameInitInfo@INIT_SETUP: GameTitle: Red Alert PackageURL:http://open-ra.org/get-dependency.php?file=ra-packages PackagePath:ra/packages/ + InstallMode:ra Delegate:GameInitDelegate Background@INIT_CHOOSEINSTALL: @@ -33,7 +34,7 @@ Background@INIT_CHOOSEINSTALL: Y:70 Width:PARENT_RIGHT Height:25 - Text:Content can be downloaded automatically or installed from CD. + Text:Content can be downloaded, or copied from the install CD. Align:Center Button@DOWNLOAD: Id:DOWNLOAD @@ -113,4 +114,50 @@ Background@INIT_DOWNLOAD: Height:25 Visible: false Text:Extract + Bold:True + +Background@INIT_COPY: + Id:INIT_COPY + X:(WINDOW_RIGHT - WIDTH)/2 + Y:(WINDOW_BOTTOM - HEIGHT)/2 + Width:500 + Height:160 + Children: + Label@TITLE: + X:0 + Y:20 + Width:PARENT_RIGHT + Height:25 + Text:Copying Red Alert Content + Align:Center + Bold:True + ProgressBar@PROGRESS: + Id:PROGRESS + X:50 + Y:55 + Width:PARENT_RIGHT - 100 + Height:25 + Label@STATUS: + Id:STATUS + X:50 + Y:80 + Width:PARENT_RIGHT - 100 + Height:25 + Align:Left + Button@RETRY: + Id:RETRY + X:PARENT_RIGHT - 280 + Y:PARENT_BOTTOM - 45 + Width:120 + Height:25 + Visible: false + Text:Retry + Bold:True + Button@CANCEL: + Id:CANCEL + X:PARENT_RIGHT - 140 + Y:PARENT_BOTTOM - 45 + Width:120 + Height:25 + Text:Cancel Bold:True \ No newline at end of file