diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index b3ed7c2915..0cf43ed332 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -361,13 +361,13 @@ namespace OpenRA foreach (var mod in ModMetadata.AllMods) Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version); - InitializeWithMod(Settings.Game.Mod, args.GetValue("Launch.Replay", null)); + InitializeMod(Settings.Game.Mod, args); if (Settings.Server.DiscoverNatDevices) RunAfterDelay(Settings.Server.NatDiscoveryTimeout, UPnP.StoppingNatDiscovery); } - public static void InitializeWithMod(string mod, string replay) + public static void InitializeMod(string mod, Arguments args) { // Clear static state if we have switched mods LobbyInfoChanged = () => { }; @@ -439,13 +439,46 @@ namespace OpenRA } else { - modData.LoadScreen.StartGame(); - Settings.Save(); - if (!string.IsNullOrEmpty(replay)) - Game.JoinReplay(replay); + var window = args != null ? args.GetValue("Launch.Window", null) : null; + if (!string.IsNullOrEmpty(window)) + { + var installData = modData.Manifest.ContentInstaller; + if (installData.InstallerBackgroundWidget != null) + Ui.LoadWidget(installData.InstallerBackgroundWidget, Ui.Root, new WidgetArgs()); + + Widgets.Ui.OpenWindow(window, new WidgetArgs()); + } + else + { + modData.LoadScreen.StartGame(); + Settings.Save(); + var replay = args != null ? args.GetValue("Launch.Replay", null) : null; + if (!string.IsNullOrEmpty(replay)) + Game.JoinReplay(replay); + } } } + public static void TestAndContinue() + { + Ui.ResetAll(); + var installData = modData.Manifest.ContentInstaller; + if (!installData.TestFiles.All(f => GlobalFileSystem.Exists(f))) + { + var args = new WidgetArgs() + { + { "continueLoading", () => InitializeMod(Game.Settings.Game.Mod, null) }, + }; + + if (installData.InstallerBackgroundWidget != null) + Ui.LoadWidget(installData.InstallerBackgroundWidget, Ui.Root, args); + + Ui.OpenWindow(installData.InstallerMenuWidget, args); + } + else + LoadShellMap(); + } + public static void LoadShellMap() { var shellmap = ChooseShellmap(); @@ -471,7 +504,7 @@ namespace OpenRA static double idealFrameTime; public static void SetIdealFrameTime(int fps) - { + { idealFrameTime = 1.0 / fps; } diff --git a/OpenRA.Game/InstallUtils.cs b/OpenRA.Game/InstallUtils.cs index 477747e913..57f7800d83 100644 --- a/OpenRA.Game/InstallUtils.cs +++ b/OpenRA.Game/InstallUtils.cs @@ -18,6 +18,22 @@ using OpenRA.FileSystem; namespace OpenRA { + public class InstallData + { + public readonly string InstallerMenuWidget = null; + public readonly string InstallerBackgroundWidget = null; + public readonly string[] TestFiles = {}; + public readonly string[] DiskTestFiles = {}; + public readonly string PackageToExtractFromCD = null; + public readonly string[] ExtractFilesFromCD = {}; + public readonly string[] CopyFilesFromCD = {}; + + public readonly string PackageMirrorList = null; + + public readonly string MusicPackageMirrorList = null; + public readonly int ShippedSoundtracks = 0; + } + public static class InstallUtils { static IEnumerable GetEntries(this ZipInputStream z) @@ -39,23 +55,26 @@ namespace OpenRA } // 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) + public static bool ExtractFromPackage(string srcPath, string package, string annotation, string[] files, string destPath, Action onProgress, Action onError) { if (!Directory.Exists(destPath)) Directory.CreateDirectory(destPath); - if (!GlobalFileSystem.Exists(srcPath)) { onError("Cannot find " + package); return false; } + Log.Write("debug", "Mounting {0}".F(srcPath)); GlobalFileSystem.Mount(srcPath); - if (!GlobalFileSystem.Exists(package)) { onError("Cannot find " + package); return false; } - GlobalFileSystem.Mount(package); + Log.Write("debug", "Mounting {0}".F(package)); + GlobalFileSystem.Mount(package, annotation); - foreach (var s in files) + foreach (var file in files) { - var destFile = Path.Combine(destPath, s); - using (var sourceStream = GlobalFileSystem.Open(s)) - using (var destStream = File.Create(destFile)) + var dest = Path.Combine(destPath, file); + if (File.Exists(dest)) + File.Delete(dest); + using (var sourceStream = GlobalFileSystem.Open(file)) + using (var destStream = File.Create(dest)) { - onProgress("Extracting " + s); + Log.Write("debug", "Extracting {0} to {1}".F(file, dest)); + onProgress("Extracting " + file); destStream.Write(sourceStream.ReadAllBytes()); } } @@ -75,8 +94,12 @@ namespace OpenRA } var destFile = Path.GetFileName(file).ToLowerInvariant(); - onProgress("Extracting " + destFile); - File.Copy(fromPath, Path.Combine(destPath, destFile), true); + var dest = Path.Combine(destPath, destFile); + if (File.Exists(dest)) + File.Delete(dest); + onProgress("Copying " + destFile); + Log.Write("debug", "Copy {0} to {1}".F(fromPath, dest)); + File.Copy(fromPath, dest, true); } return true; diff --git a/OpenRA.Game/Manifest.cs b/OpenRA.Game/Manifest.cs index ece91098dc..3ae9e78ff6 100644 --- a/OpenRA.Game/Manifest.cs +++ b/OpenRA.Game/Manifest.cs @@ -32,6 +32,7 @@ namespace OpenRA public readonly IReadOnlyDictionary MapFolders; public readonly MiniYaml LoadScreen; public readonly MiniYaml LobbyDefaults; + public readonly InstallData ContentInstaller; public readonly Dictionary> Fonts; public readonly Size TileSize = new Size(24, 24); public readonly string NewsUrl; @@ -71,6 +72,10 @@ namespace OpenRA LoadScreen = yaml["LoadScreen"]; LobbyDefaults = yaml["LobbyDefaults"]; + + if (yaml.ContainsKey("ContentInstaller")) + ContentInstaller = FieldLoader.Load(yaml["ContentInstaller"]); + Fonts = yaml["Fonts"].ToDictionary(my => { var nd = my.ToDictionary(); diff --git a/OpenRA.Mods.Cnc/CncLoadScreen.cs b/OpenRA.Mods.Cnc/CncLoadScreen.cs index c5fbb6517e..ff7db891ac 100644 --- a/OpenRA.Mods.Cnc/CncLoadScreen.cs +++ b/OpenRA.Mods.Cnc/CncLoadScreen.cs @@ -39,7 +39,7 @@ namespace OpenRA.Mods.Cnc r = Game.Renderer; if (r == null) return; - var s = new Sheet("mods/cnc/uibits/chrome.png"); + var s = new Sheet(loadInfo["Image"]); var res = r.Resolution; bounds = new Rectangle(0, 0, res.Width, res.Height); @@ -92,7 +92,7 @@ namespace OpenRA.Mods.Cnc if (!setup && r.Fonts != null) { loadingFont = r.Fonts["BigBold"]; - loadingText = "Loading"; + loadingText = loadInfo["Text"]; loadingPos = new float2((bounds.Width - loadingFont.Measure(loadingText).X) / 2, barY); versionFont = r.Fonts["Regular"]; @@ -121,24 +121,7 @@ namespace OpenRA.Mods.Cnc public void StartGame() { - TestAndContinue(); - } - - void TestAndContinue() - { - Ui.ResetAll(); - if (!loadInfo["TestFiles"].Split(',').All(f => GlobalFileSystem.Exists(f.Trim()))) - { - var args = new WidgetArgs() - { - { "continueLoading", () => TestAndContinue() }, - { "installData", loadInfo } - }; - Ui.LoadWidget(loadInfo["InstallerBackgroundWidget"], Ui.Root, args); - Ui.OpenWindow(loadInfo["InstallerMenuWidget"], args); - } - else - Game.LoadShellMap(); + Game.TestAndContinue(); } } } \ No newline at end of file diff --git a/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj b/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj index 9de122c9d4..21d51bd481 100644 --- a/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj +++ b/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj @@ -79,7 +79,6 @@ - @@ -90,7 +89,6 @@ - diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncInstallFromCDLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/CncInstallFromCDLogic.cs deleted file mode 100644 index 53ea45904d..0000000000 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncInstallFromCDLogic.cs +++ /dev/null @@ -1,127 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System; -using System.IO; -using System.Linq; -using System.Threading; -using OpenRA.Widgets; - -namespace OpenRA.Mods.Cnc.Widgets.Logic -{ - public class CncInstallFromCDLogic - { - Widget panel; - ProgressBarWidget progressBar; - LabelWidget statusLabel; - Action afterInstall; - ButtonWidget retryButton, backButton; - Widget installingContainer, insertDiskContainer; - - string[] filesToCopy, filesToExtract; - - [ObjectCreator.UseCtor] - public CncInstallFromCDLogic(Widget widget, Action afterInstall, string[] filesToCopy, string[] filesToExtract) - { - this.afterInstall = afterInstall; - this.filesToCopy = filesToCopy; - this.filesToExtract = filesToExtract; - - panel = widget; - progressBar = panel.Get("PROGRESS_BAR"); - statusLabel = panel.Get("STATUS_LABEL"); - - backButton = panel.Get("BACK_BUTTON"); - backButton.OnClick = Ui.CloseWindow; - - retryButton = panel.Get("RETRY_BUTTON"); - retryButton.OnClick = CheckForDisk; - - installingContainer = panel.Get("INSTALLING"); - insertDiskContainer = panel.Get("INSERT_DISK"); - - CheckForDisk(); - } - - public static bool IsValidDisk(string diskRoot) - { - var files = new string[][] { - new[] { diskRoot, "CONQUER.MIX" }, - new[] { diskRoot, "DESERT.MIX" }, - new[] { diskRoot, "INSTALL", "SETUP.Z" }, - }; - - return files.All(f => File.Exists(f.Aggregate(Path.Combine))); - } - - void CheckForDisk() - { - var path = InstallUtils.GetMountedDisk(IsValidDisk); - - if (path != null) - Install(path); - else - { - insertDiskContainer.IsVisible = () => true; - installingContainer.IsVisible = () => false; - } - } - - 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 extractPackage = "INSTALL/SETUP.Z"; - - var installCounter = 0; - var installTotal = filesToExtract.Count() + filesToExtract.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; - })); - - new Thread(_ => - { - try - { - if (!InstallUtils.CopyFiles(source, filesToCopy, dest, onProgress, onError)) - return; - - if (!InstallUtils.ExtractFromPackage(source, extractPackage, filesToExtract, dest, onProgress, onError)) - return; - - Game.RunAfterTick(() => - { - Ui.CloseWindow(); - afterInstall(); - }); - } - catch - { - onError("Installation failed"); - } - }) { IsBackground = true }.Start(); - } - } -} diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncInstallMusicLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/CncInstallMusicLogic.cs deleted file mode 100644 index 35bff5fc70..0000000000 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncInstallMusicLogic.cs +++ /dev/null @@ -1,57 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System; -using System.IO; -using System.Linq; -using OpenRA.FileSystem; -using OpenRA.Mods.RA.Widgets.Logic; -using OpenRA.Widgets; - -namespace OpenRA.Mods.Cnc.Widgets.Logic -{ - public class CncInstallMusicLogic - { - [ObjectCreator.UseCtor] - public CncInstallMusicLogic(Widget widget, Ruleset modRules, Action onExit) - { - var installButton = widget.GetOrNull("INSTALL_BUTTON"); - if (installButton != null) - { - Action afterInstall = () => - { - try - { - var path = new string[] { Platform.SupportDir, "Content", Game.modData.Manifest.Mod.Id }.Aggregate(Path.Combine); - GlobalFileSystem.Mount(Path.Combine(path, "scores.mix")); - GlobalFileSystem.Mount(Path.Combine(path, "transit.mix")); - - modRules.Music.Do(m => m.Value.Reload()); - - var musicPlayerLogic = (MusicPlayerLogic)installButton.Parent.LogicObject; - musicPlayerLogic.BuildMusicTable(); - } - catch (Exception e) - { - Log.Write("debug", "Mounting the new mixfile and rebuild of scores list failed:\n{0}", e); - } - }; - - installButton.OnClick = () => - Ui.OpenWindow("INSTALL_MUSIC_PANEL", new WidgetArgs() { - { "afterInstall", afterInstall }, - { "filesToCopy", new[] { "SCORES.MIX" } }, - { "filesToExtract", new[] { "transit.mix" } }, - }); - installButton.IsVisible = () => modRules.InstalledMusic.ToArray().Length < 3; // HACK around music being split between transit.mix and scores.mix - } - } - } -} diff --git a/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj b/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj index f6e2e4be16..78b1d3bcdd 100644 --- a/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj +++ b/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj @@ -67,7 +67,6 @@ - diff --git a/OpenRA.Mods.D2k/Widgets/Logic/D2kInstallFromCDLogic.cs b/OpenRA.Mods.D2k/Widgets/Logic/D2kInstallFromCDLogic.cs deleted file mode 100644 index 234afbd7fb..0000000000 --- a/OpenRA.Mods.D2k/Widgets/Logic/D2kInstallFromCDLogic.cs +++ /dev/null @@ -1,164 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System; -using System.IO; -using System.Linq; -using System.Threading; -using OpenRA.Widgets; - -namespace OpenRA.Mods.D2k.Widgets.Logic -{ - public class D2kInstallFromCDLogic - { - Widget panel; - ProgressBarWidget progressBar; - LabelWidget statusLabel; - Action continueLoading; - ButtonWidget retryButton, backButton; - Widget installingContainer, insertDiskContainer; - - [ObjectCreator.UseCtor] - public D2kInstallFromCDLogic(Widget widget, Action continueLoading) - { - panel = widget.Get("INSTALL_FROMCD_PANEL"); - progressBar = panel.Get("PROGRESS_BAR"); - statusLabel = panel.Get("STATUS_LABEL"); - - backButton = panel.Get("BACK_BUTTON"); - backButton.OnClick = Ui.CloseWindow; - - retryButton = panel.Get("RETRY_BUTTON"); - retryButton.OnClick = CheckForDisk; - - installingContainer = panel.Get("INSTALLING"); - insertDiskContainer = panel.Get("INSERT_DISK"); - - CheckForDisk(); - this.continueLoading = continueLoading; - } - - public static bool IsValidDisk(string diskRoot) - { - var files = new string[][] { - new[] { diskRoot, "music", "ambush.aud" }, - new[] { diskRoot, "setup", "setup.z" }, - }; - - return files.All(f => File.Exists(f.Aggregate(Path.Combine))); - } - - void CheckForDisk() - { - var path = InstallUtils.GetMountedDisk(IsValidDisk); - - if (path != null) - Install(path); - else - { - insertDiskContainer.IsVisible = () => true; - installingContainer.IsVisible = () => false; - } - } - - void Install(string source) - { - backButton.IsDisabled = () => true; - retryButton.IsDisabled = () => true; - insertDiskContainer.IsVisible = () => false; - installingContainer.IsVisible = () => true; - - var destMusic = new string[] { Platform.SupportDir, "Content", "d2k", "Music" }.Aggregate(Path.Combine); - var destData = new[] { Platform.SupportDir, "Content", "d2k" }.Aggregate(Path.Combine); - var destSound = new[] { destData, "GAMESFX" }.Aggregate(Path.Combine); - var copyFiles = new string[] { "music/ambush.aud", "music/arakatak.aud", "music/atregain.aud", "music/entordos.aud", "music/fightpwr.aud", "music/fremen.aud", "music/hark_bat.aud", "music/landsand.aud", "music/options.aud", "music/plotting.aud", "music/risehark.aud", "music/robotix.aud", "music/score.aud", "music/soldappr.aud", "music/spicesct.aud", "music/undercon.aud", "music/waitgame.aud" }; - - var extractPackage = "setup/setup.z"; - var extractFiles = new string[] { "SOUND.RS", "DATA.R8", "MOUSE.R8", "BLOXBASE.R8", "BLOXBAT.R8", "BLOXBGBS.R8", "BLOXICE.R8", "BLOXTREE.R8", "BLOXWAST.R8" }; - var extractAudio = new string[] { "A_ECONF1.AUD", "A_ECONF2.AUD", "A_ECONF3.AUD", "A_ESEL1.AUD", "A_ESEL2.AUD", "A_ESEL3.AUD", - "A_FCONF1.AUD", "A_FCONF2.AUD", "A_FCONF3.AUD", "A_FCONF4.AUD", "A_FSEL1.AUD", "A_FSEL2.AUD", "A_FSEL3.AUD", "A_FSEL4.AUD", - "AI_1MIN.AUD", "AI_2MIN.AUD", "AI_3MIN.AUD", "AI_4MIN.AUD", "AI_5MIN.AUD", "AI_ABORT.AUD", "AI_ATACK.AUD", "AI_BDRDY.AUD", - "AI_BLOST.AUD", "AI_BUILD.AUD", "AI_CANCL.AUD", "AI_CAPT.AUD", "A_ICONF1.AUD", "A_ICONF2.AUD", "A_ICONF3.AUD", "AI_DHRDY.AUD", - "AI_DPLOY.AUD", "AI_ENEMY.AUD", "AI_GANEW.AUD", "AI_GLOAD.AUD", "AI_GSAVE.AUD", "AI_GUARD.AUD", "AI_HATTK.AUD", "AI_HOLD.AUD", - "AI_LAUNC.AUD", "AI_MAP1A.AUD", "AI_MAP1B.AUD", "AI_MAP1C.AUD", "AI_MAP2A.AUD", "AI_MAP2B.AUD", "AI_MAP2C.AUD", "AI_MAP3A.AUD", - "AI_MAP4A.AUD", "AI_MAP5A.AUD", "AI_MAP6A.AUD", "AI_MAP7A.AUD", "AI_MAP8A.AUD", "AI_MAP9A.AUD", "AI_MEND.AUD", "AI_MFAIL.AUD", - "AI_MONEY.AUD", "AI_MWIN.AUD", "AI_NEWOP.AUD", "AI_NROOM.AUD", "AI_ORDER.AUD", "AI_PLACE.AUD", "AI_POWER.AUD", "AI_PREP.AUD", - "AI_PRMRY.AUD", "AI_REINF.AUD", "AI_RUN.AUD", "A_ISEL1.AUD", "A_ISEL2.AUD", "A_ISEL3.AUD", "AI_SELL.AUD", "AI_SILOS.AUD", - "AI_SPORT.AUD", "AI_TRAIN.AUD", "AI_ULOST.AUD", "AI_UNRDY.AUD", "AI_UPGOP.AUD", "AI_UPGRD.AUD", "AI_WATTK.AUD", "AI_WSIGN.AUD", - "A_VCONF1.AUD", "A_VCONF2.AUD", "A_VCONF3.AUD", "A_VSEL1.AUD", "A_VSEL2.AUD", "A_VSEL3.AUD", "G_SCONF1.AUD", "G_SCONF2.AUD", - "G_SCONF3.AUD", "G_SSEL1.AUD", "G_SSEL2.AUD", "G_SSEL3.AUD", "H_ECONF1.AUD", "H_ECONF2.AUD", "H_ECONF3.AUD", "H_ESEL1.AUD", - "H_ESEL2.AUD", "H_ESEL3.AUD", "HI_1MIN.AUD", "HI_2MIN.AUD", "HI_3MIN.AUD", "HI_4MIN.AUD", "HI_5MIN.AUD", "HI_ABORT.AUD", - "HI_ATACK.AUD", "HI_BDRDY.AUD", "HI_BLOST.AUD", "HI_BUILD.AUD", "HI_CANCL.AUD", "HI_CAPT.AUD", "H_ICONF1.AUD", "H_ICONF2.AUD", - "H_ICONF3.AUD", "HI_DHRDY.AUD", "HI_DPLOY.AUD", "HI_ENEMY.AUD", "HI_GANEW.AUD", "HI_GLOAD.AUD", "HI_GSAVE.AUD", "HI_GUARD.AUD", - "HI_HATTK.AUD", "HI_HOLD.AUD", "HI_LAUNC.AUD", "HI_MAP1A.AUD", "HI_MAP1B.AUD", "HI_MAP1C.AUD", "HI_MAP2A.AUD", "HI_MAP2B.AUD", - "HI_MAP2C.AUD", "HI_MAP3A.AUD", "HI_MAP3B.AUD", "HI_MAP4A.AUD", "HI_MAP4B.AUD", "HI_MAP5A.AUD", "HI_MAP6A.AUD", "HI_MAP6B.AUD", - "HI_MAP7A.AUD", "HI_MAP9A.AUD", "HI_MAP9.AUD", "HI_MEND.AUD", "HI_MFAIL.AUD", "HI_MONEY.AUD", "HI_MWIN.AUD", "HI_NEWOP.AUD", - "HI_NROOM.AUD", "HI_ORDER.AUD", "HI_PLACE.AUD", "HI_POWER.AUD", "HI_PREP.AUD", "HI_PRMRY.AUD", "HI_REINF.AUD", "HI_RUN.AUD", - "H_ISEL1.AUD", "H_ISEL2.AUD", "H_ISEL3.AUD", "HI_SELL.AUD", "HI_SILOS.AUD", "HI_SPORT.AUD", "HI_TRAIN.AUD", "HI_ULOST.AUD", - "HI_UNRDY.AUD", "HI_UPGOP.AUD", "HI_UPGRD.AUD", "HI_WATTK.AUD", "HI_WSIGN.AUD", "H_VCONF1.AUD", "H_VCONF2.AUD", "H_VCONF3.AUD", - "H_VSEL1.AUD", "H_VSEL2.AUD", "H_VSEL3.AUD", "O_ECONF1.AUD", "O_ECONF2.AUD", "O_ECONF3.AUD", "O_ESEL1.AUD", "O_ESEL2.AUD", - "O_ESEL3.AUD", "OI_1MIN.AUD", "OI_2MIN.AUD", "OI_3MIN.AUD", "OI_4MIN.AUD", "OI_5MIN.AUD", "OI_ABORT.AUD", "OI_ATACK.AUD", - "OI_BDRDY.AUD", "OI_BLOST.AUD", "OI_BUILD.AUD", "OI_CANCL.AUD", "OI_CAPT.AUD", "O_ICONF1.AUD", "O_ICONF2.AUD", "O_ICONF3.AUD", - "OI_DHRDY.AUD", "OI_DPLOY.AUD", "OI_ENEMY.AUD", "OI_GANEW.AUD", "OI_GLOAD.AUD", "OI_GSAVE.AUD", "OI_GUARD.AUD", "OI_HATTK.AUD", - "OI_HOLD.AUD", "OI_LAUNC.AUD", "OI_MAP1A.AUD", "OI_MAP1B.AUD", "OI_MAP1C.AUD", "OI_MAP2A.AUD", "OI_MAP2B.AUD", "OI_MAP2C.AUD", - "OI_MAP3A.AUD", "OI_MAP4A.AUD", "OI_MAP5A.AUD", "OI_MAP6A.AUD", "OI_MAP7A.AUD", "OI_MAP8A.AUD", "OI_MAP9A.AUD", "OI_MEND.AUD", - "OI_MFAIL.AUD", "OI_MONEY.AUD", "OI_MWIN.AUD", "OI_NEWOP.AUD", "OI_NROOM.AUD", "OI_ORDER.AUD", "OI_PLACE.AUD", "OI_POWER.AUD", - "OI_PREP.AUD", "OI_PRMRY.AUD", "OI_REINF.AUD", "OI_RUN.AUD", "O_ISEL1.AUD", "O_ISEL2.AUD", "O_ISEL3.AUD", "OI_SELL.AUD", - "OI_SILOS.AUD", "OI_SPORT.AUD", "OI_TRAIN.AUD", "OI_ULOST.AUD", "OI_UNRDY.AUD", "OI_UPGOP.AUD", "OI_UPGRD.AUD", "OI_WATTK.AUD", - "OI_WSIGN.AUD", "O_SCONF1.AUD", "O_SCONF2.AUD", "O_SCONF3.AUD", "O_SSEL1.AUD", "O_SSEL2.AUD", "O_SSEL3.AUD", "O_VCONF1.AUD", - "O_VCONF2.AUD", "O_VCONF3.AUD", "O_VSEL1.AUD", "O_VSEL2.AUD", "O_VSEL3.AUD" }; - - var installCounter = 0; - var installTotal = copyFiles.Count() + extractFiles.Count() + extractAudio.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, destMusic, onProgress, onError)) - return; - - if (!InstallUtils.ExtractFromPackage(source, extractPackage, extractFiles, destData, onProgress, onError)) - return; - - if (!InstallUtils.ExtractFromPackage(source, extractPackage, extractAudio, destSound, onProgress, onError)) - return; - - Game.RunAfterTick(() => - { - statusLabel.GetText = () => "Game assets have been extracted."; - backButton.IsDisabled = () => false; - continueLoading(); - }); - } - catch - { - onError("Installation failed"); - } - }) { IsBackground = true }; - t.Start(); - } - } -} diff --git a/OpenRA.Mods.RA/DefaultLoadScreen.cs b/OpenRA.Mods.RA/DefaultLoadScreen.cs index ef6b5342d7..3e4481079a 100644 --- a/OpenRA.Mods.RA/DefaultLoadScreen.cs +++ b/OpenRA.Mods.RA/DefaultLoadScreen.cs @@ -20,7 +20,6 @@ namespace OpenRA.Mods.RA { public class DefaultLoadScreen : ILoadScreen { - Dictionary info; Stopwatch lastUpdate = Stopwatch.StartNew(); Renderer r; @@ -31,8 +30,6 @@ namespace OpenRA.Mods.RA public void Init(Manifest m, Dictionary info) { - this.info = info; - // Avoid standard loading mechanisms so we // can display the loadscreen as early as possible r = Game.Renderer; @@ -72,23 +69,7 @@ namespace OpenRA.Mods.RA public void StartGame() { - TestAndContinue(); - } - - void TestAndContinue() - { - Ui.ResetAll(); - if (!info["TestFiles"].Split(',').All(f => GlobalFileSystem.Exists(f.Trim()))) - { - var args = new WidgetArgs() - { - { "continueLoading", () => TestAndContinue() }, - { "installData", info } - }; - Ui.OpenWindow(info["InstallerMenuWidget"], args); - } - else - Game.LoadShellMap(); + Game.TestAndContinue(); } } } diff --git a/OpenRA.Mods.RA/ModChooserLoadScreen.cs b/OpenRA.Mods.RA/ModChooserLoadScreen.cs index bdfc3d2968..e6c8b86068 100644 --- a/OpenRA.Mods.RA/ModChooserLoadScreen.cs +++ b/OpenRA.Mods.RA/ModChooserLoadScreen.cs @@ -22,7 +22,7 @@ namespace OpenRA.Mods.Cnc public void Init(Manifest m, Dictionary info) { - var sheet = new Sheet("mods/modchooser/chrome.png"); + var sheet = new Sheet(info["Image"]); var res = Game.Renderer.Resolution; bounds = new Rectangle(0, 0, res.Width, res.Height); sprite = new Sprite(sheet, new Rectangle(0,0,1024,480), TextureChannel.Alpha); diff --git a/OpenRA.Mods.RA/NullLoadScreen.cs b/OpenRA.Mods.RA/NullLoadScreen.cs index 05217fe3f4..7b879332e2 100644 --- a/OpenRA.Mods.RA/NullLoadScreen.cs +++ b/OpenRA.Mods.RA/NullLoadScreen.cs @@ -30,7 +30,6 @@ namespace OpenRA.Mods.RA public void StartGame() { Ui.ResetAll(); - Game.modData.WidgetLoader.LoadWidget( new WidgetArgs(), Ui.Root, "INIT_SETUP" ); } } } diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index a7c9bdafbe..3cd96f7a4a 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -391,7 +391,6 @@ - @@ -519,6 +518,8 @@ + + diff --git a/OpenRA.Mods.RA/Widgets/Logic/DownloadPackagesLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/DownloadPackagesLogic.cs index 5cd29af5ea..db5e34e2cd 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/DownloadPackagesLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/DownloadPackagesLogic.cs @@ -21,17 +21,17 @@ namespace OpenRA.Mods.RA.Widgets.Logic { public class DownloadPackagesLogic { - Widget panel; - Dictionary installData; - ProgressBarWidget progressBar; - LabelWidget statusLabel; - Action afterInstall; + readonly Widget panel; + readonly string mirrorListUrl; + readonly ProgressBarWidget progressBar; + readonly LabelWidget statusLabel; + readonly Action afterInstall; string mirror; [ObjectCreator.UseCtor] - public DownloadPackagesLogic(Widget widget, Dictionary installData, Action afterInstall) + public DownloadPackagesLogic(Widget widget, Action afterInstall, string mirrorListUrl) { - this.installData = installData; + this.mirrorListUrl = mirrorListUrl; this.afterInstall = afterInstall; panel = widget.Get("INSTALL_DOWNLOAD_PANEL"); @@ -130,7 +130,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic }; // Get the list of mirrors - var updateMirrors = new Download(installData["PackageMirrorList"], mirrorsFile, onDownloadProgress, onFetchMirrorsComplete); + var updateMirrors = new Download(mirrorListUrl, mirrorsFile, onDownloadProgress, onFetchMirrorsComplete); cancelButton.OnClick = () => { updateMirrors.Cancel(); Ui.CloseWindow(); }; retryButton.OnClick = () => { updateMirrors.Cancel(); ShowDownloadDialog(); }; } diff --git a/OpenRA.Mods.RA/Widgets/Logic/RAInstallFromCDLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/InstallFromCDLogic.cs similarity index 59% rename from OpenRA.Mods.RA/Widgets/Logic/RAInstallFromCDLogic.cs rename to OpenRA.Mods.RA/Widgets/Logic/InstallFromCDLogic.cs index b0aa1846b8..0a77e0d2ce 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/RAInstallFromCDLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/InstallFromCDLogic.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -16,7 +16,7 @@ using OpenRA.Widgets; namespace OpenRA.Mods.RA.Widgets.Logic { - public class RAInstallFromCDLogic + public class InstallFromCDLogic { Widget panel; ProgressBarWidget progressBar; @@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic Widget installingContainer, insertDiskContainer; [ObjectCreator.UseCtor] - public RAInstallFromCDLogic(Widget widget, Action continueLoading) + public InstallFromCDLogic(Widget widget, Action continueLoading) { this.continueLoading = continueLoading; panel = widget.Get("INSTALL_FROMCD_PANEL"); @@ -44,12 +44,14 @@ namespace OpenRA.Mods.RA.Widgets.Logic CheckForDisk(); } + bool IsValidDisk(string diskRoot) + { + return Game.modData.Manifest.ContentInstaller.DiskTestFiles.All(f => File.Exists(Path.Combine(diskRoot, f))); + } + void CheckForDisk() { - Func ValidDiskFilter = diskRoot => File.Exists(diskRoot+Path.DirectorySeparatorChar+"MAIN.MIX") && - File.Exists(new string[] { diskRoot, "INSTALL", "REDALERT.MIX" }.Aggregate(Path.Combine)); - - var path = InstallUtils.GetMountedDisk(ValidDiskFilter); + var path = InstallUtils.GetMountedDisk(IsValidDisk); if (path != null) Install(path); @@ -67,18 +69,20 @@ namespace OpenRA.Mods.RA.Widgets.Logic insertDiskContainer.IsVisible = () => false; installingContainer.IsVisible = () => true; - var dest = new string[] { Platform.SupportDir, "Content", "ra" }.Aggregate(Path.Combine); - var copyFiles = new string[] { "INSTALL/REDALERT.MIX" }; + var dest = new string[] { Platform.SupportDir, "Content", Game.modData.Manifest.Mod.Id }.Aggregate(Path.Combine); + var copyFiles = Game.modData.Manifest.ContentInstaller.CopyFilesFromCD; - var extractPackage = "MAIN.MIX"; - var extractFiles = new string[] { "conquer.mix", "russian.mix", "allies.mix", "sounds.mix", - "scores.mix", "snow.mix", "interior.mix", "temperat.mix" }; + var packageToExtract = Game.modData.Manifest.ContentInstaller.PackageToExtractFromCD.Split(':'); + var extractPackage = packageToExtract.First(); + var annotation = packageToExtract.Length > 1 ? packageToExtract.Last() : null; + + var extractFiles = Game.modData.Manifest.ContentInstaller.ExtractFilesFromCD; var installCounter = 0; var installTotal = copyFiles.Count() + extractFiles.Count(); var onProgress = (Action)(s => Game.RunAfterTick(() => { - progressBar.Percentage = installCounter*100/installTotal; + progressBar.Percentage = installCounter * 100 / installTotal; installCounter++; statusLabel.GetText = () => s; @@ -91,28 +95,39 @@ namespace OpenRA.Mods.RA.Widgets.Logic retryButton.IsDisabled = () => false; })); - var t = new Thread( _ => + new Thread(() => { try { if (!InstallUtils.CopyFiles(source, copyFiles, dest, onProgress, onError)) + { + onError("Copying files from CD failed."); return; + } - if (!InstallUtils.ExtractFromPackage(source, extractPackage, extractFiles, dest, onProgress, onError)) - return; + if (!string.IsNullOrEmpty(extractPackage)) + { + if (!InstallUtils.ExtractFromPackage(source, extractPackage, annotation, extractFiles, dest, onProgress, onError)) + { + onError("Extracting files from CD failed."); + return; + } + } Game.RunAfterTick(() => { + statusLabel.GetText = () => "Game assets have been extracted."; Ui.CloseWindow(); continueLoading(); }); } - catch + catch(Exception e) { - onError("Installation failed"); + onError("Installation failed.\n{0}".F(e.Message)); + Log.Write("debug", e.ToString()); + return; } - }) { IsBackground = true }; - t.Start(); + }) { IsBackground = true }.Start(); } } } diff --git a/OpenRA.Mods.RA/Widgets/Logic/InstallLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/InstallLogic.cs index 97a53a74ff..69bfeca4c3 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/InstallLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/InstallLogic.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -17,35 +17,27 @@ namespace OpenRA.Mods.RA.Widgets.Logic public class InstallLogic : Widget { [ObjectCreator.UseCtor] - public InstallLogic(Widget widget, Dictionary installData, Action continueLoading) + public InstallLogic(Widget widget, Action continueLoading) { + var mirrorListUrl = Game.modData.Manifest.ContentInstaller.PackageMirrorList; var panel = widget.Get("INSTALL_PANEL"); - var args = new WidgetArgs() + var widgetArgs = new WidgetArgs() { { "afterInstall", () => { Ui.CloseWindow(); continueLoading(); } }, - { "installData", installData }, - { "continueLoading", continueLoading } + { "continueLoading", continueLoading }, + { "mirrorListUrl", mirrorListUrl }, }; panel.Get("DOWNLOAD_BUTTON").OnClick = () => - Ui.OpenWindow("INSTALL_DOWNLOAD_PANEL", args); + Ui.OpenWindow("INSTALL_DOWNLOAD_PANEL", widgetArgs); - if (installData.ContainsKey("FilesToCopy") && !string.IsNullOrEmpty(installData["FilesToCopy"]) && - installData.ContainsKey("FilesToExtract") && !string.IsNullOrEmpty(installData["FilesToExtract"])) - { - args = new WidgetArgs(args) - { - { "filesToCopy", installData["FilesToCopy"].Split(',') }, - { "filesToExtract", installData["FilesToExtract"].Split(',') }, - }; - } panel.Get("INSTALL_BUTTON").OnClick = () => - Ui.OpenWindow("INSTALL_FROMCD_PANEL", args); + Ui.OpenWindow("INSTALL_FROMCD_PANEL", widgetArgs); panel.Get("BACK_BUTTON").OnClick = () => { Game.Settings.Game.PreviousMod = Game.modData.Manifest.Mod.Id; - Game.InitializeWithMod("modchooser", null); + Game.InitializeMod("modchooser", null); }; } } diff --git a/OpenRA.Mods.RA/Widgets/Logic/InstallMusicLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/InstallMusicLogic.cs new file mode 100644 index 0000000000..94971f7b52 --- /dev/null +++ b/OpenRA.Mods.RA/Widgets/Logic/InstallMusicLogic.cs @@ -0,0 +1,59 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using OpenRA.FileSystem; +using OpenRA.Widgets; + +namespace OpenRA.Mods.RA.Widgets.Logic +{ + public class InstallMusicLogic + { + [ObjectCreator.UseCtor] + public InstallMusicLogic(Widget widget) + { + var installMusicContainer = widget.Get("INSTALL_MUSIC_PANEL"); + + var cancelButton = installMusicContainer.GetOrNull("CANCEL_BUTTON"); + if (cancelButton != null) + { + cancelButton.OnClick = () => Game.InitializeMod(Game.Settings.Game.Mod, null); + } + + var copyFromDiscButton = installMusicContainer.GetOrNull("COPY_FROM_CD_BUTTON"); + if (copyFromDiscButton != null) + { + copyFromDiscButton.OnClick = () => + { + Ui.OpenWindow("INSTALL_FROMCD_PANEL", new WidgetArgs() { + { "continueLoading", () => Game.InitializeMod(Game.Settings.Game.Mod, null) }, + }); + }; + } + + var downloadButton = installMusicContainer.GetOrNull("DOWNLOAD_BUTTON"); + if (downloadButton != null) + { + var mirrorListUrl = Game.modData.Manifest.ContentInstaller.MusicPackageMirrorList; + downloadButton.IsVisible = () => !string.IsNullOrEmpty(mirrorListUrl); + downloadButton.OnClick = () => + { + Ui.OpenWindow("INSTALL_DOWNLOAD_PANEL", new WidgetArgs() { + { "afterInstall", () => Game.InitializeMod(Game.Settings.Game.Mod, null) }, + { "mirrorListUrl", mirrorListUrl }, + }); + }; + } + } + } +} diff --git a/OpenRA.Mods.RA/Widgets/Logic/MainMenuLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/MainMenuLogic.cs index 5231c797cd..70be5d890e 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/MainMenuLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/MainMenuLogic.cs @@ -54,7 +54,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic mainMenu.Get("MODS_BUTTON").OnClick = () => { Game.Settings.Game.PreviousMod = Game.modData.Manifest.Mod.Id; - Game.InitializeWithMod("modchooser", null); + Game.InitializeMod("modchooser", null); }; mainMenu.Get("SETTINGS_BUTTON").OnClick = () => diff --git a/OpenRA.Mods.RA/Widgets/Logic/ModBrowserLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/ModBrowserLogic.cs index 0d09193a9d..7a2a518185 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/ModBrowserLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/ModBrowserLogic.cs @@ -161,7 +161,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic Game.RunAfterTick(() => { Ui.CloseWindow(); - Game.InitializeWithMod(mod.Id, null); + Game.InitializeMod(mod.Id, null); }); } } diff --git a/OpenRA.Mods.RA/Widgets/Logic/MusicPlayerLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/MusicPlayerLogic.cs index 6b8dd1a4ce..4896d83bed 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/MusicPlayerLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/MusicPlayerLogic.cs @@ -81,6 +81,20 @@ namespace OpenRA.Mods.RA.Widgets.Logic musicSlider.OnChange += x => Sound.MusicVolume = x; musicSlider.Value = Sound.MusicVolume; + var installButton = widget.GetOrNull("INSTALL_BUTTON"); + if (installButton != null) + { + var args = new string[] { "Launch.Window=INSTALL_MUSIC_PANEL" }; + installButton.OnClick = () => + { + Game.modData.LoadScreen.Display(); // HACK: prevent a flicker when transitioning to the installation dialog + Game.InitializeMod(Game.Settings.Game.Mod, new Arguments(args)); + }; + + var installData = Game.modData.Manifest.ContentInstaller; + installButton.IsVisible = () => modRules.InstalledMusic.ToArray().Length <= installData.ShippedSoundtracks; + } + panel.Get("BACK_BUTTON").OnClick = () => { Game.Settings.Save(); Ui.CloseWindow(); onExit(); }; } diff --git a/OpenRA.Mods.TS/OpenRA.Mods.TS.csproj b/OpenRA.Mods.TS/OpenRA.Mods.TS.csproj index 65ab02ac41..652b989571 100644 --- a/OpenRA.Mods.TS/OpenRA.Mods.TS.csproj +++ b/OpenRA.Mods.TS/OpenRA.Mods.TS.csproj @@ -46,7 +46,6 @@ - diff --git a/OpenRA.Mods.TS/Widgets/Logic/TSInstallFromCDLogic.cs b/OpenRA.Mods.TS/Widgets/Logic/TSInstallFromCDLogic.cs deleted file mode 100755 index c1c82d7a7e..0000000000 --- a/OpenRA.Mods.TS/Widgets/Logic/TSInstallFromCDLogic.cs +++ /dev/null @@ -1,111 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System; -using System.IO; -using System.Linq; -using System.Threading; -using OpenRA.Widgets; - -namespace OpenRA.Mods.TS.Widgets.Logic -{ - public class TSInstallFromCDLogic - { - Widget panel; - ProgressBarWidget progressBar; - LabelWidget statusLabel; - Action continueLoading; - ButtonWidget retryButton, backButton; - Widget installingContainer, insertDiskContainer; - - [ObjectCreator.UseCtor] - public TSInstallFromCDLogic(Widget widget, Action continueLoading) - { - this.continueLoading = continueLoading; - panel = widget.Get("INSTALL_FROMCD_PANEL"); - progressBar = panel.Get("PROGRESS_BAR"); - statusLabel = panel.Get("STATUS_LABEL"); - - backButton = panel.Get("BACK_BUTTON"); - backButton.OnClick = Ui.CloseWindow; - - retryButton = panel.Get("RETRY_BUTTON"); - retryButton.OnClick = CheckForDisk; - - installingContainer = panel.Get("INSTALLING"); - insertDiskContainer = panel.Get("INSERT_DISK"); - CheckForDisk(); - } - - void CheckForDisk() - { - Func validDiskFilter = diskRoot => File.Exists(diskRoot + Path.DirectorySeparatorChar + "multi.mix") && - File.Exists(new string[] { diskRoot, "install", "tibsun.mix" }.Aggregate(Path.Combine)); - - var path = InstallUtils.GetMountedDisk(validDiskFilter); - - if (path != null) - Install(path); - else - { - insertDiskContainer.IsVisible = () => true; - installingContainer.IsVisible = () => false; - } - } - - void Install(string source) - { - backButton.IsDisabled = () => true; - retryButton.IsDisabled = () => true; - insertDiskContainer.IsVisible = () => false; - installingContainer.IsVisible = () => true; - - var dest = new string[] { Platform.SupportDir, "Content", "ts" }.Aggregate(Path.Combine); - var copyFiles = new string[] { "install/tibsun.mix", "scores.mix", "multi.mix" }; - - var installCounter = 0; - var installTotal = copyFiles.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; - - Game.RunAfterTick(() => - { - Ui.CloseWindow(); - continueLoading(); - }); - } - catch - { - onError("Installation failed"); - } - }) { IsBackground = true }; - t.Start(); - } - } -} diff --git a/mods/cnc/chrome/install.yaml b/mods/cnc/chrome/install.yaml index 25c2d85913..4f7ffdd0eb 100644 --- a/mods/cnc/chrome/install.yaml +++ b/mods/cnc/chrome/install.yaml @@ -82,7 +82,7 @@ Container@INSTALL_PANEL: Text: Use CD Container@INSTALL_FROMCD_PANEL: - Logic: CncInstallFromCDLogic + Logic: InstallFromCDLogic X: (WINDOW_RIGHT - WIDTH)/2 Y: (WINDOW_BOTTOM - 150)/2 Width: 640 diff --git a/mods/cnc/chrome/music.yaml b/mods/cnc/chrome/music.yaml index 1b632ce6ed..b7faa30885 100644 --- a/mods/cnc/chrome/music.yaml +++ b/mods/cnc/chrome/music.yaml @@ -170,7 +170,6 @@ Container@MUSIC_PANEL: Height: 35 Text: Back Button@INSTALL_BUTTON: - Logic: CncInstallMusicLogic X: 220 Y: 399 Width: 140 @@ -178,7 +177,7 @@ Container@MUSIC_PANEL: Text: Install Music Container@INSTALL_MUSIC_PANEL: - Logic: CncInstallFromCDLogic + Logic: InstallMusicLogic X: (WINDOW_RIGHT - WIDTH)/2 Y: (WINDOW_BOTTOM - 150)/2 Width: 640 @@ -201,52 +200,37 @@ Container@INSTALL_MUSIC_PANEL: Y: 11 ImageCollection: logos ImageName: install - Container@INSTALLING: - Width: PARENT_RIGHT - Height: PARENT_BOTTOM - Visible: false - Children: - ProgressBar@PROGRESS_BAR: - X: 170 - Y: 45 - Width: PARENT_RIGHT - 185 - Height: 35 - Label@STATUS_LABEL: - X: 170 - Y: 85 - Width: PARENT_RIGHT - 185 - Height: 25 - Align: Left - Container@INSERT_DISK: - Width: PARENT_RIGHT - Height: PARENT_BOTTOM - Visible: false - Children: - Label@MUSIC_DISK_NOT_FOUND: - X: 170 - Y: 35 - Width: PARENT_RIGHT-30 - Height: 25 - Text: Disk not found - Font: Bold - Label@PLEASE_INSERT_MUSIC_DISK: - 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: + Label@INFO: + X: 170 + Y: 35 + Width: PARENT_RIGHT-30 + Height: 25 + Text: The soundtrack is currently unavailable. + Font: Bold + Label@INFO2: + X: 170 + Y: 70 + Width: PARENT_RIGHT-185 + Height: 25 + WordWrap: true + Text: OpenRA can download the music files from the internet, or you can install from the original C&C CDs. + Font: Bold + Button@CANCEL_BUTTON: Key: escape Y: 149 Width: 140 Height: 35 Text: Back - Button@RETRY_BUTTON: + Button@DOWNLOAD_BUTTON: + X: 350 + Y: 149 + Width: 140 + Height: 35 + Text: Download + Button@COPY_FROM_CD_BUTTON: X: 500 Y: 149 Width: 140 Height: 35 - Text: Retry + Text: Use CD diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml index 42928e31d6..d7f27f1565 100644 --- a/mods/cnc/mod.yaml +++ b/mods/cnc/mod.yaml @@ -127,12 +127,22 @@ TileSets: mods/cnc/tilesets/jungle.yaml LoadScreen: CncLoadScreen + Image: mods/cnc/uibits/chrome.png + Text: Loading + +ContentInstaller: + TestFiles: conquer.mix, desert.mix, sounds.mix, speech.mix, temperat.mix, tempicnh.mix, winter.mix + InstallerBackgroundWidget: INSTALL_BACKGROUND InstallerMenuWidget: INSTALL_PANEL FilesToCopy: CONQUER.MIX, DESERT.MIX, SCORES.MIX, SOUNDS.MIX, TEMPERAT.MIX, WINTER.MIX FilesToExtract: speech.mix, tempicnh.mix, transit.mix - InstallerBackgroundWidget: INSTALL_BACKGROUND - TestFiles: conquer.mix, desert.mix, general.mix, sounds.mix, speech.mix, temperat.mix, tempicnh.mix, winter.mix - PackageMirrorList: http://openra.net/packages/cnc-mirrors.txt + PackageMirrorList: http://www.openra.net/packages/cnc-mirrors.txt + DiskTestFiles: conquer.mix, desert.mix, install/setup.z + PackageToExtractFromCD: install/setup.z + ExtractFilesFromCD: speech.mix, tempicnh.mix, transit.mix + CopyFilesFromCD: conquer.mix, desert.mix, general.mix, scores.mix, sounds.mix, temperat.mix, winter.mix + ShippedSoundtracks: 2 + MusicPackageMirrorList: http://www.openra.net/packages/cnc-music-mirrors.txt ServerTraits: LobbyCommands @@ -192,4 +202,4 @@ Missions: SupportsMapsFrom: cnc -NewsUrl: http://openra.net/gamenews \ No newline at end of file +NewsUrl: http://www.openra.net/gamenews diff --git a/mods/d2k/chrome/gameinit.yaml b/mods/d2k/chrome/install.yaml similarity index 99% rename from mods/d2k/chrome/gameinit.yaml rename to mods/d2k/chrome/install.yaml index 4f15639075..3991f8f127 100644 --- a/mods/d2k/chrome/gameinit.yaml +++ b/mods/d2k/chrome/install.yaml @@ -101,7 +101,7 @@ Background@INSTALL_DOWNLOAD_PANEL: Key: escape Background@INSTALL_FROMCD_PANEL: - Logic: D2kInstallFromCDLogic + Logic: InstallFromCDLogic X: (WINDOW_RIGHT - WIDTH)/2 Y: (WINDOW_BOTTOM - HEIGHT)/2 Width: 500 diff --git a/mods/d2k/mod.yaml b/mods/d2k/mod.yaml index a96e0ef6f4..e1ef44bebd 100644 --- a/mods/d2k/mod.yaml +++ b/mods/d2k/mod.yaml @@ -56,7 +56,7 @@ Assemblies: mods/d2k/OpenRA.Mods.D2k.dll ChromeLayout: - mods/d2k/chrome/gameinit.yaml + mods/d2k/chrome/install.yaml mods/d2k/chrome/ingame.yaml mods/ra/chrome/ingame-chat.yaml mods/ra/chrome/ingame-diplomacy.yaml @@ -112,11 +112,18 @@ Translations: LoadScreen: DefaultLoadScreen Image: mods/d2k/uibits/loadscreen.png + Text: Filling Crates..., Breeding Sandworms... + +ContentInstaller: InstallerMenuWidget: INSTALL_PANEL # TODO: check if DATA.R8 is at 1.03 patch level with 4840 frames TestFiles: BLOXBASE.R8, BLOXBAT.R8, BLOXBGBS.R8, BLOXICE.R8, BLOXTREE.R8, BLOXWAST.R8, DATA.R8, SOUND.RS - PackageMirrorList: http://openra.net/packages/d2k-103-mirrors.txt - Text: Filling Crates..., Breeding Sandworms... + PackageMirrorList: http://www.openra.net/packages/d2k-103-mirrors.txt + DiskTestFiles: music/ambush.aud, setup/setup.z + PackageToExtractFromCD: setup/setup.z + ExtractFilesFromCD: SOUND.RS, DATA.R8, MOUSE.R8, BLOXBASE.R8, BLOXBAT.R8, BLOXBGBS.R8, BLOXICE.R8, BLOXTREE.R8, BLOXWAST.R8, A_ECONF1.AUD, A_ECONF2.AUD, A_ECONF3.AUD, A_ESEL1.AUD, A_ESEL2.AUD, A_ESEL3.AUD, A_FCONF1.AUD, A_FCONF2.AUD, A_FCONF3.AUD,A_FCONF4.AUD, A_FSEL1.AUD, A_FSEL2.AUD, A_FSEL3.AUD, A_FSEL4.AUD, AI_1MIN.AUD, AI_2MIN.AUD, AI_3MIN.AUD, AI_4MIN.AUD, AI_5MIN.AUD, AI_ABORT.AUD, AI_ATACK.AUD, AI_BDRDY.AUD, AI_BLOST.AUD, AI_BUILD.AUD, AI_CANCL.AUD, AI_CAPT.AUD, A_ICONF1.AUD, A_ICONF2.AUD, A_ICONF3.AUD, AI_DHRDY.AUD, AI_DPLOY.AUD, AI_ENEMY.AUD, AI_GANEW.AUD, AI_GLOAD.AUD, AI_GSAVE.AUD, AI_GUARD.AUD, AI_HATTK.AUD, AI_HOLD.AUD, AI_LAUNC.AUD, AI_MAP1A.AUD, AI_MAP1B.AUD, AI_MAP1C.AUD, AI_MAP2A.AUD, AI_MAP2B.AUD, AI_MAP2C.AUD, AI_MAP3A.AUD, AI_MAP4A.AUD, AI_MAP5A.AUD, AI_MAP6A.AUD, AI_MAP7A.AUD, AI_MAP8A.AUD, AI_MAP9A.AUD, AI_MEND.AUD, AI_MFAIL.AUD, AI_MONEY.AUD, AI_MWIN.AUD, AI_NEWOP.AUD, AI_NROOM.AUD, AI_ORDER.AUD, AI_PLACE.AUD, AI_POWER.AUD, AI_PREP.AUD, AI_PRMRY.AUD, AI_REINF.AUD, AI_RUN.AUD, A_ISEL1.AUD, A_ISEL2.AUD, A_ISEL3.AUD, AI_SELL.AUD, AI_SILOS.AUD, AI_SPORT.AUD, AI_TRAIN.AUD, AI_ULOST.AUD, AI_UNRDY.AUD, AI_UPGOP.AUD, AI_UPGRD.AUD, AI_WATTK.AUD, AI_WSIGN.AUD, A_VCONF1.AUD, A_VCONF2.AUD, A_VCONF3.AUD, A_VSEL1.AUD, A_VSEL2.AUD, A_VSEL3.AUD, G_SCONF1.AUD, G_SCONF2.AUD, G_SCONF3.AUD, G_SSEL1.AUD, G_SSEL2.AUD, G_SSEL3.AUD, H_ECONF1.AUD, H_ECONF2.AUD, H_ECONF3.AUD, H_ESEL1.AUD, H_ESEL2.AUD, H_ESEL3.AUD, HI_1MIN.AUD, HI_2MIN.AUD, HI_3MIN.AUD, HI_4MIN.AUD, HI_5MIN.AUD, HI_ABORT.AUD, HI_ATACK.AUD, HI_BDRDY.AUD, HI_BLOST.AUD, HI_BUILD.AUD, HI_CANCL.AUD, HI_CAPT.AUD, H_ICONF1.AUD, H_ICONF2.AUD, H_ICONF3.AUD, HI_DHRDY.AUD, HI_DPLOY.AUD, HI_ENEMY.AUD, HI_GANEW.AUD,HI_GLOAD.AUD, HI_GSAVE.AUD, HI_GUARD.AUD, HI_HATTK.AUD, HI_HOLD.AUD, HI_LAUNC.AUD, HI_MAP1A.AUD, HI_MAP1B.AUD, HI_MAP1C.AUD, HI_MAP2A.AUD, HI_MAP2B.AUD, HI_MAP2C.AUD, HI_MAP3A.AUD, HI_MAP3B.AUD, HI_MAP4A.AUD, HI_MAP4B.AUD, HI_MAP5A.AUD, HI_MAP6A.AUD, HI_MAP6B.AUD, HI_MAP7A.AUD, HI_MAP9A.AUD, HI_MAP9.AUD, HI_MEND.AUD, HI_MFAIL.AUD, HI_MONEY.AUD, HI_MWIN.AUD, HI_NEWOP.AUD, HI_NROOM.AUD, HI_ORDER.AUD, HI_PLACE.AUD, HI_POWER.AUD, HI_PREP.AUD, HI_PRMRY.AUD, HI_REINF.AUD, HI_RUN.AUD, H_ISEL1.AUD, H_ISEL2.AUD, H_ISEL3.AUD, HI_SELL.AUD, HI_SILOS.AUD,HI_SPORT.AUD, HI_TRAIN.AUD, HI_ULOST.AUD, HI_UNRDY.AUD, HI_UPGOP.AUD, HI_UPGRD.AUD, HI_WATTK.AUD, HI_WSIGN.AUD, H_VCONF1.AUD, H_VCONF2.AUD, H_VCONF3.AUD, H_VSEL1.AUD, H_VSEL2.AUD, H_VSEL3.AUD, O_ECONF1.AUD, O_ECONF2.AUD, O_ECONF3.AUD, O_ESEL1.AUD, O_ESEL2.AUD, O_ESEL3.AUD, OI_1MIN.AUD, OI_2MIN.AUD, OI_3MIN.AUD, OI_4MIN.AUD, OI_5MIN.AUD, OI_ABORT.AUD, OI_ATACK.AUD, OI_BDRDY.AUD, OI_BLOST.AUD, OI_BUILD.AUD, OI_CANCL.AUD, OI_CAPT.AUD, O_ICONF1.AUD, O_ICONF2.AUD, O_ICONF3.AUD, OI_DHRDY.AUD, OI_DPLOY.AUD, OI_ENEMY.AUD, OI_GANEW.AUD, OI_GLOAD.AUD, OI_GSAVE.AUD, OI_GUARD.AUD, OI_HATTK.AUD, OI_HOLD.AUD, OI_LAUNC.AUD, OI_MAP1A.AUD, OI_MAP1B.AUD, OI_MAP1C.AUD, OI_MAP2A.AUD, OI_MAP2B.AUD, OI_MAP2C.AUD, OI_MAP3A.AUD, OI_MAP4A.AUD, OI_MAP5A.AUD, OI_MAP6A.AUD, OI_MAP7A.AUD, OI_MAP8A.AUD, OI_MAP9A.AUD, OI_MEND.AUD, OI_MFAIL.AUD, OI_MONEY.AUD, OI_MWIN.AUD, OI_NEWOP.AUD, OI_NROOM.AUD, OI_ORDER.AUD, OI_PLACE.AUD, OI_POWER.AUD, OI_PREP.AUD, OI_PRMRY.AUD, OI_REINF.AUD, OI_RUN.AUD, O_ISEL1.AUD, O_ISEL2.AUD, O_ISEL3.AUD, OI_SELL.AUD, OI_SILOS.AUD, OI_SPORT.AUD, OI_TRAIN.AUD, OI_ULOST.AUD, OI_UNRDY.AUD, OI_UPGOP.AUD, OI_UPGRD.AUD, OI_WATTK.AUD, OI_WSIGN.AUD, O_SCONF1.AUD, O_SCONF2.AUD, O_SCONF3.AUD, O_SSEL1.AUD, O_SSEL2.AUD, O_SSEL3.AUD, O_VCONF1.AUD, O_VCONF2.AUD, O_VCONF3.AUD, O_VSEL1.AUD, O_VSEL2.AUD, O_VSEL3.AUD + CopyFilesFromCD: music/ambush.aud, music/arakatak.aud, music/atregain.aud, music/entordos.aud, music/fightpwr.aud, music/fremen.aud, music/hark_bat.aud, music/landsand.aud, music/options.aud, music/plotting.aud, music/risehark.aud, music/robotix.aud, music/score.aud, music/soldappr.aud, music/spicesct.aud, music/undercon.aud, music/waitgame.aud + ShippedSoundtracks: 1 ServerTraits: LobbyCommands @@ -170,4 +177,4 @@ LuaScripts: SupportsMapsFrom: d2k -NewsUrl: http://openra.net/gamenews \ No newline at end of file +NewsUrl: http://www.openra.net/gamenews \ No newline at end of file diff --git a/mods/modchooser/mod.yaml b/mods/modchooser/mod.yaml index 4a290c6bac..d2db930390 100644 --- a/mods/modchooser/mod.yaml +++ b/mods/modchooser/mod.yaml @@ -24,6 +24,7 @@ Notifications: mods/modchooser/notifications.yaml LoadScreen: ModChooserLoadScreen + Image: mods/modchooser/chrome.png ChromeMetrics: mods/modchooser/metrics.yaml @@ -47,4 +48,5 @@ Fonts: TinyBold: Font:FreeSansBold.ttf Size:10 + LobbyDefaults: \ No newline at end of file diff --git a/mods/ra/chrome/gameinit.yaml b/mods/ra/chrome/install.yaml similarity index 98% rename from mods/ra/chrome/gameinit.yaml rename to mods/ra/chrome/install.yaml index 0c7d2c527c..9a4d0aa32e 100644 --- a/mods/ra/chrome/gameinit.yaml +++ b/mods/ra/chrome/install.yaml @@ -2,7 +2,7 @@ Background@INSTALL_PANEL: Logic: InstallLogic X: (WINDOW_RIGHT - WIDTH)/2 Y: (WINDOW_BOTTOM - HEIGHT)/2 - Width: 510 + Width: 500 Height: 160 Children: Label@TITLE: @@ -94,7 +94,7 @@ Background@INSTALL_DOWNLOAD_PANEL: Key: escape Background@INSTALL_FROMCD_PANEL: - Logic: RAInstallFromCDLogic + Logic: InstallFromCDLogic X: (WINDOW_RIGHT - WIDTH)/2 Y: (WINDOW_BOTTOM - HEIGHT)/2 Width: 500 diff --git a/mods/ra/chrome/musicplayer.yaml b/mods/ra/chrome/musicplayer.yaml index d5dfd42257..5189cdc0f8 100644 --- a/mods/ra/chrome/musicplayer.yaml +++ b/mods/ra/chrome/musicplayer.yaml @@ -149,12 +149,69 @@ Background@MUSIC_PANEL: Align: Center Visible: false Text: No Music Installed - Button@BACK_BUTTON: - X: PARENT_RIGHT - 180 + Button@INSTALL_BUTTON: + X: 20 Y: PARENT_BOTTOM - 45 - Width: 160 + Width: 120 + Height: 25 + Text: Install Music + Font: Bold + Button@BACK_BUTTON: + X: PARENT_RIGHT - 140 + Y: PARENT_BOTTOM - 45 + Width: 120 Height: 25 Text: Close Font: Bold Key: escape +Background@INSTALL_MUSIC_PANEL: + Logic: InstallMusicLogic + 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: Install Music + Align: Center + Font: Bold + Label@DESC1: + X: 0 + Y: 50 + Width: PARENT_RIGHT + Height: 25 + Text: The soundtrack is currently unavailable. + Align: Center + Label@DESC2: + X: 0 + Y: 70 + Width: PARENT_RIGHT + Height: 25 + Text: Please choose an installation method. + Align: Center + Button@COPY_FROM_CD_BUTTON: + X: 20 + Y: PARENT_BOTTOM - 45 + Width: 110 + Height: 25 + Text: Use CD + Font: Bold + Button@DOWNLOAD_BUTTON: + X: 140 + Y: PARENT_BOTTOM - 45 + Width: 110 + Height: 25 + Text: Download + Font: Bold + Button@CANCEL_BUTTON: + X: PARENT_RIGHT - 130 + Y: PARENT_BOTTOM - 45 + Width: 110 + Height: 25 + Text: Back + Font: Bold diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index a3e17e6a66..f7b62a84f4 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -69,7 +69,7 @@ Assemblies: mods/d2k/OpenRA.Mods.D2k.dll ChromeLayout: - mods/ra/chrome/gameinit.yaml + mods/ra/chrome/install.yaml mods/ra/chrome/ingame.yaml mods/ra/chrome/ingame-chat.yaml mods/ra/chrome/ingame-diplomacy.yaml @@ -129,11 +129,19 @@ Translations: LoadScreen: DefaultLoadScreen Image: mods/ra/uibits/loadscreen.png - InstallerMenuWidget: INSTALL_PANEL - TestFiles: allies.mix, conquer.mix, general.mix, interior.mix, redalert.mix, russian.mix, scores.mix, snow.mix, sounds.mix, temperat.mix - PackageMirrorList: http://openra.net/packages/ra-mirrors.txt Text: Filling Crates..., Charging Capacitors..., Reticulating Splines..., Planting Trees..., Building Bridges..., Aging Empires..., Compiling EVA..., Constructing Pylons..., Activating Skynet..., Splitting Atoms... +ContentInstaller: + InstallerMenuWidget: INSTALL_PANEL + TestFiles: allies.mix, conquer.mix, interior.mix, redalert.mix, russian.mix, snow.mix, sounds.mix, temperat.mix + PackageMirrorList: http://www.openra.net/packages/ra-mirrors.txt + DiskTestFiles: MAIN.MIX, INSTALL/REDALERT.MIX + PackageToExtractFromCD: MAIN.MIX + ExtractFilesFromCD: conquer.mix, russian.mix, allies.mix, sounds.mix, scores.mix, snow.mix, interior.mix, temperat.mix, general.mix + CopyFilesFromCD: INSTALL/REDALERT.MIX + ShippedSoundtracks: 2 + MusicPackageMirrorList: http://www.openra.net/packages/ra-music-mirrors.txt + ServerTraits: LobbyCommands PlayerPinger @@ -189,4 +197,4 @@ Missions: SupportsMapsFrom: ra -NewsUrl: http://openra.net/gamenews \ No newline at end of file +NewsUrl: http://www.openra.net/gamenews \ No newline at end of file diff --git a/mods/ts/chrome/gameinit.yaml b/mods/ts/chrome/install.yaml similarity index 98% rename from mods/ts/chrome/gameinit.yaml rename to mods/ts/chrome/install.yaml index 7f83536c3e..ad6120e8f8 100644 --- a/mods/ts/chrome/gameinit.yaml +++ b/mods/ts/chrome/install.yaml @@ -2,7 +2,7 @@ Background@INSTALL_PANEL: Logic: InstallLogic X: (WINDOW_RIGHT - WIDTH)/2 Y: (WINDOW_BOTTOM - HEIGHT)/2 - Width: 510 + Width: 500 Height: 160 Children: Label@TITLE: @@ -94,7 +94,7 @@ Background@INSTALL_DOWNLOAD_PANEL: Key: escape Background@INSTALL_FROMCD_PANEL: - Logic: TSInstallFromCDLogic + Logic: InstallFromCDLogic X: (WINDOW_RIGHT - WIDTH)/2 Y: (WINDOW_BOTTOM - HEIGHT)/2 Width: 500 diff --git a/mods/ts/mod.yaml b/mods/ts/mod.yaml index 6321b0a615..d9a0aa62e1 100644 --- a/mods/ts/mod.yaml +++ b/mods/ts/mod.yaml @@ -96,7 +96,7 @@ Assemblies: mods/ts/OpenRA.Mods.TS.dll ChromeLayout: - mods/ts/chrome/gameinit.yaml + mods/ts/chrome/install.yaml mods/ra/chrome/ingame.yaml mods/ra/chrome/ingame-chat.yaml mods/ra/chrome/ingame-diplomacy.yaml @@ -154,10 +154,17 @@ Translations: LoadScreen: DefaultLoadScreen Image: mods/ts/uibits/loadscreen.png + Text: Updating EVA installation..., Changing perspective... + +ContentInstaller: InstallerMenuWidget: INSTALL_PANEL TestFiles: cache.mix, conquer.mix, isosnow.mix, isotemp.mix, local.mix, sidec01.mix, sidec02.mix, sno.mix, snow.mix, sounds.mix, speech01.mix, tem.mix, temperat.mix - PackageMirrorList: http://openra.net/packages/ts-mirrors.txt - Text: Updating EVA installation..., Changing perspective... + PackageMirrorList: http://www.openra.net/packages/ts-mirrors.txt + DiskTestFiles: MULTI.MIX, INSTALL/TIBSUN.MIX + CopyFilesFromCD: INSTALL/TIBSUN.MIX, SCORES.MIX, MULTI.MIX + PackageToExtractFromCD: INSTALL/TIBSUN.MIX:CRC32 + ExtractFilesFromCD: cache.mix, conquer.mix, isosnow.mix, isotemp.mix, local.mix, sidec01.mix, sidec02.mix, sno.mix, snow.mix, sounds.mix, speech01.mix, tem.mix, temperat.mix + ShippedSoundtracks: 2 ServerTraits: LobbyCommands @@ -211,4 +218,4 @@ LuaScripts: SupportsMapsFrom: ts -NewsUrl: http://openra.net/gamenews \ No newline at end of file +NewsUrl: http://www.openra.net/gamenews