diff options
author | Jesse Plamondon-Willard <github@jplamondonw.com> | 2017-05-13 21:36:50 -0400 |
---|---|---|
committer | Jesse Plamondon-Willard <github@jplamondonw.com> | 2017-05-13 21:36:50 -0400 |
commit | 53547a8ca3a5cba45bd0a5a478d0f40daa282888 (patch) | |
tree | d0ccbdf5b8fed2edc43c83724acc9eb734939c44 /src/StardewModdingAPI/Framework/ModLoading | |
parent | 7f368aa8896baa551aa156a8e67e9dd16416022d (diff) | |
download | SMAPI-53547a8ca3a5cba45bd0a5a478d0f40daa282888.tar.gz SMAPI-53547a8ca3a5cba45bd0a5a478d0f40daa282888.tar.bz2 SMAPI-53547a8ca3a5cba45bd0a5a478d0f40daa282888.zip |
pass API version into mod metadata validation to simplify unit testing (#285)
Diffstat (limited to 'src/StardewModdingAPI/Framework/ModLoading')
4 files changed, 64 insertions, 23 deletions
diff --git a/src/StardewModdingAPI/Framework/ModLoading/IModMetadata.cs b/src/StardewModdingAPI/Framework/ModLoading/IModMetadata.cs new file mode 100644 index 00000000..3771ffdd --- /dev/null +++ b/src/StardewModdingAPI/Framework/ModLoading/IModMetadata.cs @@ -0,0 +1,39 @@ +using StardewModdingAPI.Framework.Models; + +namespace StardewModdingAPI.Framework.ModLoading +{ + /// <summary>Metadata for a mod.</summary> + internal interface IModMetadata + { + /********* + ** Accessors + *********/ + /// <summary>The mod's display name.</summary> + string DisplayName { get; } + + /// <summary>The mod's full directory path.</summary> + string DirectoryPath { get; } + + /// <summary>The mod manifest.</summary> + IManifest Manifest { get; } + + /// <summary>Optional metadata about a mod version that SMAPI should assume is compatible or broken, regardless of whether it detects incompatible code.</summary> + ModCompatibility Compatibility { get; } + + /// <summary>The metadata resolution status.</summary> + ModMetadataStatus Status { get; } + + /// <summary>The reason the metadata is invalid, if any.</summary> + string Error { get; } + + + /********* + ** Public methods + *********/ + /// <summary>Set the mod status.</summary> + /// <param name="status">The metadata resolution status.</param> + /// <param name="error">The reason the metadata is invalid, if any.</param> + /// <returns>Return the instance for chaining.</returns> + IModMetadata SetStatus(ModMetadataStatus status, string error = null); + } +} diff --git a/src/StardewModdingAPI/Framework/ModLoading/ModMetadata.cs b/src/StardewModdingAPI/Framework/ModLoading/ModMetadata.cs index 5ec2d4e0..7b25e090 100644 --- a/src/StardewModdingAPI/Framework/ModLoading/ModMetadata.cs +++ b/src/StardewModdingAPI/Framework/ModLoading/ModMetadata.cs @@ -3,7 +3,7 @@ namespace StardewModdingAPI.Framework.ModLoading { /// <summary>Metadata for a mod.</summary> - internal class ModMetadata + internal class ModMetadata : IModMetadata { /********* ** Accessors @@ -47,21 +47,11 @@ namespace StardewModdingAPI.Framework.ModLoading /// <param name="status">The metadata resolution status.</param> /// <param name="error">The reason the metadata is invalid, if any.</param> /// <returns>Return the instance for chaining.</returns> - public ModMetadata SetStatus(ModMetadataStatus status, string error = null) + public IModMetadata SetStatus(ModMetadataStatus status, string error = null) { this.Status = status; this.Error = error; return this; } } - - /// <summary>Indicates the status of a mod's metadata resolution.</summary> - internal enum ModMetadataStatus - { - /// <summary>The mod has been found, but hasn't been processed yet.</summary> - Found, - - /// <summary>The mod cannot be loaded.</summary> - Failed - } } diff --git a/src/StardewModdingAPI/Framework/ModLoading/ModMetadataStatus.cs b/src/StardewModdingAPI/Framework/ModLoading/ModMetadataStatus.cs new file mode 100644 index 00000000..1b2b0b55 --- /dev/null +++ b/src/StardewModdingAPI/Framework/ModLoading/ModMetadataStatus.cs @@ -0,0 +1,12 @@ +namespace StardewModdingAPI.Framework.ModLoading +{ + /// <summary>Indicates the status of a mod's metadata resolution.</summary> + internal enum ModMetadataStatus + { + /// <summary>The mod has been found, but hasn't been processed yet.</summary> + Found, + + /// <summary>The mod cannot be loaded.</summary> + Failed + } +}
\ No newline at end of file diff --git a/src/StardewModdingAPI/Framework/ModLoading/ModResolver.cs b/src/StardewModdingAPI/Framework/ModLoading/ModResolver.cs index 9b26e8b0..a3d4ce3e 100644 --- a/src/StardewModdingAPI/Framework/ModLoading/ModResolver.cs +++ b/src/StardewModdingAPI/Framework/ModLoading/ModResolver.cs @@ -18,7 +18,7 @@ namespace StardewModdingAPI.Framework.ModLoading /// <param name="jsonHelper">The JSON helper with which to read manifests.</param> /// <param name="compatibilityRecords">Metadata about mods that SMAPI should assume is compatible or broken, regardless of whether it detects incompatible code.</param> /// <returns>Returns the manifests by relative folder.</returns> - public IEnumerable<ModMetadata> ReadManifests(string rootPath, JsonHelper jsonHelper, IEnumerable<ModCompatibility> compatibilityRecords) + public IEnumerable<IModMetadata> ReadManifests(string rootPath, JsonHelper jsonHelper, IEnumerable<ModCompatibility> compatibilityRecords) { compatibilityRecords = compatibilityRecords.ToArray(); foreach (DirectoryInfo modDir in this.GetModFolders(rootPath)) @@ -75,9 +75,9 @@ namespace StardewModdingAPI.Framework.ModLoading /// <summary>Validate manifest metadata.</summary> /// <param name="mods">The mod manifests to validate.</param> - public void ValidateManifests(IEnumerable<ModMetadata> mods) + public void ValidateManifests(IEnumerable<IModMetadata> mods) { - foreach (ModMetadata mod in mods) + foreach (IModMetadata mod in mods) { // skip if already failed if (mod.Status == ModMetadataStatus.Failed) @@ -127,12 +127,12 @@ namespace StardewModdingAPI.Framework.ModLoading /// <summary>Sort the given mods by the order they should be loaded.</summary> /// <param name="mods">The mods to process.</param> - public IEnumerable<ModMetadata> ProcessDependencies(IEnumerable<ModMetadata> mods) + public IEnumerable<IModMetadata> ProcessDependencies(IEnumerable<IModMetadata> mods) { var unsortedMods = mods.ToList(); - var sortedMods = new Stack<ModMetadata>(); + var sortedMods = new Stack<IModMetadata>(); var visitedMods = new bool[unsortedMods.Count]; - var currentChain = new List<ModMetadata>(); + var currentChain = new List<IModMetadata>(); bool success = true; for (int index = 0; index < unsortedMods.Count; index++) @@ -162,7 +162,7 @@ namespace StardewModdingAPI.Framework.ModLoading /// <param name="currentChain">The current change of mod dependencies.</param> /// <param name="unsortedMods">The mods remaining to sort.</param> /// <returns>Returns whether the mod can be loaded.</returns> - private bool ProcessDependencies(int modIndex, bool[] visitedMods, Stack<ModMetadata> sortedMods, List<ModMetadata> currentChain, List<ModMetadata> unsortedMods) + private bool ProcessDependencies(int modIndex, bool[] visitedMods, Stack<IModMetadata> sortedMods, List<IModMetadata> currentChain, List<IModMetadata> unsortedMods) { // visit mod if (visitedMods[modIndex]) @@ -170,7 +170,7 @@ namespace StardewModdingAPI.Framework.ModLoading visitedMods[modIndex] = true; // mod already failed - ModMetadata mod = unsortedMods[modIndex]; + IModMetadata mod = unsortedMods[modIndex]; if (mod.Status == ModMetadataStatus.Failed) return false; @@ -194,7 +194,7 @@ namespace StardewModdingAPI.Framework.ModLoading } // get mods which should be loaded before this one - ModMetadata[] modsToLoadFirst = + IModMetadata[] modsToLoadFirst = ( from unsorted in unsortedMods where mod.Manifest.Dependencies.Any(required => required.UniqueID == unsorted.Manifest.UniqueID) @@ -203,7 +203,7 @@ namespace StardewModdingAPI.Framework.ModLoading .ToArray(); // detect circular references - ModMetadata circularReferenceMod = currentChain.FirstOrDefault(modsToLoadFirst.Contains); + IModMetadata circularReferenceMod = currentChain.FirstOrDefault(modsToLoadFirst.Contains); if (circularReferenceMod != null) { mod.SetStatus(ModMetadataStatus.Failed, $"its dependencies have a circular reference: {string.Join(" => ", currentChain.Select(p => p.DisplayName))} => {circularReferenceMod.DisplayName})."); @@ -212,7 +212,7 @@ namespace StardewModdingAPI.Framework.ModLoading currentChain.Add(mod); // recursively sort dependencies - foreach (ModMetadata requiredMod in modsToLoadFirst) + foreach (IModMetadata requiredMod in modsToLoadFirst) { int index = unsortedMods.IndexOf(requiredMod); success = this.ProcessDependencies(index, visitedMods, sortedMods, currentChain, unsortedMods); |