summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs2
-rw-r--r--src/SMAPI/Framework/SCore.cs67
-rw-r--r--src/SMAPI/IMod.cs2
3 files changed, 38 insertions, 33 deletions
diff --git a/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs b/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs
index d115810a..5e9e3c35 100644
--- a/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs
+++ b/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs
@@ -52,7 +52,7 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning
".zip",
".7z",
".tar",
- ".tar.gz"
+ ".tar.gz",
// backup files
".backup",
diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs
index 4ba0dd9c..98eb2803 100644
--- a/src/SMAPI/Framework/SCore.cs
+++ b/src/SMAPI/Framework/SCore.cs
@@ -1686,12 +1686,16 @@ namespace StardewModdingAPI.Framework
this.Monitor.Log("Launching mods...", LogLevel.Debug);
foreach (IModMetadata metadata in loadedMods)
{
+ IMod mod =
+ metadata.Mod
+ ?? throw new InvalidOperationException($"The '{metadata.DisplayName}' mod is not initialized correctly."); // should never happen, but avoids nullability warnings
+
#if SMAPI_DEPRECATED
// add interceptors
- if (metadata.Mod?.Helper is ModHelper helper)
+ if (mod.Helper is ModHelper helper)
{
// ReSharper disable SuspiciousTypeConversion.Global
- if (metadata.Mod is IAssetEditor editor)
+ if (mod is IAssetEditor editor)
{
SCore.DeprecationManager.Warn(
source: metadata,
@@ -1704,7 +1708,7 @@ namespace StardewModdingAPI.Framework
this.ContentCore.Editors.Add(new ModLinked<IAssetEditor>(metadata, editor));
}
- if (metadata.Mod is IAssetLoader loader)
+ if (mod is IAssetLoader loader)
{
SCore.DeprecationManager.Warn(
source: metadata,
@@ -1749,41 +1753,42 @@ namespace StardewModdingAPI.Framework
}
#endif
- // call entry method
+ // initialize mod
Context.HeuristicModsRunningCode.Push(metadata);
- try
- {
- IMod mod = metadata.Mod!;
- mod.Entry(mod.Helper!);
- }
- catch (Exception ex)
- {
- metadata.LogAsMod($"Mod crashed on entry and might not work correctly. Technical details:\n{ex.GetLogSummary()}", LogLevel.Error);
- }
-
- // get mod API
- try
{
- object? api = metadata.Mod!.GetApi();
- if (api != null && !api.GetType().IsPublic)
+ // call entry method
+ try
+ {
+ mod.Entry(mod.Helper!);
+ }
+ catch (Exception ex)
{
- api = null;
- this.Monitor.Log($"{metadata.DisplayName} provides an API instance with a non-public type. This isn't currently supported, so the API won't be available to other mods.", LogLevel.Warn);
+ metadata.LogAsMod($"Mod crashed on entry and might not work correctly. Technical details:\n{ex.GetLogSummary()}", LogLevel.Error);
}
- if (api != null)
- this.Monitor.Log($" Found mod-provided API ({api.GetType().FullName}).");
- metadata.SetApi(api);
- }
- catch (Exception ex)
- {
- this.Monitor.Log($"Failed loading mod-provided API for {metadata.DisplayName}. Integrations with other mods may not work. Error: {ex.GetLogSummary()}", LogLevel.Error);
- }
+ // get mod API
+ try
+ {
+ object? api = mod.GetApi();
+ if (api != null && !api.GetType().IsPublic)
+ {
+ api = null;
+ this.Monitor.Log($"{metadata.DisplayName} provides an API instance with a non-public type. This isn't currently supported, so the API won't be available to other mods.", LogLevel.Warn);
+ }
- // validate mod doesn't implement both GetApi() and GetApi(mod)
- if (metadata.Api != null && metadata.Mod!.GetType().GetMethod(nameof(Mod.GetApi), new Type[] { typeof(IManifest) })!.DeclaringType != typeof(Mod))
- metadata.LogAsMod($"Mod implements both {nameof(Mod.GetApi)}() and {nameof(Mod.GetApi)}({nameof(IManifest)}), which isn't allowed. The latter will be ignored.", LogLevel.Error);
+ if (api != null)
+ this.Monitor.Log($" Found mod-provided API ({api.GetType().FullName}).");
+ metadata.SetApi(api);
+ }
+ catch (Exception ex)
+ {
+ this.Monitor.Log($"Failed loading mod-provided API for {metadata.DisplayName}. Integrations with other mods may not work. Error: {ex.GetLogSummary()}", LogLevel.Error);
+ }
+ // validate mod doesn't implement both GetApi() and GetApi(mod)
+ if (metadata.Api != null && mod.GetType().GetMethod(nameof(Mod.GetApi), new Type[] { typeof(IModInfo) })!.DeclaringType != typeof(Mod))
+ metadata.LogAsMod($"Mod implements both {nameof(Mod.GetApi)}() and {nameof(Mod.GetApi)}({nameof(IModInfo)}), which isn't allowed. The latter will be ignored.", LogLevel.Error);
+ }
Context.HeuristicModsRunningCode.TryPop(out _);
}
diff --git a/src/SMAPI/IMod.cs b/src/SMAPI/IMod.cs
index 19d01311..87c9880c 100644
--- a/src/SMAPI/IMod.cs
+++ b/src/SMAPI/IMod.cs
@@ -30,7 +30,7 @@ namespace StardewModdingAPI
/// <summary>Get an <a href="https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Integrations">API that other mods can access</a>. This is always called after <see cref="Entry"/>, and is called once per mod that accesses the API (even if they access it multiple times).</summary>
/// <param name="mod">The mod accessing the API.</param>
- /// <remarks>Returns the API instance, or <c>null</c> if the mod has no API. Note that the manifest is provided for informational purposes only, and that denying API access to specific mods is strongly discouraged and may be considered abusive.</remarks>
+ /// <remarks>Returns the API instance, or <c>null</c> if the mod has no API. Note that <paramref name="mod"/> is provided for informational purposes only, and that denying API access to specific mods is strongly discouraged and may be considered abusive.</remarks>
/// <inheritdoc cref="GetApi()" include="/Remarks" />
object? GetApi(IModInfo mod);
}