From 3261516b511a1b7c195b20d573e6f558b586cc0e Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Fri, 5 Aug 2016 19:41:26 +0100 Subject: [PATCH] Support loading mods from arbitrary locations. --- OpenRA.Game/Game.cs | 12 +++++++++++- OpenRA.Game/InstalledMods.cs | 12 ++++++++---- OpenRA.Game/Support/Arguments.cs | 1 + OpenRA.Server/Program.cs | 16 ++++++++++++++-- OpenRA.Utility/Program.cs | 18 +++++++++++++----- 5 files changed, 47 insertions(+), 12 deletions(-) diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index d5190cfa98..a2078cc1d8 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -244,6 +244,16 @@ namespace OpenRA { Console.WriteLine("Platform is {0}", Platform.CurrentPlatform); + // Special case handling of Game.Mod argument: if it matches a real filesystem path + // then we use this to override the mod search path, and replace it with the mod id + var modArgument = args.GetValue("Game.Mod", null); + string customModPath = null; + if (modArgument != null && (File.Exists(modArgument) || Directory.Exists(modArgument))) + { + customModPath = modArgument; + args.ReplaceValue("Game.Mod", Path.GetFileNameWithoutExtension(modArgument)); + } + InitializeSettings(args); Log.AddChannel("perf", "perf.log"); @@ -303,7 +313,7 @@ namespace OpenRA GlobalChat = new GlobalChat(); - Mods = new InstalledMods(); + Mods = new InstalledMods(customModPath); Console.WriteLine("Available mods:"); foreach (var mod in Mods) Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Metadata.Title, mod.Value.Metadata.Version); diff --git a/OpenRA.Game/InstalledMods.cs b/OpenRA.Game/InstalledMods.cs index 2fcbc6d5bb..2c64faf36b 100644 --- a/OpenRA.Game/InstalledMods.cs +++ b/OpenRA.Game/InstalledMods.cs @@ -23,9 +23,9 @@ namespace OpenRA { readonly Dictionary mods; - public InstalledMods() + public InstalledMods(string customModPath) { - mods = GetInstalledMods(); + mods = GetInstalledMods(customModPath); } static IEnumerable> GetCandidateMods() @@ -89,10 +89,14 @@ namespace OpenRA } } - static Dictionary GetInstalledMods() + static Dictionary GetInstalledMods(string customModPath) { var ret = new Dictionary(); - foreach (var pair in GetCandidateMods()) + 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); diff --git a/OpenRA.Game/Support/Arguments.cs b/OpenRA.Game/Support/Arguments.cs index bfda87411d..5ea78e0c40 100644 --- a/OpenRA.Game/Support/Arguments.cs +++ b/OpenRA.Game/Support/Arguments.cs @@ -35,5 +35,6 @@ namespace OpenRA public bool Contains(string key) { return args.ContainsKey(key); } public string GetValue(string key, string defaultValue) { return Contains(key) ? args[key] : defaultValue; } + public void ReplaceValue(string key, string value) { args[key] = value; } } } diff --git a/OpenRA.Server/Program.cs b/OpenRA.Server/Program.cs index 27c89fc0c1..94e12c1dcd 100644 --- a/OpenRA.Server/Program.cs +++ b/OpenRA.Server/Program.cs @@ -10,6 +10,7 @@ #endregion using System; +using System.IO; using System.Net; using System.Threading; using OpenRA.Support; @@ -20,18 +21,29 @@ namespace OpenRA.Server { static void Main(string[] args) { + var arguments = new Arguments(args); Log.AddChannel("debug", "dedicated-debug.log"); Log.AddChannel("perf", "dedicated-perf.log"); Log.AddChannel("server", "dedicated-server.log"); Log.AddChannel("nat", "dedicated-nat.log"); + // Special case handling of Game.Mod argument: if it matches a real filesystem path + // then we use this to override the mod search path, and replace it with the mod id + var modArgument = arguments.GetValue("Game.Mod", null); + string customModPath = null; + if (modArgument != null && (File.Exists(modArgument) || Directory.Exists(modArgument))) + { + customModPath = modArgument; + arguments.ReplaceValue("Game.Mod", Path.GetFileNameWithoutExtension(modArgument)); + } + // HACK: The engine code assumes that Game.Settings is set. // This isn't nearly as bad as ModData, but is still not very nice. - Game.InitializeSettings(new Arguments(args)); + Game.InitializeSettings(arguments); var settings = Game.Settings.Server; var mod = Game.Settings.Game.Mod; - var mods = new InstalledMods(); + var mods = new InstalledMods(customModPath); // HACK: The engine code *still* assumes that Game.ModData is set var modData = Game.ModData = new ModData(mods[mod], mods); diff --git a/OpenRA.Utility/Program.cs b/OpenRA.Utility/Program.cs index 779dafc278..4ebe8f534e 100644 --- a/OpenRA.Utility/Program.cs +++ b/OpenRA.Utility/Program.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Runtime.Serialization; @@ -43,22 +44,29 @@ namespace OpenRA Log.AddChannel("debug", null); Game.InitializeSettings(Arguments.Empty); - var mods = new InstalledMods(); if (args.Length == 0) { - PrintUsage(mods, null); + PrintUsage(new InstalledMods(null), null); return; } - var modName = args[0]; - if (!mods.Keys.Contains(modName)) + var modId = args[0]; + string customModPath = null; + if (File.Exists(modId) || Directory.Exists(modId)) + { + customModPath = modId; + modId = Path.GetFileNameWithoutExtension(modId); + } + + var mods = new InstalledMods(customModPath); + if (!mods.Keys.Contains(modId)) { PrintUsage(mods, null); return; } - var modData = new ModData(mods[modName], mods); + var modData = new ModData(mods[modId], mods); var utility = new Utility(modData, mods); args = args.Skip(1).ToArray(); var actions = new UtilityActions();