diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index 2cb2a90798..bb3e8a57e4 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -293,7 +293,7 @@ namespace OpenRA public static bool IsModInstalled(string modId) { - return Manifest.AllMods[modId].RequiresMods.All(IsModInstalled); + return ModMetadata.AllMods[modId].RequiresMods.All(IsModInstalled); } public static bool IsModInstalled(KeyValuePair mod) diff --git a/OpenRA.Game/Manifest.cs b/OpenRA.Game/Manifest.cs index 0342c92f84..fa53465508 100644 --- a/OpenRA.Game/Manifest.cs +++ b/OpenRA.Game/Manifest.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using OpenRA.FileSystem; using OpenRA.Primitives; namespace OpenRA @@ -32,8 +33,6 @@ namespace OpenRA /// Describes what is to be loaded in order to run a mod. public class Manifest { - public static readonly Dictionary AllMods = LoadMods(); - public readonly ModMetadata Mod; public readonly string[] Packages, Rules, ServerTraits, @@ -60,13 +59,11 @@ namespace OpenRA readonly TypeDictionary modules = new TypeDictionary(); readonly Dictionary yaml; - public Manifest(string modId, string modPath = null) + public Manifest(string modId) { - if (modPath == null) - modPath = ModMetadata.CandidateModPaths[modId]; + var package = ModMetadata.AllMods[modId].Package; - var path = Path.Combine(modPath, "mod.yaml"); - yaml = new MiniYaml(null, MiniYaml.FromFile(path)).ToDictionary(); + yaml = new MiniYaml(null, MiniYaml.FromStream(package.GetStream("mod.yaml"))).ToDictionary(); Mod = FieldLoader.Load(yaml["Metadata"]); Mod.Id = modId; @@ -200,28 +197,5 @@ namespace OpenRA return module; } - - static Dictionary LoadMods() - { - var ret = new Dictionary(); - foreach (var mod in ModMetadata.CandidateModPaths) - { - if (!File.Exists(Path.Combine(mod.Value, "mod.yaml"))) - continue; - - try - { - var manifest = new Manifest(mod.Key, mod.Value); - ret.Add(mod.Key, manifest); - } - catch (Exception ex) - { - Log.Write("debug", "An exception occurred while trying to load mod {0}:", mod); - Log.Write("debug", ex.ToString()); - } - } - - return ret; - } } } diff --git a/OpenRA.Game/ModMetadata.cs b/OpenRA.Game/ModMetadata.cs index 09c30e3942..d7e6087f02 100644 --- a/OpenRA.Game/ModMetadata.cs +++ b/OpenRA.Game/ModMetadata.cs @@ -12,12 +12,12 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using OpenRA.FileSystem; namespace OpenRA { public class ModMetadata { - public static readonly Dictionary CandidateModPaths = GetCandidateMods(); public static readonly Dictionary AllMods = ValidateMods(); public string Id; @@ -26,26 +26,40 @@ namespace OpenRA public string Version; public string Author; public bool Hidden; + + public Dictionary RequiresMods; public ContentInstaller Content; + public IReadOnlyPackage Package; static Dictionary ValidateMods() { var ret = new Dictionary(); - foreach (var pair in CandidateModPaths) + foreach (var pair in GetCandidateMods()) { try { - var yamlPath = Path.Combine(pair.Value, "mod.yaml"); - if (!File.Exists(yamlPath)) + IReadOnlyPackage package = null; + if (Directory.Exists(pair.Value)) + package = new Folder(pair.Value); + else + throw new InvalidDataException(pair.Value + " is not a valid mod package"); + + if (!package.Contains("mod.yaml")) continue; - var yaml = new MiniYaml(null, MiniYaml.FromFile(yamlPath)); + var yaml = new MiniYaml(null, MiniYaml.FromStream(package.GetStream("mod.yaml"))); var nd = yaml.ToDictionary(); if (!nd.ContainsKey("Metadata")) continue; var metadata = FieldLoader.Load(nd["Metadata"]); metadata.Id = pair.Key; + metadata.Package = package; + + if (nd.ContainsKey("RequiresMods")) + metadata.RequiresMods = nd["RequiresMods"].ToDictionary(my => my.Value); + else + metadata.RequiresMods = new Dictionary(); if (nd.ContainsKey("ContentInstaller")) metadata.Content = FieldLoader.Load(nd["ContentInstaller"]); diff --git a/OpenRA.Game/Platform.cs b/OpenRA.Game/Platform.cs index 260684d20e..0b99287f61 100644 --- a/OpenRA.Game/Platform.cs +++ b/OpenRA.Game/Platform.cs @@ -124,7 +124,7 @@ namespace OpenRA { // Resolve mod package paths. if (ModMetadata.AllMods.ContainsKey(package)) - package = ModMetadata.CandidateModPaths[package]; + package = ModMetadata.AllMods[package].Package.Name; return ResolvePath(Path.Combine(package, target)); } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Installation/InstallModLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Installation/InstallModLogic.cs index b918827bdb..91e103c164 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Installation/InstallModLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Installation/InstallModLogic.cs @@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { var panel = widget.Get("INSTALL_MOD_PANEL"); - var mods = Manifest.AllMods[modId].RequiresMods.Where(m => !Game.IsModInstalled(m)).Select(m => "{0} ({1})".F(m.Key, m.Value)); + var mods = ModMetadata.AllMods[modId].RequiresMods.Where(m => !Game.IsModInstalled(m)).Select(m => "{0} ({1})".F(m.Key, m.Value)); var text = string.Join(", ", mods); panel.Get("MOD_LIST").Text = text; diff --git a/OpenRA.Mods.Common/Widgets/Logic/ModBrowserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/ModBrowserLogic.cs index cc71d41d9f..747c5eb58f 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/ModBrowserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/ModBrowserLogic.cs @@ -82,17 +82,19 @@ namespace OpenRA.Mods.Common.Widgets.Logic { try { - using (var preview = new Bitmap(Platform.ResolvePath(ModMetadata.CandidateModPaths[mod.Id], "preview.png"))) - if (preview.Width == 296 && preview.Height == 196) - previews.Add(mod.Id, sheetBuilder.Add(preview)); + using (var stream = ModMetadata.AllMods[mod.Id].Package.GetStream("preview.png")) + using (var preview = new Bitmap(stream)) + if (preview.Width == 296 && preview.Height == 196) + previews.Add(mod.Id, sheetBuilder.Add(preview)); } catch (Exception) { } try { - using (var logo = new Bitmap(Platform.ResolvePath(ModMetadata.CandidateModPaths[mod.Id], "logo.png"))) - if (logo.Width == 96 && logo.Height == 96) - logos.Add(mod.Id, sheetBuilder.Add(logo)); + using (var stream = ModMetadata.AllMods[mod.Id].Package.GetStream("logo.png")) + using (var logo = new Bitmap(stream)) + if (logo.Width == 96 && logo.Height == 96) + logos.Add(mod.Id, sheetBuilder.Add(logo)); } catch (Exception) { } }