summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/StardewModdingAPI/Framework/ModLoading/IModMetadata.cs39
-rw-r--r--src/StardewModdingAPI/Framework/ModLoading/ModMetadata.cs14
-rw-r--r--src/StardewModdingAPI/Framework/ModLoading/ModMetadataStatus.cs12
-rw-r--r--src/StardewModdingAPI/Framework/ModLoading/ModResolver.cs22
-rw-r--r--src/StardewModdingAPI/Program.cs12
-rw-r--r--src/StardewModdingAPI/StardewModdingAPI.csproj2
6 files changed, 72 insertions, 29 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);
diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs
index 37e1e000..9ccb4ddc 100644
--- a/src/StardewModdingAPI/Program.cs
+++ b/src/StardewModdingAPI/Program.cs
@@ -317,12 +317,12 @@ namespace StardewModdingAPI
ModResolver resolver = new ModResolver();
// load manifests
- ModMetadata[] mods = resolver.ReadManifests(Constants.ModPath, new JsonHelper(), this.Settings.ModCompatibility).ToArray();
+ IModMetadata[] mods = resolver.ReadManifests(Constants.ModPath, new JsonHelper(), this.Settings.ModCompatibility).ToArray();
resolver.ValidateManifests(mods);
// check for deprecated metadata
IList<Action> deprecationWarnings = new List<Action>();
- foreach (ModMetadata mod in mods)
+ foreach (IModMetadata mod in mods)
{
// missing unique ID
if (string.IsNullOrWhiteSpace(mod.Manifest.UniqueID))
@@ -428,7 +428,7 @@ namespace StardewModdingAPI
string[] fields = entry.Value.Split('/');
if (fields.Length < SObject.objectInfoDescriptionIndex + 1)
{
- LogIssue(entry.Key, $"too few fields for an object");
+ LogIssue(entry.Key, "too few fields for an object");
issuesFound = true;
continue;
}
@@ -493,16 +493,16 @@ namespace StardewModdingAPI
/// <param name="contentManager">The content manager to use for mod content.</param>
/// <param name="deprecationWarnings">A list to populate with any deprecation warnings.</param>
/// <returns>Returns the number of mods successfully loaded.</returns>
- private int LoadMods(ModMetadata[] mods, JsonHelper jsonHelper, SContentManager contentManager, IList<Action> deprecationWarnings)
+ private int LoadMods(IModMetadata[] mods, JsonHelper jsonHelper, SContentManager contentManager, IList<Action> deprecationWarnings)
{
this.Monitor.Log("Loading mods...");
- void LogSkip(ModMetadata mod, string reasonPhrase, LogLevel level = LogLevel.Error) => this.Monitor.Log($"Skipped {mod.DisplayName} because {reasonPhrase}", level);
+ void LogSkip(IModMetadata mod, string reasonPhrase, LogLevel level = LogLevel.Error) => this.Monitor.Log($"Skipped {mod.DisplayName} because {reasonPhrase}", level);
// load mod assemblies
int modsLoaded = 0;
AssemblyLoader modAssemblyLoader = new AssemblyLoader(Constants.TargetPlatform, this.Monitor);
AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => modAssemblyLoader.ResolveAssembly(e.Name);
- foreach (ModMetadata metadata in mods)
+ foreach (IModMetadata metadata in mods)
{
// validate status
if (metadata.Status == ModMetadataStatus.Failed)
diff --git a/src/StardewModdingAPI/StardewModdingAPI.csproj b/src/StardewModdingAPI/StardewModdingAPI.csproj
index 2424f438..a7362153 100644
--- a/src/StardewModdingAPI/StardewModdingAPI.csproj
+++ b/src/StardewModdingAPI/StardewModdingAPI.csproj
@@ -121,6 +121,8 @@
<Compile Include="Events\EventArgsStringChanged.cs" />
<Compile Include="Events\GameEvents.cs" />
<Compile Include="Events\GraphicsEvents.cs" />
+ <Compile Include="Framework\ModLoading\IModMetadata.cs" />
+ <Compile Include="Framework\ModLoading\ModMetadataStatus.cs" />
<Compile Include="Framework\ModLoading\ModResolver.cs" />
<Compile Include="Framework\ModLoading\AssemblyDefinitionResolver.cs" />
<Compile Include="Framework\ModLoading\AssemblyParseResult.cs" />