Read mod registrations from system support dir.

This commit is contained in:
Paul Chote
2017-06-22 19:52:36 +01:00
committed by reaperrr
parent e69f129fed
commit 739f357090
2 changed files with 93 additions and 60 deletions

View File

@@ -16,10 +16,12 @@ using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Primitives;
namespace OpenRA namespace OpenRA
{ {
[Flags]
enum ModRegistration { User = 1, System = 2 }
public class ExternalMod public class ExternalMod
{ {
public readonly string Id; public readonly string Id;
@@ -43,22 +45,27 @@ namespace OpenRA
{ {
sheetBuilder = new SheetBuilder(SheetType.BGRA, 256); sheetBuilder = new SheetBuilder(SheetType.BGRA, 256);
// Load registered mods // If the player has defined a local support directory (in the game directory)
var supportPath = Platform.ResolvePath(Path.Combine("^", "ModMetadata")); // then this will override both the regular and system support dirs
if (!Directory.Exists(supportPath)) var sources = new[] { Platform.SystemSupportDir, Platform.SupportDir };
return; foreach (var source in sources.Distinct())
foreach (var path in Directory.GetFiles(supportPath, "*.yaml"))
{ {
try var metadataPath = Path.Combine(source, "ModMetadata");
if (!Directory.Exists(metadataPath))
continue;
foreach (var path in Directory.GetFiles(metadataPath, "*.yaml"))
{ {
var yaml = MiniYaml.FromStream(File.OpenRead(path), path).First().Value; try
LoadMod(yaml, path); {
} var yaml = MiniYaml.FromStream(File.OpenRead(path), path).First().Value;
catch (Exception e) LoadMod(yaml, path);
{ }
Log.Write("debug", "Failed to parse mod metadata file '{0}'", path); catch (Exception e)
Log.Write("debug", e.ToString()); {
Log.Write("debug", "Failed to parse mod metadata file '{0}'", path);
Log.Write("debug", e.ToString());
}
} }
} }
} }
@@ -80,7 +87,7 @@ namespace OpenRA
mods[key] = mod; mods[key] = mod;
} }
internal void Register(Manifest mod, string launchPath) internal void Register(Manifest mod, string launchPath, ModRegistration registration)
{ {
if (mod.Metadata.Hidden) if (mod.Metadata.Hidden)
return; return;
@@ -104,20 +111,33 @@ namespace OpenRA
})) }))
}; };
var supportPath = Platform.ResolvePath(Path.Combine("^", "ModMetadata")); var sources = new List<string>();
if (registration.HasFlag(ModRegistration.System))
sources.Add(Platform.SystemSupportDir);
try if (registration.HasFlag(ModRegistration.User))
{ sources.Add(Platform.SupportDir);
// Make sure the mod is available for this session, even if saving it fails
LoadMod(yaml.First().Value);
Directory.CreateDirectory(supportPath); // Make sure the mod is available for this session, even if saving it fails
File.WriteAllLines(Path.Combine(supportPath, key + ".yaml"), yaml.ToLines(false).ToArray()); LoadMod(yaml.First().Value);
}
catch (Exception e) foreach (var source in sources.Distinct())
{ {
Log.Write("debug", "Failed to register current mod metadata"); if (!Directory.Exists(source))
Log.Write("debug", e.ToString()); continue;
var metadataPath = Path.Combine(source, "ModMetadata");
try
{
Directory.CreateDirectory(metadataPath);
File.WriteAllLines(Path.Combine(metadataPath, key + ".yaml"), yaml.ToLines(false).ToArray());
}
catch (Exception e)
{
Log.Write("debug", "Failed to register current mod metadata");
Log.Write("debug", e.ToString());
}
} }
} }
@@ -128,43 +148,56 @@ namespace OpenRA
/// * Filename doesn't match internal key /// * Filename doesn't match internal key
/// * Fails to parse as a mod registration /// * Fails to parse as a mod registration
/// </summary> /// </summary>
internal void ClearInvalidRegistrations(ExternalMod activeMod) internal void ClearInvalidRegistrations(ExternalMod activeMod, ModRegistration registration)
{ {
var metadataPath = Platform.ResolvePath(Path.Combine("^", "ModMetadata")); var sources = new List<string>();
foreach (var path in Directory.GetFiles(metadataPath, "*.yaml")) if (registration.HasFlag(ModRegistration.System))
sources.Add(Platform.SystemSupportDir);
if (registration.HasFlag(ModRegistration.User))
sources.Add(Platform.SupportDir);
foreach (var source in sources.Distinct())
{ {
string modKey = null; var metadataPath = Path.Combine(source, "ModMetadata");
try if (!Directory.Exists(metadataPath))
{ continue;
var yaml = MiniYaml.FromStream(File.OpenRead(path), path).First().Value;
var m = FieldLoader.Load<ExternalMod>(yaml);
modKey = ExternalMod.MakeKey(m);
// Continue to the next entry if this one is valid foreach (var path in Directory.GetFiles(metadataPath, "*.yaml"))
if (File.Exists(m.LaunchPath) && Path.GetFileNameWithoutExtension(path) == modKey &&
!(activeMod != null && m.LaunchPath == activeMod.LaunchPath && m.Id == activeMod.Id && m.Version != activeMod.Version))
continue;
}
catch (Exception e)
{ {
Log.Write("debug", "Failed to parse mod metadata file '{0}'", path); string modKey = null;
Log.Write("debug", e.ToString()); try
} {
var yaml = MiniYaml.FromStream(File.OpenRead(path), path).First().Value;
var m = FieldLoader.Load<ExternalMod>(yaml);
modKey = ExternalMod.MakeKey(m);
// Remove from the ingame mod switcher // Continue to the next entry if this one is valid
if (Path.GetFileNameWithoutExtension(path) == modKey) if (File.Exists(m.LaunchPath) && Path.GetFileNameWithoutExtension(path) == modKey &&
mods.Remove(modKey); !(activeMod != null && m.LaunchPath == activeMod.LaunchPath && m.Id == activeMod.Id && m.Version != activeMod.Version))
continue;
}
catch (Exception e)
{
Log.Write("debug", "Failed to parse mod metadata file '{0}'", path);
Log.Write("debug", e.ToString());
}
// Remove stale or corrupted metadata // Remove from the ingame mod switcher
try if (Path.GetFileNameWithoutExtension(path) == modKey)
{ mods.Remove(modKey);
File.Delete(path);
Log.Write("debug", "Removed invalid mod metadata file '{0}'", path); // Remove stale or corrupted metadata
} try
catch (Exception e) {
{ File.Delete(path);
Log.Write("debug", "Failed to remove mod metadata file '{0}'", path); Log.Write("debug", "Removed invalid mod metadata file '{0}'", path);
Log.Write("debug", e.ToString()); }
catch (Exception e)
{
Log.Write("debug", "Failed to remove mod metadata file '{0}'", path);
Log.Write("debug", e.ToString());
}
} }
} }
} }

View File

@@ -350,11 +350,11 @@ namespace OpenRA
if (launchPath.First() == '"' && launchPath.Last() == '"') if (launchPath.First() == '"' && launchPath.Last() == '"')
launchPath = launchPath.Substring(1, launchPath.Length - 2); launchPath = launchPath.Substring(1, launchPath.Length - 2);
ExternalMods.Register(Mods[modID], launchPath); ExternalMods.Register(Mods[modID], launchPath, ModRegistration.User);
ExternalMod activeMod; ExternalMod activeMod;
if (ExternalMods.TryGetValue(ExternalMod.MakeKey(Mods[modID]), out activeMod)) if (ExternalMods.TryGetValue(ExternalMod.MakeKey(Mods[modID]), out activeMod))
ExternalMods.ClearInvalidRegistrations(activeMod); ExternalMods.ClearInvalidRegistrations(activeMod, ModRegistration.User);
} }
Console.WriteLine("External mods:"); Console.WriteLine("External mods:");