diff --git a/OpenRA.FileFormats/InstallUtils.cs b/OpenRA.FileFormats/InstallUtils.cs index 41b6fe926c..2ccb26e6b5 100644 --- a/OpenRA.FileFormats/InstallUtils.cs +++ b/OpenRA.FileFormats/InstallUtils.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using ICSharpCode.SharpZipLib; using ICSharpCode.SharpZipLib.Zip; @@ -26,6 +27,15 @@ namespace OpenRA.FileFormats if (e != null) yield return e; else break; } } + + public static string GetMountedDisk(string[] volumeNames) + { + var volumes = DriveInfo.GetDrives() + .Where(v => v.DriveType == DriveType.CDRom && v.IsReady) + .Select(v => v.RootDirectory.FullName); + + return volumes.FirstOrDefault(v => volumeNames.Contains(Path.GetFileName(v))); + } // TODO: The package should be mounted into its own context to avoid name collisions with installed files public static bool ExtractFromPackage(string srcPath, string package, string[] files, string destPath, Action onProgress, Action onError) diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncInstallFromCDLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/CncInstallFromCDLogic.cs index f58ad22efa..aba73ab5b6 100644 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncInstallFromCDLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/Logic/CncInstallFromCDLogic.cs @@ -24,6 +24,8 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic ProgressBarWidget progressBar; LabelWidget statusLabel; Action continueLoading; + ButtonWidget retryButton, backButton; + Widget installingContainer, insertDiskContainer; [ObjectCreator.UseCtor] public CncInstallFromCDLogic([ObjectCreator.Param] Widget widget, @@ -34,41 +36,43 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic progressBar = panel.GetWidget("PROGRESS_BAR"); statusLabel = panel.GetWidget("STATUS_LABEL"); - var backButton = panel.GetWidget("BACK_BUTTON"); + backButton = panel.GetWidget("BACK_BUTTON"); backButton.OnClick = Widget.CloseWindow; - backButton.IsVisible = () => false; - var retryButton = panel.GetWidget("RETRY_BUTTON"); - retryButton.OnClick = PromptForCD; - retryButton.IsVisible = () => false; + retryButton = panel.GetWidget("RETRY_BUTTON"); + retryButton.OnClick = CheckForDisk; - // TODO: Search obvious places (platform dependent) for CD - PromptForCD(); + installingContainer = panel.GetWidget("INSTALLING"); + insertDiskContainer = panel.GetWidget("INSERT_DISK"); + CheckForDisk(); } - void PromptForCD() + void CheckForDisk() { - if (Game.Settings.Graphics.Mode == WindowMode.Fullscreen) + var path = InstallUtils.GetMountedDisk(new [] { "GDI95", "NOD95" }); + + if (path != null) + Install(path); + else { - statusLabel.GetText = () => "Error: Installing from Fullscreen mode is not supported"; - panel.GetWidget("BACK_BUTTON").IsVisible = () => true; - return; + insertDiskContainer.IsVisible = () => true; + installingContainer.IsVisible = () => false; } - - progressBar.SetIndeterminate(true); - Game.Utilities.PromptFilepathAsync("Select CONQUER.MIX on the C&C CD", path => Game.RunAfterTick(() => Install(path))); } - void Install(string path) + void Install(string source) { + backButton.IsDisabled = () => true; + retryButton.IsDisabled = () => true; + insertDiskContainer.IsVisible = () => false; + installingContainer.IsVisible = () => true; + var dest = new string[] { Platform.SupportDir, "Content", "cnc" }.Aggregate(Path.Combine); var copyFiles = new string[] { "CONQUER.MIX", "DESERT.MIX", - "GENERAL.MIX", "SCORES.MIX", "SOUNDS.MIX", "TEMPERAT.MIX", "WINTER.MIX"}; + "GENERAL.MIX", "SCORES.MIX", "SOUNDS.MIX", "TEMPERAT.MIX", "WINTER.MIX" }; var extractPackage = "INSTALL/SETUP.Z"; - var extractFiles = new string[] { "cclocal.mix", "speech.mix", "tempicnh.mix", "updatec.mix" }; - - progressBar.SetIndeterminate(false); + var extractFiles = new string[] { "cclocal.mix", "speech.mix", "tempicnh.mix", "updatec.mix", "transit.mix" }; var installCounter = 0; var installTotal = copyFiles.Count() + extractFiles.Count(); @@ -83,34 +87,30 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic var onError = (Action)(s => Game.RunAfterTick(() => { statusLabel.GetText = () => "Error: "+s; - panel.GetWidget("RETRY_BUTTON").IsVisible = () => true; - panel.GetWidget("BACK_BUTTON").IsVisible = () => true; + backButton.IsDisabled = () => false; + retryButton.IsDisabled = () => false; })); - string source; - try - { - source = Path.GetDirectoryName(path); - } - catch (ArgumentException) - { - onError("Invalid path selected"); - return; - } - var t = new Thread( _ => { - if (!InstallUtils.CopyFiles(source, copyFiles, dest, onProgress, onError)) - return; - - if (!InstallUtils.ExtractFromPackage(source, extractPackage, extractFiles, dest, onProgress, onError)) - return; - - Game.RunAfterTick(() => + try { - Widget.CloseWindow(); - continueLoading(); - }); + if (!InstallUtils.CopyFiles(source, copyFiles, dest, onProgress, onError)) + return; + + if (!InstallUtils.ExtractFromPackage(source, extractPackage, extractFiles, dest, onProgress, onError)) + return; + + Game.RunAfterTick(() => + { + Widget.CloseWindow(); + continueLoading(); + }); + } + catch + { + onError("Installation failed"); + } }) { IsBackground = true }; t.Start(); } diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncMusicPlayerLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/CncMusicPlayerLogic.cs index 0759cdb941..d3ab33fe81 100644 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncMusicPlayerLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/Logic/CncMusicPlayerLogic.cs @@ -47,12 +47,14 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic panel.GetWidget("BACK_BUTTON").OnClick = () => { Widget.CloseWindow(); onExit(); }; - Action afterInstall = path => + Action afterInstall = () => { // Mount the new mixfile and rebuild the scores list try { - FileSystem.Mount(path); + var path = new string[] { Platform.SupportDir, "Content", "cnc" }.Aggregate(Path.Combine); + FileSystem.Mount(Path.Combine(path, "scores.mix")); + FileSystem.Mount(Path.Combine(path, "transit.mix")); Rules.Music.Do(m => m.Value.Reload()); } catch (Exception) { } @@ -189,94 +191,95 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic Widget panel; ProgressBarWidget progressBar; LabelWidget statusLabel; - Action afterInstall; + Action afterInstall; + ButtonWidget retryButton, backButton; + Widget installingContainer, insertDiskContainer; [ObjectCreator.UseCtor] public CncInstallMusicLogic([ObjectCreator.Param] Widget widget, - [ObjectCreator.Param] Action afterInstall) + [ObjectCreator.Param] Action afterInstall) { this.afterInstall = afterInstall; panel = widget.GetWidget("INSTALL_MUSIC_PANEL"); progressBar = panel.GetWidget("PROGRESS_BAR"); statusLabel = panel.GetWidget("STATUS_LABEL"); - var backButton = panel.GetWidget("BACK_BUTTON"); + backButton = panel.GetWidget("BACK_BUTTON"); backButton.OnClick = Widget.CloseWindow; - backButton.IsVisible = () => false; - var retryButton = panel.GetWidget("RETRY_BUTTON"); - retryButton.OnClick = PromptForCD; - retryButton.IsVisible = () => false; + retryButton = panel.GetWidget("RETRY_BUTTON"); + retryButton.OnClick = CheckForDisk; - // TODO: Search obvious places (platform dependent) for CD - PromptForCD(); + installingContainer = panel.GetWidget("INSTALLING"); + insertDiskContainer = panel.GetWidget("INSERT_DISK"); + CheckForDisk(); } - void PromptForCD() + void CheckForDisk() { - if (Game.Settings.Graphics.Mode == WindowMode.Fullscreen) + var path = InstallUtils.GetMountedDisk(new [] { "GDI95", "NOD95" }); + + if (path != null) + Install(path); + else { - statusLabel.GetText = () => "Error: Installing from Fullscreen mode is not supported"; - panel.GetWidget("BACK_BUTTON").IsVisible = () => true; - return; + insertDiskContainer.IsVisible = () => true; + installingContainer.IsVisible = () => false; } - - progressBar.SetIndeterminate(true); - statusLabel.GetText = () => "Waiting for file"; - Game.Utilities.PromptFilepathAsync("Select SCORES.MIX on the C&C CD", path => Install(path)); } - public void OnError(string message) + void Install(string source) { - Game.RunAfterTick(() => - { - progressBar.SetIndeterminate(false); - statusLabel.GetText = () => "Error: "+message; - panel.GetWidget("RETRY_BUTTON").IsVisible = () => true; - panel.GetWidget("BACK_BUTTON").IsVisible = () => true; - }); - } + backButton.IsDisabled = () => true; + retryButton.IsDisabled = () => true; + insertDiskContainer.IsVisible = () => false; + installingContainer.IsVisible = () => true; - void Install(string path) - { var dest = new string[] { Platform.SupportDir, "Content", "cnc" }.Aggregate(Path.Combine); - Game.RunAfterTick(() => statusLabel.GetText = () => "Installing"); + var copyFiles = new string[] { "SCORES.MIX" }; + + var extractPackage = "INSTALL/SETUP.Z"; + var extractFiles = new string[] { "transit.mix" }; + + var installCounter = 0; + var installTotal = copyFiles.Count() + extractFiles.Count(); + var onProgress = (Action)(s => Game.RunAfterTick(() => + { + progressBar.Percentage = installCounter*100/installTotal; + installCounter++; + + statusLabel.GetText = () => s; + })); + + var onError = (Action)(s => Game.RunAfterTick(() => + { + statusLabel.GetText = () => "Error: "+s; + backButton.IsDisabled = () => false; + retryButton.IsDisabled = () => false; + })); + + var t = new Thread( _ => + { + try + { + if (!InstallUtils.CopyFiles(source, copyFiles, dest, onProgress, onError)) + return; + + if (!InstallUtils.ExtractFromPackage(source, extractPackage, extractFiles, dest, onProgress, onError)) + return; - // Mount the package and check that it contains the correct files - try - { - var mixFile = new MixFile(path, 0); - - if (!mixFile.Exists("aoi.aud")) - { - OnError("Not the C&C SCORES.MIX"); - return; + Game.RunAfterTick(() => + { + Widget.CloseWindow(); + afterInstall(); + }); } - - var t = new Thread( _ => + catch { - var destPath = Path.Combine(dest, "scores.mix"); - try - { - File.Copy(path, destPath, true); - Game.RunAfterTick(() => - { - Widget.CloseWindow(); // Progress panel - afterInstall(destPath); - }); - } - catch (Exception e) - { - OnError("File copy failed"); - Log.Write("debug", e.Message); - } - }) { IsBackground = true }; - t.Start(); - } - catch - { - OnError("Invalid mix file"); - } + onError("Installation failed"); + } + }) { IsBackground = true }; + t.Start(); } } } diff --git a/mods/cnc/chrome/install.yaml b/mods/cnc/chrome/install.yaml index 61f21de074..03ecb391ea 100644 --- a/mods/cnc/chrome/install.yaml +++ b/mods/cnc/chrome/install.yaml @@ -57,13 +57,13 @@ Container@INSTALL_PANEL: Height:25 Text:OpenRA requires the original C&C content files. Font:Bold - Label@INFO: + Label@INFO2: X:170 Y:70 Width:PARENT_RIGHT-185 Height:25 WordWrap:true - Text:OpenRA can download these files (excluding music and videos) from the internet, or you can install from the original C&C CD. + Text:OpenRA can download these files (excluding music and videos) from the internet, or you can install from the original C&C CDs. Font:Bold Button@QUIT_BUTTON: Id:QUIT_BUTTON @@ -118,20 +118,46 @@ Container@INSTALL_FROMCD_PANEL: Y:11 ImageCollection:logos ImageName:install - ProgressBar@PROGRESS_BAR: - Id:PROGRESS_BAR - X:170 - Y:45 - Width:PARENT_RIGHT - 185 - Height:35 - Label@STATUS_LABEL: - Id:STATUS_LABEL - X:170 - Y:85 - Width:PARENT_RIGHT - 185 - Height:25 - Align:Left - Text:Waiting for CD + Container@INSTALLING: + Id:INSTALLING + Width:PARENT_RIGHT + Height:PARENT_BOTTOM + Visible: false + Children: + ProgressBar@PROGRESS_BAR: + Id:PROGRESS_BAR + X:170 + Y:45 + Width:PARENT_RIGHT - 185 + Height:35 + Label@STATUS_LABEL: + Id:STATUS_LABEL + X:170 + Y:85 + Width:PARENT_RIGHT - 185 + Height:25 + Align:Left + Container@INSERT_DISK: + Id:INSERT_DISK + Width:PARENT_RIGHT + Height:PARENT_BOTTOM + Visible: false + Children: + Label@INFO: + X:170 + Y:35 + Width:PARENT_RIGHT-30 + Height:25 + Text:Disk not found + Font:Bold + Label@INFO2: + X:170 + Y:70 + Width:PARENT_RIGHT-185 + Height:25 + WordWrap:true + Text:Please insert one of the Command & Conquer install CDs then click Retry. + Font:Bold Button@BACK_BUTTON: Id:BACK_BUTTON Key:escape diff --git a/mods/cnc/chrome/music.yaml b/mods/cnc/chrome/music.yaml index 4b1d46c1a0..c3c9efabd8 100644 --- a/mods/cnc/chrome/music.yaml +++ b/mods/cnc/chrome/music.yaml @@ -225,20 +225,46 @@ Container@INSTALL_MUSIC_PANEL: Y:11 ImageCollection:logos ImageName:install - ProgressBar@PROGRESS_BAR: - Id:PROGRESS_BAR - X:170 - Y:45 - Width:PARENT_RIGHT - 185 - Height:35 - Label@STATUS_LABEL: - Id:STATUS_LABEL - X:170 - Y:85 - Width:PARENT_RIGHT - 185 - Height:25 - Align:Left - Text:Waiting for file + Container@INSTALLING: + Id:INSTALLING + Width:PARENT_RIGHT + Height:PARENT_BOTTOM + Visible: false + Children: + ProgressBar@PROGRESS_BAR: + Id:PROGRESS_BAR + X:170 + Y:45 + Width:PARENT_RIGHT - 185 + Height:35 + Label@STATUS_LABEL: + Id:STATUS_LABEL + X:170 + Y:85 + Width:PARENT_RIGHT - 185 + Height:25 + Align:Left + Container@INSERT_DISK: + Id:INSERT_DISK + Width:PARENT_RIGHT + Height:PARENT_BOTTOM + Visible: false + Children: + Label@INFO: + X:170 + Y:35 + Width:PARENT_RIGHT-30 + Height:25 + Text:Disk not found + Font:Bold + Label@INFO2: + X:170 + Y:70 + Width:PARENT_RIGHT-185 + Height:25 + WordWrap:true + Text:Please insert one of the Command & Conquer install CDs then click Retry. + Font:Bold Button@BACK_BUTTON: Id:BACK_BUTTON Key:escape