From 792c82c2d4e325106ec374a319c44f4a1040c24e Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Thu, 20 Jan 2011 15:49:58 +1300 Subject: [PATCH] Automatically extract packages. Fix ra. --- OpenRA.Game/Game.cs | 7 + .../Widgets/Delegates/GameInitDelegate.cs | 175 ++++++++---------- OpenRA.Mods.RA/Widgets/GameInitInfoWidget.cs | 4 +- mods/cnc/chrome/gameinit.yaml | 6 +- mods/ra/chrome/mainmenu.yaml | 46 ----- mods/ra/mod.yaml | 1 + 6 files changed, 87 insertions(+), 152 deletions(-) diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index 2393f90062..b60a48795e 100755 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -100,6 +100,10 @@ namespace OpenRA return Widget.OpenWindow(widget, new Dictionary{{ "world", world }, { "orderManager", orderManager }, { "worldRenderer", worldRenderer }}); } + static object syncroot = new object(); + static Action tickActions = () => {}; + + public static void RunAfterTick(Action a) { lock(syncroot) tickActions += a; } static void Tick( OrderManager orderManager, Viewport viewPort ) { if (orderManager.Connection.ConnectionState != lastConnectionState) @@ -123,6 +127,9 @@ namespace OpenRA PerfHistory.items["batches"].Tick(); MasterServerQuery.Tick(); + Action a; + lock(syncroot) { a = tickActions; tickActions = () => {}; } + a(); } private static void Tick( OrderManager orderManager ) diff --git a/OpenRA.Mods.RA/Widgets/Delegates/GameInitDelegate.cs b/OpenRA.Mods.RA/Widgets/Delegates/GameInitDelegate.cs index 49eca025a1..3403dc24e5 100755 --- a/OpenRA.Mods.RA/Widgets/Delegates/GameInitDelegate.cs +++ b/OpenRA.Mods.RA/Widgets/Delegates/GameInitDelegate.cs @@ -32,6 +32,7 @@ namespace OpenRA.Mods.RA.Widgets.Delegates public GameInitDelegate([ObjectCreator.Param] Widget widget) { Info = (widget as GameInitInfoWidget); + Game.ConnectionStateChanged += orderManager => { Widget.CloseWindow(); @@ -72,7 +73,7 @@ namespace OpenRA.Mods.RA.Widgets.Delegates window.GetWidget("DOWNLOAD").OnMouseUp = mi => { ShowDownloadDialog(); return true; }; window.GetWidget("FROMCD").OnMouseUp = mi => { - SelectDisk(path => System.Console.WriteLine(path)); + PromptFilepathAsync("Select CD", "Select the {0} CD".F(Info.GameTitle), true, path => System.Console.WriteLine(path)); return true; }; @@ -84,53 +85,43 @@ namespace OpenRA.Mods.RA.Widgets.Delegates window = Widget.OpenWindow("INIT_DOWNLOAD"); var status = window.GetWidget("STATUS"); status.GetText = () => "Initializing..."; - - + var progress = window.GetWidget("PROGRESS"); // TODO: Download to a temp location or the support dir var file = Info.PackageName; - var progress = window.GetWidget("PROGRESS"); - - window.GetWidget("EXTRACT").OnMouseUp = mi => - { - if (ExtractZip(file, Info.PackagePath)) - ContinueLoading(Info); - return true; - }; - - - if (File.Exists(file)) - { - window.GetWidget("EXTRACT").IsVisible = () => true; - status.GetText = () => "Download Cached"; - progress.Percentage = 100; - } - else - { - var dl = DownloadUrl(Info.PackageURL, file, - (_,i) => { - status.GetText = () => "Downloading {1}/{2} kB ({0}%)".F(i.ProgressPercentage, i.BytesReceived/1024, i.TotalBytesToReceive/1024); - progress.Percentage = i.ProgressPercentage; - }, - (_,i) => { - if (i.Error != null) - { - ShowDownloadError(i.Error.Message); - } - else - { - status.GetText = () => "Download Complete"; - window.GetWidget("EXTRACT").IsVisible = () => true; - window.GetWidget("CANCEL").IsVisible = () => false; - } + var dl = DownloadUrl(Info.PackageURL, file, + (_,i) => { + status.GetText = () => "Downloading {1}/{2} kB ({0}%)".F(i.ProgressPercentage, i.BytesReceived/1024, i.TotalBytesToReceive/1024); + progress.Percentage = i.ProgressPercentage; + }, + (_,i) => { + if (i.Error != null) + { + ShowDownloadError(i.Error.Message); } - ); - window.GetWidget("CANCEL").IsVisible = () => true; - window.GetWidget("RETRY").IsVisible = () => true; - - window.GetWidget("CANCEL").OnMouseUp = mi => { dl.CancelAsync(); ShowInstallMethodDialog(); return true; }; - window.GetWidget("RETRY").OnMouseUp = mi => { dl.CancelAsync(); ShowDownloadDialog(); return true; }; - } + else + { + // 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));})); + } + } + ); + + window.GetWidget("CANCEL").OnMouseUp = mi => { dl.CancelAsync(); ShowInstallMethodDialog(); return true; }; + window.GetWidget("RETRY").OnMouseUp = mi => { dl.CancelAsync(); ShowDownloadDialog(); return true; }; } void ShowDownloadError(string e) @@ -140,69 +131,13 @@ namespace OpenRA.Mods.RA.Widgets.Delegates window.GetWidget("CANCEL").IsVisible = () => true; } - // TODO: This needs to live on a different process if we want to run it as root - public bool ExtractZip(string zipFile, string path) - { - if (!File.Exists(zipFile)) { ShowDownloadError("Download Corrupted"); return false; } - List extracted = new List(); - try - { - ZipEntry entry; - var z = new ZipInputStream(File.OpenRead(zipFile)); - while ((entry = z.GetNextEntry()) != null) - { - if (!entry.IsFile) continue; - if (!Directory.Exists(Path.Combine(path, Path.GetDirectoryName(entry.Name)))) - Directory.CreateDirectory(Path.Combine(path, Path.GetDirectoryName(entry.Name))); - - window.GetWidget("STATUS").GetText = () => "Status: Extracting {0}".F(entry.Name); - - var destPath = path + Path.DirectorySeparatorChar + entry.Name; - Console.WriteLine("Extracting to {0}",destPath); - extracted.Add(path); - using (var f = File.Create(destPath)) - { - int bufSize = 2048; - byte[] buf = new byte[bufSize]; - while ((bufSize = z.Read(buf, 0, buf.Length)) > 0) - f.Write(buf, 0, bufSize); - } - } - z.Close(); - } - catch (SharpZipBaseException) - { - foreach(var f in extracted) - File.Delete(f); - - ShowDownloadError("Download Corrupted"); - return false; - } - return true; - } - - void SelectDisk(Action withPath) - { - Process p = new Process(); - p.StartInfo.FileName = "OpenRA.Launcher.Mac/build/Release/OpenRA.app/Contents/MacOS/OpenRA"; - p.StartInfo.Arguments = "--filepicker --title \"Select CD\" --message \"Select the {0} CD\" --require-directory --button-text \"Select\"".F(Info.GameTitle); - p.StartInfo.UseShellExecute = false; - p.StartInfo.CreateNoWindow = true; - p.EnableRaisingEvents = true; - p.Exited += (_,e) => - { - withPath(p.StandardOutput.ReadToEnd()); - }; - p.Start(); - } - void ContinueLoading(Widget widget) { Game.LoadShellMap(); Widget.RootWidget.Children.Remove(widget); Widget.OpenWindow("MAINMENU_BG"); } - + public static WebClient DownloadUrl(string url, string path, DownloadProgressChangedEventHandler onProgress, AsyncCompletedEventHandler onComplete) { WebClient wc = new WebClient(); @@ -215,5 +150,43 @@ namespace OpenRA.Mods.RA.Widgets.Delegates Game.OnQuit += () => wc.CancelAsync(); return wc; } + + public static void ExtractZip(string zipFile, string path, Action parseOutput, Action onComplete) + { + Process p = new Process(); + p.StartInfo.FileName = "OpenRA.Utility.exe"; + p.StartInfo.Arguments = "\"--extract-zip={0},{1}\"".F(zipFile, path); + p.StartInfo.UseShellExecute = false; + p.StartInfo.CreateNoWindow = true; + p.StartInfo.RedirectStandardOutput = true; + p.Start(); + + 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(); + } + + public static void PromptFilepathAsync(string title, string message, bool directory, Action withPath) + { + Process p = new Process(); + p.StartInfo.FileName = "OpenRA.Launcher.Mac/build/Release/OpenRA.app/Contents/MacOS/OpenRA"; + 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.EnableRaisingEvents = true; + p.Exited += (_,e) => + { + withPath(p.StandardOutput.ReadToEnd()); + }; + p.Start(); + } } } diff --git a/OpenRA.Mods.RA/Widgets/GameInitInfoWidget.cs b/OpenRA.Mods.RA/Widgets/GameInitInfoWidget.cs index a801db36ae..7f3a095e54 100755 --- a/OpenRA.Mods.RA/Widgets/GameInitInfoWidget.cs +++ b/OpenRA.Mods.RA/Widgets/GameInitInfoWidget.cs @@ -9,6 +9,8 @@ #endregion using OpenRA.Widgets; +using System; +using OpenRA.Mods.RA.Widgets.Delegates; namespace OpenRA.Mods.RA.Widgets { @@ -19,7 +21,7 @@ namespace OpenRA.Mods.RA.Widgets public string PackageURL; public string PackageName; public string PackagePath; - + public override void DrawInner() {} } } \ No newline at end of file diff --git a/mods/cnc/chrome/gameinit.yaml b/mods/cnc/chrome/gameinit.yaml index f2589807b7..98b37f5a3a 100644 --- a/mods/cnc/chrome/gameinit.yaml +++ b/mods/cnc/chrome/gameinit.yaml @@ -2,10 +2,9 @@ GameInitInfo@INIT_SETUP: Id:INIT_SETUP TestFile: conquer.mix GameTitle: Command & Conquer -# PackageURL:http://open-ra.org/get-dependency.php?file=cnc-packages - PackageURL:http://localhost/~paul/cnc-packages.zip + PackageURL:http://open-ra.org/get-dependency.php?file=cnc-packages PackageName:cnc-packages.zip - PackagePath:mods/cnc/packages + PackagePath:cnc/packages/ Delegate:GameInitDelegate Background@INIT_CHOOSEINSTALL: @@ -105,7 +104,6 @@ Background@INIT_DOWNLOAD: Y:PARENT_BOTTOM - 45 Width:120 Height:25 - Visible: false Text:Cancel Bold:True Button@EXTRACT: diff --git a/mods/ra/chrome/mainmenu.yaml b/mods/ra/chrome/mainmenu.yaml index 5d45c8c731..737f3fb7d4 100644 --- a/mods/ra/chrome/mainmenu.yaml +++ b/mods/ra/chrome/mainmenu.yaml @@ -1,49 +1,3 @@ -Background@MAINMENU_INIT: - Id:MAINMENU_INIT - X:(WINDOW_RIGHT - WIDTH)/2 - Y:(WINDOW_BOTTOM - HEIGHT)/2 - Width:250 - Height:330 - Visible:true - Delegate:GameInitDelegate - Children: - GameInitInfo: - Id:INFO - TestFile: fakefile.mix - GameTitle: Red Alert - Label@MAINMENU_LABEL_TITLE: - Id:MAINMENU_LABEL_TITLE - X:0 - Y:20 - Width:250 - Height:25 - Text:Install Game Content - Align:Center - Bold:True - Button@INIT_DOWNLOAD: - Id:INIT_DOWNLOAD - X:45 - Y:70 - Width:160 - Height:25 - Text:Download - Bold:True - Button@INIT_FROMCD: - Id:INIT_FROMCD - X:45 - Y:110 - Width:160 - Height:25 - Text:From CD - Bold:True - Button@INIT_QUIT: - Id:INIT_QUIT - X:45 - Y:150 - Width:160 - Height:25 - Text:Quit - Bold:True Background@MAINMENU_BG: Id:MAINMENU_BG X:(WINDOW_RIGHT - WIDTH)/2 diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index 765270d658..ca23fe1d7f 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -51,6 +51,7 @@ Assemblies: mods/ra/OpenRA.Mods.RA.dll ChromeLayout: + mods/ra/chrome/gameinit.yaml mods/ra/chrome/ingame.yaml mods/ra/chrome/mainmenu.yaml mods/ra/chrome/videoplayer.yaml