Added ModsToLoadFirst/Last to SMAPI config, along with the implementation
This commit is contained in:
parent
9ae69245b3
commit
bb2fde1829
|
@ -245,7 +245,9 @@ namespace StardewModdingAPI.Framework.ModLoading
|
||||||
/// <summary>Sort the given mods by the order they should be loaded.</summary>
|
/// <summary>Sort the given mods by the order they should be loaded.</summary>
|
||||||
/// <param name="mods">The mods to process.</param>
|
/// <param name="mods">The mods to process.</param>
|
||||||
/// <param name="modDatabase">Handles access to SMAPI's internal mod metadata list.</param>
|
/// <param name="modDatabase">Handles access to SMAPI's internal mod metadata list.</param>
|
||||||
public IEnumerable<IModMetadata> ProcessDependencies(IEnumerable<IModMetadata> mods, ModDatabase modDatabase)
|
/// <param name="modIdsToLoadFirst">The mod IDs SMAPI should try to load first, before any other mods not included in this list.</param>
|
||||||
|
/// <param name="modIdsToLoadLast">The mod IDs SMAPI should try to load last, after all other mods not included in this list.</param>
|
||||||
|
public IEnumerable<IModMetadata> ProcessDependencies(IEnumerable<IModMetadata> mods, IReadOnlyList<string> modIdsToLoadFirst, IReadOnlyList<string> modIdsToLoadLast, ModDatabase modDatabase)
|
||||||
{
|
{
|
||||||
// initialize metadata
|
// initialize metadata
|
||||||
mods = mods.ToArray();
|
mods = mods.ToArray();
|
||||||
|
@ -260,8 +262,18 @@ namespace StardewModdingAPI.Framework.ModLoading
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort mods
|
// sort mods
|
||||||
foreach (IModMetadata mod in mods)
|
IModMetadata[] allMods = mods.ToArray();
|
||||||
this.ProcessDependencies(mods.ToArray(), modDatabase, mod, states, sortedMods, new List<IModMetadata>());
|
IModMetadata[] modsToLoadFirst = allMods.Where(m => modIdsToLoadFirst.Contains(m.Manifest.UniqueID)).ToArray();
|
||||||
|
IModMetadata[] modsToLoadLast = allMods.Where(m => modIdsToLoadLast.Contains(m.Manifest.UniqueID)).ToArray();
|
||||||
|
IModMetadata[] modsToLoadAsUsual = allMods.Where(m => !modsToLoadFirst.Contains(m) && !modsToLoadLast.Contains(m)).ToArray();
|
||||||
|
|
||||||
|
List<IModMetadata> orderSortedMods = new();
|
||||||
|
orderSortedMods.AddRange(modsToLoadFirst);
|
||||||
|
orderSortedMods.AddRange(modsToLoadAsUsual);
|
||||||
|
orderSortedMods.AddRange(modsToLoadLast);
|
||||||
|
|
||||||
|
foreach (IModMetadata mod in orderSortedMods)
|
||||||
|
this.ProcessDependencies(orderSortedMods, modDatabase, mod, states, sortedMods, new List<IModMetadata>());
|
||||||
|
|
||||||
return sortedMods.Reverse();
|
return sortedMods.Reverse();
|
||||||
}
|
}
|
||||||
|
@ -278,7 +290,7 @@ namespace StardewModdingAPI.Framework.ModLoading
|
||||||
/// <param name="sortedMods">The list in which to save mods sorted by dependency order.</param>
|
/// <param name="sortedMods">The list in which to save mods sorted by dependency order.</param>
|
||||||
/// <param name="currentChain">The current change of mod dependencies.</param>
|
/// <param name="currentChain">The current change of mod dependencies.</param>
|
||||||
/// <returns>Returns the mod dependency status.</returns>
|
/// <returns>Returns the mod dependency status.</returns>
|
||||||
private ModDependencyStatus ProcessDependencies(IModMetadata[] mods, ModDatabase modDatabase, IModMetadata mod, IDictionary<IModMetadata, ModDependencyStatus> states, Stack<IModMetadata> sortedMods, ICollection<IModMetadata> currentChain)
|
private ModDependencyStatus ProcessDependencies(IReadOnlyList<IModMetadata> mods, ModDatabase modDatabase, IModMetadata mod, IDictionary<IModMetadata, ModDependencyStatus> states, Stack<IModMetadata> sortedMods, ICollection<IModMetadata> currentChain)
|
||||||
{
|
{
|
||||||
// check if already visited
|
// check if already visited
|
||||||
switch (states[mod])
|
switch (states[mod])
|
||||||
|
@ -409,7 +421,7 @@ namespace StardewModdingAPI.Framework.ModLoading
|
||||||
/// <summary>Get the dependencies declared in a manifest.</summary>
|
/// <summary>Get the dependencies declared in a manifest.</summary>
|
||||||
/// <param name="manifest">The mod manifest.</param>
|
/// <param name="manifest">The mod manifest.</param>
|
||||||
/// <param name="loadedMods">The loaded mods.</param>
|
/// <param name="loadedMods">The loaded mods.</param>
|
||||||
private IEnumerable<ModDependency> GetDependenciesFrom(IManifest manifest, IModMetadata[] loadedMods)
|
private IEnumerable<ModDependency> GetDependenciesFrom(IManifest manifest, IReadOnlyList<IModMetadata> loadedMods)
|
||||||
{
|
{
|
||||||
IModMetadata? FindMod(string id) => loadedMods.FirstOrDefault(m => m.HasID(id));
|
IModMetadata? FindMod(string id) => loadedMods.FirstOrDefault(m => m.HasID(id));
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,12 @@ namespace StardewModdingAPI.Framework.Models
|
||||||
/// <summary>The mod IDs SMAPI should ignore when performing update checks or validating update keys.</summary>
|
/// <summary>The mod IDs SMAPI should ignore when performing update checks or validating update keys.</summary>
|
||||||
public HashSet<string> SuppressUpdateChecks { get; set; }
|
public HashSet<string> SuppressUpdateChecks { get; set; }
|
||||||
|
|
||||||
|
/// <summary>The mod IDs SMAPI should try to load first, before any other mods not included in this list.</summary>
|
||||||
|
public List<string> ModsToLoadFirst { get; set; }
|
||||||
|
|
||||||
|
/// <summary>The mod IDs SMAPI should try to load last, after all other mods not included in this list.</summary>
|
||||||
|
public List<string> ModsToLoadLast { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/********
|
/********
|
||||||
** Public methods
|
** Public methods
|
||||||
|
@ -100,7 +106,9 @@ namespace StardewModdingAPI.Framework.Models
|
||||||
/// <param name="consoleColors">The colors to use for text written to the SMAPI console.</param>
|
/// <param name="consoleColors">The colors to use for text written to the SMAPI console.</param>
|
||||||
/// <param name="suppressHarmonyDebugMode">Whether to prevent mods from enabling Harmony's debug mode, which impacts performance and creates a file on your desktop. Debug mode should never be enabled by a released mod.</param>
|
/// <param name="suppressHarmonyDebugMode">Whether to prevent mods from enabling Harmony's debug mode, which impacts performance and creates a file on your desktop. Debug mode should never be enabled by a released mod.</param>
|
||||||
/// <param name="suppressUpdateChecks">The mod IDs SMAPI should ignore when performing update checks or validating update keys.</param>
|
/// <param name="suppressUpdateChecks">The mod IDs SMAPI should ignore when performing update checks or validating update keys.</param>
|
||||||
public SConfig(bool developerMode, bool? checkForUpdates, bool? paranoidWarnings, bool? useBetaChannel, string gitHubProjectName, string webApiBaseUrl, string[]? verboseLogging, bool? rewriteMods, bool? useCaseInsensitivePaths, bool? logNetworkTraffic, ColorSchemeConfig consoleColors, bool? suppressHarmonyDebugMode, string[]? suppressUpdateChecks)
|
/// <param name="modsToLoadFirst">The mod IDs SMAPI should try to load first, before any other mods not included in this list.</param>
|
||||||
|
/// <param name="modsToLoadLast">The mod IDs SMAPI should try to load last, after all other mods not included in this list.</param>
|
||||||
|
public SConfig(bool developerMode, bool? checkForUpdates, bool? paranoidWarnings, bool? useBetaChannel, string gitHubProjectName, string webApiBaseUrl, string[]? verboseLogging, bool? rewriteMods, bool? useCaseInsensitivePaths, bool? logNetworkTraffic, ColorSchemeConfig consoleColors, bool? suppressHarmonyDebugMode, string[]? suppressUpdateChecks, string[]? modsToLoadFirst, string[]? modsToLoadLast)
|
||||||
{
|
{
|
||||||
this.DeveloperMode = developerMode;
|
this.DeveloperMode = developerMode;
|
||||||
this.CheckForUpdates = checkForUpdates ?? (bool)SConfig.DefaultValues[nameof(this.CheckForUpdates)];
|
this.CheckForUpdates = checkForUpdates ?? (bool)SConfig.DefaultValues[nameof(this.CheckForUpdates)];
|
||||||
|
@ -115,6 +123,8 @@ namespace StardewModdingAPI.Framework.Models
|
||||||
this.ConsoleColors = consoleColors;
|
this.ConsoleColors = consoleColors;
|
||||||
this.SuppressHarmonyDebugMode = suppressHarmonyDebugMode ?? (bool)SConfig.DefaultValues[nameof(this.SuppressHarmonyDebugMode)];
|
this.SuppressHarmonyDebugMode = suppressHarmonyDebugMode ?? (bool)SConfig.DefaultValues[nameof(this.SuppressHarmonyDebugMode)];
|
||||||
this.SuppressUpdateChecks = new HashSet<string>(suppressUpdateChecks ?? Array.Empty<string>(), StringComparer.OrdinalIgnoreCase);
|
this.SuppressUpdateChecks = new HashSet<string>(suppressUpdateChecks ?? Array.Empty<string>(), StringComparer.OrdinalIgnoreCase);
|
||||||
|
this.ModsToLoadFirst = new List<string>(modsToLoadFirst ?? Array.Empty<string>());
|
||||||
|
this.ModsToLoadLast = new List<string>(modsToLoadLast ?? Array.Empty<string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Override the value of <see cref="DeveloperMode"/>.</summary>
|
/// <summary>Override the value of <see cref="DeveloperMode"/>.</summary>
|
||||||
|
|
|
@ -423,9 +423,17 @@ namespace StardewModdingAPI.Framework
|
||||||
this.Monitor.Log($" Skipped {mod.GetRelativePathWithRoot()} (folder name starts with a dot).");
|
this.Monitor.Log($" Skipped {mod.GetRelativePathWithRoot()} (folder name starts with a dot).");
|
||||||
mods = mods.Where(p => !p.IsIgnored).ToArray();
|
mods = mods.Where(p => !p.IsIgnored).ToArray();
|
||||||
|
|
||||||
|
// warn about mods that should load first or last which are not found at all
|
||||||
|
foreach (string modId in this.Settings.ModsToLoadFirst)
|
||||||
|
if (!mods.Any(m => m.Manifest.UniqueID == modId))
|
||||||
|
this.Monitor.Log($" SMAPI configuration specifies a mod {modId} that should load first, but it could not be found.", LogLevel.Warn);
|
||||||
|
foreach (string modId in this.Settings.ModsToLoadLast)
|
||||||
|
if (!mods.Any(m => m.Manifest.UniqueID == modId))
|
||||||
|
this.Monitor.Log($" SMAPI configuration specifies a mod {modId} that should load last, but it could not be found.", LogLevel.Warn);
|
||||||
|
|
||||||
// load mods
|
// load mods
|
||||||
resolver.ValidateManifests(mods, Constants.ApiVersion, toolkit.GetUpdateUrl, getFileLookup: this.GetFileLookup);
|
resolver.ValidateManifests(mods, Constants.ApiVersion, toolkit.GetUpdateUrl, getFileLookup: this.GetFileLookup);
|
||||||
mods = resolver.ProcessDependencies(mods, modDatabase).ToArray();
|
mods = resolver.ProcessDependencies(mods, this.Settings.ModsToLoadFirst, this.Settings.ModsToLoadLast, modDatabase).ToArray();
|
||||||
this.LoadMods(mods, this.Toolkit.JsonHelper, this.ContentCore, modDatabase);
|
this.LoadMods(mods, this.Toolkit.JsonHelper, this.ContentCore, modDatabase);
|
||||||
|
|
||||||
// check for software likely to cause issues
|
// check for software likely to cause issues
|
||||||
|
|
|
@ -141,5 +141,15 @@ copy all the settings, or you may cause bugs due to overridden changes in future
|
||||||
"SMAPI.ConsoleCommands",
|
"SMAPI.ConsoleCommands",
|
||||||
"SMAPI.ErrorHandler",
|
"SMAPI.ErrorHandler",
|
||||||
"SMAPI.SaveBackup"
|
"SMAPI.SaveBackup"
|
||||||
]
|
],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mod IDs SMAPI should try to load first, before any other mods not included in this list.
|
||||||
|
*/
|
||||||
|
"ModsToLoadFirst": [],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mod IDs SMAPI should try to load last, after all other mods not included in this list.
|
||||||
|
*/
|
||||||
|
"ModsToLoadLast": []
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue