#region Copyright & License Information /* * Copyright 2007-2017 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, either version 3 of * the License, or (at your option) any later version. For more * information, see COPYING. */ #endregion using System; using System.Collections; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using OpenRA.FileSystem; using OpenRA.Graphics; using OpenRA.Primitives; namespace OpenRA { public class InstalledMods : IReadOnlyDictionary { readonly Dictionary mods; readonly SheetBuilder sheetBuilder; readonly Dictionary icons = new Dictionary(); public readonly IReadOnlyDictionary Icons; public InstalledMods(string customModPath) { sheetBuilder = new SheetBuilder(SheetType.BGRA, 256); Icons = new ReadOnlyDictionary(icons); mods = GetInstalledMods(customModPath); } static IEnumerable> GetCandidateMods() { // Get mods that are in the game folder. var basePath = Platform.ResolvePath(Path.Combine(".", "mods")); var mods = Directory.GetDirectories(basePath) .Select(x => Pair.New(x.Substring(basePath.Length + 1), x)) .ToList(); foreach (var m in Directory.GetFiles(basePath, "*.oramod")) mods.Add(Pair.New(Path.GetFileNameWithoutExtension(m), m)); // Get mods that are in the support folder. var supportPath = Platform.ResolvePath(Path.Combine("^", "mods")); if (!Directory.Exists(supportPath)) return mods; foreach (var pair in Directory.GetDirectories(supportPath).ToDictionary(x => x.Substring(supportPath.Length + 1))) mods.Add(Pair.New(pair.Key, pair.Value)); foreach (var m in Directory.GetFiles(supportPath, "*.oramod")) mods.Add(Pair.New(Path.GetFileNameWithoutExtension(m), m)); return mods; } Manifest LoadMod(string id, string path) { IReadOnlyPackage package = null; try { if (Directory.Exists(path)) package = new Folder(path); else { try { using (var fileStream = File.OpenRead(path)) package = new ZipFile(fileStream, path); } catch { throw new InvalidDataException(path + " is not a valid mod package"); } } if (!package.Contains("mod.yaml")) throw new InvalidDataException(path + " is not a valid mod package"); using (var stream = package.GetStream("icon.png")) if (stream != null) using (var bitmap = new Bitmap(stream)) icons[id] = sheetBuilder.Add(bitmap); // Mods in the support directory and oramod packages (which are listed later // in the CandidateMods list) override mods in the main install. return new Manifest(id, package); } catch (Exception) { if (package != null) package.Dispose(); return null; } } Dictionary GetInstalledMods(string customModPath) { var ret = new Dictionary(); var candidates = GetCandidateMods(); if (customModPath != null) candidates = candidates.Append(Pair.New(Path.GetFileNameWithoutExtension(customModPath), customModPath)); foreach (var pair in candidates) { var mod = LoadMod(pair.First, pair.Second); // Mods in the support directory and oramod packages (which are listed later // in the CandidateMods list) override mods in the main install. if (mod != null) ret[pair.First] = mod; } return ret; } public Manifest this[string key] { get { return mods[key]; } } public int Count { get { return mods.Count; } } public ICollection Keys { get { return mods.Keys; } } public ICollection Values { get { return mods.Values; } } public bool ContainsKey(string key) { return mods.ContainsKey(key); } public IEnumerator> GetEnumerator() { return mods.GetEnumerator(); } public bool TryGetValue(string key, out Manifest value) { return mods.TryGetValue(key, out value); } IEnumerator IEnumerable.GetEnumerator() { return mods.GetEnumerator(); } } }