summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI/Framework')
-rw-r--r--src/SMAPI/Framework/CommandQueue.cs47
-rw-r--r--src/SMAPI/Framework/Content/AssetInfo.cs12
-rw-r--r--src/SMAPI/Framework/Content/AssetInterceptorChange.cs3
-rw-r--r--src/SMAPI/Framework/ContentCoordinator.cs20
-rw-r--r--src/SMAPI/Framework/ContentManagers/BaseContentManager.cs3
-rw-r--r--src/SMAPI/Framework/ContentManagers/GameContentManager.cs24
-rw-r--r--src/SMAPI/Framework/ContentManagers/ModContentManager.cs27
-rw-r--r--src/SMAPI/Framework/ContentPack.cs2
-rw-r--r--src/SMAPI/Framework/Logging/LogManager.cs2
-rw-r--r--src/SMAPI/Framework/ModHelpers/CommandHelper.cs4
-rw-r--r--src/SMAPI/Framework/ModHelpers/ContentHelper.cs2
-rw-r--r--src/SMAPI/Framework/ModHelpers/ModHelper.cs16
-rw-r--r--src/SMAPI/Framework/ModLoading/AssemblyLoader.cs4
-rw-r--r--src/SMAPI/Framework/ModLoading/Finders/LegacyAssemblyFinder.cs2
-rw-r--r--src/SMAPI/Framework/ModLoading/InstructionHandleResult.cs2
-rw-r--r--src/SMAPI/Framework/ModLoading/ModMetadata.cs2
-rw-r--r--src/SMAPI/Framework/ModLoading/ModResolver.cs4
-rw-r--r--src/SMAPI/Framework/ModLoading/RewriteFacades/HarmonyInstanceFacade.cs2
-rw-r--r--src/SMAPI/Framework/ModLoading/RewriteFacades/SpriteBatchFacade.cs1
-rw-r--r--src/SMAPI/Framework/Models/SConfig.cs32
-rw-r--r--src/SMAPI/Framework/Networking/MultiplayerPeerMod.cs2
-rw-r--r--src/SMAPI/Framework/Rendering/SXnaDisplayDevice.cs2
-rw-r--r--src/SMAPI/Framework/SCore.cs146
-rw-r--r--src/SMAPI/Framework/SGame.cs3
-rw-r--r--src/SMAPI/Framework/Serialization/KeybindConverter.cs5
25 files changed, 247 insertions, 122 deletions
diff --git a/src/SMAPI/Framework/CommandQueue.cs b/src/SMAPI/Framework/CommandQueue.cs
new file mode 100644
index 00000000..c51016ad
--- /dev/null
+++ b/src/SMAPI/Framework/CommandQueue.cs
@@ -0,0 +1,47 @@
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+
+namespace StardewModdingAPI.Framework
+{
+ /// <summary>A thread-safe command queue optimized for infrequent changes.</summary>
+ internal class CommandQueue
+ {
+ /********
+ ** Fields
+ ********/
+ /// <summary>The underlying list of queued commands to parse and execute.</summary>
+ private readonly List<string> RawCommandQueue = new();
+
+
+ /********
+ ** Public methods
+ ********/
+ /// <summary>Add a command to the queue.</summary>
+ /// <param name="command">The command to add.</param>
+ public void Add(string command)
+ {
+ lock (this.RawCommandQueue)
+ this.RawCommandQueue.Add(command);
+ }
+
+ /// <summary>Remove and return all queued commands, if any.</summary>
+ /// <param name="queued">The commands that were dequeued, in the order they were originally queued.</param>
+ /// <returns>Returns whether any values were dequeued.</returns>
+ [SuppressMessage("ReSharper", "InconsistentlySynchronizedField", Justification = "Deliberately check if it's empty before locking unnecessarily.")]
+ public bool TryDequeue([NotNullWhen(true)] out string[]? queued)
+ {
+ if (this.RawCommandQueue.Count is 0)
+ {
+ queued = null;
+ return false;
+ }
+
+ lock (this.RawCommandQueue)
+ {
+ queued = this.RawCommandQueue.ToArray();
+ this.RawCommandQueue.Clear();
+ return queued.Length > 0;
+ }
+ }
+ }
+}
diff --git a/src/SMAPI/Framework/Content/AssetInfo.cs b/src/SMAPI/Framework/Content/AssetInfo.cs
index 773e3126..43feed27 100644
--- a/src/SMAPI/Framework/Content/AssetInfo.cs
+++ b/src/SMAPI/Framework/Content/AssetInfo.cs
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Graphics;
+#if SMAPI_DEPRECATED
using StardewModdingAPI.Framework.Deprecations;
+#endif
namespace StardewModdingAPI.Framework.Content
{
@@ -30,6 +32,10 @@ namespace StardewModdingAPI.Framework.Content
public IAssetName NameWithoutLocale => this.NameWithoutLocaleImpl ??= this.Name.GetBaseAssetName();
/// <inheritdoc />
+ public Type DataType { get; }
+
+#if SMAPI_DEPRECATED
+ /// <inheritdoc />
[Obsolete($"Use {nameof(AssetInfo.Name)} or {nameof(AssetInfo.NameWithoutLocale)} instead. This property will be removed in SMAPI 4.0.0.")]
public string AssetName
{
@@ -50,9 +56,7 @@ namespace StardewModdingAPI.Framework.Content
return this.NameWithoutLocale.Name;
}
}
-
- /// <inheritdoc />
- public Type DataType { get; }
+#endif
/*********
@@ -71,6 +75,7 @@ namespace StardewModdingAPI.Framework.Content
this.GetNormalizedPath = getNormalizedPath;
}
+#if SMAPI_DEPRECATED
/// <inheritdoc />
[Obsolete($"Use {nameof(Name)}.{nameof(IAssetName.IsEquivalentTo)} or {nameof(AssetInfo.NameWithoutLocale)}.{nameof(IAssetName.IsEquivalentTo)} instead. This method will be removed in SMAPI 4.0.0.")]
public bool AssetNameEquals(string path)
@@ -90,6 +95,7 @@ namespace StardewModdingAPI.Framework.Content
return this.NameWithoutLocale.IsEquivalentTo(path);
}
+#endif
/*********
diff --git a/src/SMAPI/Framework/Content/AssetInterceptorChange.cs b/src/SMAPI/Framework/Content/AssetInterceptorChange.cs
index f3d4f3f4..3b5068dc 100644
--- a/src/SMAPI/Framework/Content/AssetInterceptorChange.cs
+++ b/src/SMAPI/Framework/Content/AssetInterceptorChange.cs
@@ -1,8 +1,8 @@
+#if SMAPI_DEPRECATED
using System;
using System.Reflection;
using StardewModdingAPI.Internal;
-#pragma warning disable CS0618 // obsolete asset interceptors deliberately supported here
namespace StardewModdingAPI.Framework.Content
{
/// <summary>A wrapper for <see cref="IAssetEditor"/> and <see cref="IAssetLoader"/> for internal cache invalidation.</summary>
@@ -103,3 +103,4 @@ namespace StardewModdingAPI.Framework.Content
}
}
}
+#endif
diff --git a/src/SMAPI/Framework/ContentCoordinator.cs b/src/SMAPI/Framework/ContentCoordinator.cs
index 3e09ac62..9e044b44 100644
--- a/src/SMAPI/Framework/ContentCoordinator.cs
+++ b/src/SMAPI/Framework/ContentCoordinator.cs
@@ -12,7 +12,9 @@ using StardewModdingAPI.Framework.Content;
using StardewModdingAPI.Framework.ContentManagers;
using StardewModdingAPI.Framework.Reflection;
using StardewModdingAPI.Framework.Utilities;
+#if SMAPI_DEPRECATED
using StardewModdingAPI.Internal;
+#endif
using StardewModdingAPI.Metadata;
using StardewModdingAPI.Toolkit.Serialization;
using StardewModdingAPI.Toolkit.Utilities.PathLookups;
@@ -84,6 +86,7 @@ namespace StardewModdingAPI.Framework
/// <summary>The cached asset load/edit operations to apply, indexed by asset name.</summary>
private readonly TickCacheDictionary<IAssetName, AssetOperationGroup?> AssetOperationsByKey = new();
+#if SMAPI_DEPRECATED
/// <summary>A cache of asset operation groups created for legacy <see cref="IAssetLoader"/> implementations.</summary>
[Obsolete("This only exists to support legacy code and will be removed in SMAPI 4.0.0.")]
private readonly Dictionary<IAssetLoader, Dictionary<Type, AssetLoadOperation>> LegacyLoaderCache = new(ReferenceEqualityComparer.Instance);
@@ -91,6 +94,7 @@ namespace StardewModdingAPI.Framework
/// <summary>A cache of asset operation groups created for legacy <see cref="IAssetEditor"/> implementations.</summary>
[Obsolete("This only exists to support legacy code and will be removed in SMAPI 4.0.0.")]
private readonly Dictionary<IAssetEditor, Dictionary<Type, AssetEditOperation>> LegacyEditorCache = new(ReferenceEqualityComparer.Instance);
+#endif
/*********
@@ -102,6 +106,7 @@ namespace StardewModdingAPI.Framework
/// <summary>The current language as a constant.</summary>
public LocalizedContentManager.LanguageCode Language => this.MainContentManager.Language;
+#if SMAPI_DEPRECATED
/// <summary>Interceptors which provide the initial versions of matching assets.</summary>
[Obsolete("This only exists to support legacy code and will be removed in SMAPI 4.0.0.")]
public IList<ModLinked<IAssetLoader>> Loaders { get; } = new List<ModLinked<IAssetLoader>>();
@@ -109,6 +114,7 @@ namespace StardewModdingAPI.Framework
/// <summary>Interceptors which edit matching assets after they're loaded.</summary>
[Obsolete("This only exists to support legacy code and will be removed in SMAPI 4.0.0.")]
public IList<ModLinked<IAssetEditor>> Editors { get; } = new List<ModLinked<IAssetEditor>>();
+#endif
/// <summary>The absolute path to the <see cref="ContentManager.RootDirectory"/>.</summary>
public string FullRootDirectory { get; }
@@ -498,15 +504,25 @@ namespace StardewModdingAPI.Framework
return invalidatedAssets.Keys;
}
+#if SMAPI_DEPRECATED
/// <summary>Get the asset load and edit operations to apply to a given asset if it's (re)loaded now.</summary>
/// <typeparam name="T">The asset type.</typeparam>
/// <param name="info">The asset info to load or edit.</param>
public AssetOperationGroup? GetAssetOperations<T>(IAssetInfo info)
where T : notnull
+#else
+ /// <summary>Get the asset load and edit operations to apply to a given asset if it's (re)loaded now.</summary>
+ /// <param name="info">The asset info to load or edit.</param>
+ public AssetOperationGroup? GetAssetOperations(IAssetInfo info)
+#endif
{
return this.AssetOperationsByKey.GetOrSet(
info.Name,
+#if SMAPI_DEPRECATED
() => this.GetAssetOperationsWithoutCache<T>(info)
+#else
+ () => this.RequestAssetOperations(info)
+#endif
);
}
@@ -629,6 +645,7 @@ namespace StardewModdingAPI.Framework
return map;
}
+#if SMAPI_DEPRECATED
/// <summary>Get the asset load and edit operations to apply to a given asset if it's (re)loaded now, ignoring the <see cref="AssetOperationsByKey"/> cache.</summary>
/// <typeparam name="T">The asset type.</typeparam>
/// <param name="info">The asset info to load or edit.</param>
@@ -639,7 +656,6 @@ namespace StardewModdingAPI.Framework
AssetOperationGroup? group = this.RequestAssetOperations(info);
// legacy load operations
-#pragma warning disable CS0612, CS0618 // deprecated code
if (this.Editors.Count > 0 || this.Loaders.Count > 0)
{
IAssetInfo legacyInfo = this.GetLegacyAssetInfo(info);
@@ -738,7 +754,6 @@ namespace StardewModdingAPI.Framework
);
}
}
-#pragma warning restore CS0612, CS0618
return group;
}
@@ -818,5 +833,6 @@ namespace StardewModdingAPI.Framework
// else no change needed
return asset;
}
+#endif
}
}
diff --git a/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs b/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs
index d7be0c37..54f8e2a2 100644
--- a/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs
+++ b/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs
@@ -111,7 +111,6 @@ namespace StardewModdingAPI.Framework.ContentManagers
}
/// <inheritdoc />
- [SuppressMessage("ReSharper", "ConditionIsAlwaysTrueOrFalse", Justification = "Copied as-is from game code")]
public sealed override string LoadBaseString(string path)
{
try
@@ -119,7 +118,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
// copied as-is from LocalizedContentManager.LoadBaseString
// This is only changed to call this.Load instead of base.Load, to support mod assets
this.ParseStringPath(path, out string assetName, out string key);
- Dictionary<string, string> strings = this.Load<Dictionary<string, string>>(assetName, LanguageCode.en);
+ Dictionary<string, string>? strings = this.Load<Dictionary<string, string>?>(assetName, LanguageCode.en);
return strings != null && strings.ContainsKey(key)
? this.GetString(strings, key)
: path;
diff --git a/src/SMAPI/Framework/ContentManagers/GameContentManager.cs b/src/SMAPI/Framework/ContentManagers/GameContentManager.cs
index 446f4a67..df7bdc59 100644
--- a/src/SMAPI/Framework/ContentManagers/GameContentManager.cs
+++ b/src/SMAPI/Framework/ContentManagers/GameContentManager.cs
@@ -76,7 +76,11 @@ namespace StardewModdingAPI.Framework.ContentManagers
// custom asset from a loader
string locale = this.GetLocale();
IAssetInfo info = new AssetInfo(locale, assetName, typeof(T), this.AssertAndNormalizeAssetName);
- AssetOperationGroup? operations = this.Coordinator.GetAssetOperations<T>(info);
+ AssetOperationGroup? operations = this.Coordinator.GetAssetOperations
+#if SMAPI_DEPRECATED
+ <T>
+#endif
+ (info);
if (operations?.LoadOperations.Count > 0)
{
if (!this.AssertMaxOneRequiredLoader(info, operations.LoadOperations, out string? error))
@@ -129,7 +133,11 @@ namespace StardewModdingAPI.Framework.ContentManagers
data = this.AssetsBeingLoaded.Track(assetName.Name, () =>
{
IAssetInfo info = new AssetInfo(assetName.LocaleCode, assetName, typeof(T), this.AssertAndNormalizeAssetName);
- AssetOperationGroup? operations = this.Coordinator.GetAssetOperations<T>(info);
+ AssetOperationGroup? operations = this.Coordinator.GetAssetOperations
+#if SMAPI_DEPRECATED
+ <T>
+#endif
+ (info);
IAssetData asset =
this.ApplyLoader<T>(info, operations?.LoadOperations)
?? new AssetDataForObject(info, this.RawLoad<T>(assetName, useCache), this.AssertAndNormalizeAssetName, this.Reflection);
@@ -294,7 +302,11 @@ namespace StardewModdingAPI.Framework.ContentManagers
? $"Multiple mods want to provide the '{info.Name}' asset: {string.Join(", ", loaderNames)}"
: $"The '{loaderNames[0]}' mod wants to provide the '{info.Name}' asset multiple times";
- error = $"{errorPhrase}. An asset can't be loaded multiple times, so SMAPI will use the default asset instead. Uninstall one of the mods to fix this. (Message for modders: you should avoid {nameof(AssetLoadPriority)}.{nameof(AssetLoadPriority.Exclusive)} and {nameof(IAssetLoader)} if possible to avoid conflicts.)";
+ error = $"{errorPhrase}. An asset can't be loaded multiple times, so SMAPI will use the default asset instead. Uninstall one of the mods to fix this. (Message for modders: you should avoid {nameof(AssetLoadPriority)}.{nameof(AssetLoadPriority.Exclusive)}"
+#if SMAPI_DEPRECATED
+ + " and {nameof(IAssetLoader)}"
+#endif
+ + " if possible to avoid conflicts.)";
return false;
}
@@ -349,6 +361,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
// handle mismatch
if (loadedMap.TileSheets.Count <= vanillaSheet.Index || loadedMap.TileSheets[vanillaSheet.Index].Id != vanillaSheet.Id)
{
+#if SMAPI_DEPRECATED
// only show warning if not farm map
// This is temporary: mods shouldn't do this for any vanilla map, but these are the ones we know will crash. Showing a warning for others instead gives modders time to update their mods, while still simplifying troubleshooting.
bool isFarmMap = info.Name.IsEquivalentTo("Maps/Farm") || info.Name.IsEquivalentTo("Maps/Farm_Combat") || info.Name.IsEquivalentTo("Maps/Farm_Fishing") || info.Name.IsEquivalentTo("Maps/Farm_Foraging") || info.Name.IsEquivalentTo("Maps/Farm_FourCorners") || info.Name.IsEquivalentTo("Maps/Farm_Island") || info.Name.IsEquivalentTo("Maps/Farm_Mining");
@@ -361,7 +374,12 @@ namespace StardewModdingAPI.Framework.ContentManagers
mod.LogAsMod($"SMAPI blocked a '{info.Name}' map load: {reason}", LogLevel.Error);
return false;
}
+
mod.LogAsMod($"SMAPI found an issue with a '{info.Name}' map load: {reason}", LogLevel.Warn);
+#else
+ mod.LogAsMod($"SMAPI found an issue with a '{info.Name}' map load: {this.GetOnBehalfOfLabel(loader.OnBehalfOf, parenthetical: false) ?? "mod"} reordered the original tilesheets, which often causes crashes.\nTechnical details for mod author: Expected order: {string.Join(", ", vanillaTilesheetRefs.Select(p => p.Id))}. See https://stardewvalleywiki.com/Modding:Maps#Tilesheet_order for help.", LogLevel.Error);
+ return false;
+#endif
}
}
}
diff --git a/src/SMAPI/Framework/ContentManagers/ModContentManager.cs b/src/SMAPI/Framework/ContentManagers/ModContentManager.cs
index 8c5d0f84..f3cf05d9 100644
--- a/src/SMAPI/Framework/ContentManagers/ModContentManager.cs
+++ b/src/SMAPI/Framework/ContentManagers/ModContentManager.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
@@ -47,9 +46,6 @@ namespace StardewModdingAPI.Framework.ContentManagers
/// <summary>If a map tilesheet's image source has no file extensions, the file extensions to check for in the local mod folder.</summary>
private static readonly string[] LocalTilesheetExtensions = { ".png", ".xnb" };
- /// <summary>A lookup of image file paths to whether they have PyTK scaling information.</summary>
- private static readonly Dictionary<string, bool> IsPyTkScaled = new(StringComparer.OrdinalIgnoreCase);
-
/*********
** Accessors
@@ -211,24 +207,13 @@ namespace StardewModdingAPI.Framework.ContentManagers
{
if (ModContentManager.EnablePyTkLegacyMode)
{
- if (!ModContentManager.IsPyTkScaled.TryGetValue(file.FullName, out bool isScaled))
- {
- string? dirPath = file.DirectoryName;
- string fileName = $"{Path.GetFileNameWithoutExtension(file.Name)}.pytk.json";
-
- string path = dirPath is not null
- ? Path.Combine(dirPath, fileName)
- : fileName;
-
- ModContentManager.IsPyTkScaled[file.FullName] = isScaled = File.Exists(path);
- }
-
- asRawData = !isScaled;
- if (!asRawData)
- this.Monitor.LogOnce("Enabled compatibility mode for PyTK scaled textures. This won't cause any issues, but may impact performance.", LogLevel.Warn);
+ // PyTK intercepts Texture2D file loads to rescale them (e.g. for HD portraits),
+ // but doesn't support IRawTextureData loads yet. We can't just check if the
+ // current file has a '.pytk.json' rescale file though, since PyTK may still
+ // rescale it if the original asset or another edit gets rescaled.
+ asRawData = false;
+ this.Monitor.LogOnce("Enabled compatibility mode for PyTK 1.23.0 or earlier. This won't cause any issues, but may impact performance.", LogLevel.Warn);
}
- else
- asRawData = true;
}
// load
diff --git a/src/SMAPI/Framework/ContentPack.cs b/src/SMAPI/Framework/ContentPack.cs
index 70fe51f8..a1d977e4 100644
--- a/src/SMAPI/Framework/ContentPack.cs
+++ b/src/SMAPI/Framework/ContentPack.cs
@@ -96,6 +96,7 @@ namespace StardewModdingAPI.Framework
}
}
+#if SMAPI_DEPRECATED
/// <inheritdoc />
[Obsolete($"Use {nameof(IContentPack.ModContent)}.{nameof(IModContentHelper.Load)} instead. This method will be removed in SMAPI 4.0.0.")]
public T LoadAsset<T>(string key)
@@ -110,6 +111,7 @@ namespace StardewModdingAPI.Framework
{
return this.ModContent.GetInternalAssetName(key).Name;
}
+#endif
/*********
diff --git a/src/SMAPI/Framework/Logging/LogManager.cs b/src/SMAPI/Framework/Logging/LogManager.cs
index d811ed5c..c0b7c0ba 100644
--- a/src/SMAPI/Framework/Logging/LogManager.cs
+++ b/src/SMAPI/Framework/Logging/LogManager.cs
@@ -400,7 +400,7 @@ namespace StardewModdingAPI.Framework.Logging
/// <param name="mods">The loaded mods.</param>
/// <param name="skippedMods">The mods which could not be loaded.</param>
/// <param name="logParanoidWarnings">Whether to log issues for mods which directly use potentially sensitive .NET APIs like file or shell access.</param>
- [SuppressMessage("ReSharper", "ConstantConditionalAccessQualifier", Justification = "Manifests aren't guaranteed non-null at this point in the loading process.")]
+ [SuppressMessage("ReSharper", "ConditionalAccessQualifierIsNonNullableAccordingToAPIContract", Justification = "Manifests aren't guaranteed non-null at this point in the loading process.")]
private void LogModWarnings(IEnumerable<IModMetadata> mods, IModMetadata[] skippedMods, bool logParanoidWarnings)
{
// get mods with warnings
diff --git a/src/SMAPI/Framework/ModHelpers/CommandHelper.cs b/src/SMAPI/Framework/ModHelpers/CommandHelper.cs
index ddbd618a..21435f62 100644
--- a/src/SMAPI/Framework/ModHelpers/CommandHelper.cs
+++ b/src/SMAPI/Framework/ModHelpers/CommandHelper.cs
@@ -1,5 +1,7 @@
using System;
+#if SMAPI_DEPRECATED
using StardewModdingAPI.Framework.Deprecations;
+#endif
namespace StardewModdingAPI.Framework.ModHelpers
{
@@ -32,6 +34,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
return this;
}
+#if SMAPI_DEPRECATED
/// <inheritdoc />
[Obsolete("Use mod-provided APIs to integrate with mods instead. This method will be removed in SMAPI 4.0.0.")]
public bool Trigger(string name, string[] arguments)
@@ -45,5 +48,6 @@ namespace StardewModdingAPI.Framework.ModHelpers
return this.CommandManager.Trigger(name, arguments);
}
+#endif
}
}
diff --git a/src/SMAPI/Framework/ModHelpers/ContentHelper.cs b/src/SMAPI/Framework/ModHelpers/ContentHelper.cs
index 427adac2..9992cb52 100644
--- a/src/SMAPI/Framework/ModHelpers/ContentHelper.cs
+++ b/src/SMAPI/Framework/ModHelpers/ContentHelper.cs
@@ -1,3 +1,4 @@
+#if SMAPI_DEPRECATED
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@@ -249,3 +250,4 @@ namespace StardewModdingAPI.Framework.ModHelpers
}
}
}
+#endif
diff --git a/src/SMAPI/Framework/ModHelpers/ModHelper.cs b/src/SMAPI/Framework/ModHelpers/ModHelper.cs
index 48973691..caa66bad 100644
--- a/src/SMAPI/Framework/ModHelpers/ModHelper.cs
+++ b/src/SMAPI/Framework/ModHelpers/ModHelper.cs
@@ -1,7 +1,9 @@
using System;
using System.IO;
using StardewModdingAPI.Events;
+#if SMAPI_DEPRECATED
using StardewModdingAPI.Framework.Deprecations;
+#endif
using StardewModdingAPI.Framework.Input;
namespace StardewModdingAPI.Framework.ModHelpers
@@ -9,12 +11,14 @@ namespace StardewModdingAPI.Framework.ModHelpers
/// <summary>Provides simplified APIs for writing mods.</summary>
internal class ModHelper : BaseHelper, IModHelper, IDisposable
{
+#if SMAPI_DEPRECATED
/*********
** Fields
*********/
/// <summary>The backing field for <see cref="Content"/>.</summary>
[Obsolete("This only exists to support legacy code and will be removed in SMAPI 4.0.0.")]
private readonly ContentHelper ContentImpl;
+#endif
/*********
@@ -26,6 +30,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
/// <inheritdoc />
public IModEvents Events { get; }
+#if SMAPI_DEPRECATED
/// <inheritdoc />
[Obsolete($"Use {nameof(IGameContentHelper)} or {nameof(IModContentHelper)} instead.")]
public IContentHelper Content
@@ -42,6 +47,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
return this.ContentImpl;
}
}
+#endif
/// <inheritdoc />
public IGameContentHelper GameContent { get; }
@@ -96,9 +102,9 @@ namespace StardewModdingAPI.Framework.ModHelpers
/// <exception cref="InvalidOperationException">The <paramref name="modDirectory"/> path does not exist on disk.</exception>
public ModHelper(
IModMetadata mod, string modDirectory, Func<SInputState> currentInputState, IModEvents events,
-#pragma warning disable CS0612 // deprecated code
+#if SMAPI_DEPRECATED
ContentHelper contentHelper,
-#pragma warning restore CS0612
+#endif
IGameContentHelper gameContentHelper, IModContentHelper modContentHelper, IContentPackHelper contentPackHelper, ICommandHelper commandHelper, IDataHelper dataHelper, IModRegistry modRegistry, IReflectionHelper reflectionHelper, IMultiplayerHelper multiplayer, ITranslationHelper translationHelper
)
: base(mod)
@@ -111,9 +117,9 @@ namespace StardewModdingAPI.Framework.ModHelpers
// initialize
this.DirectoryPath = modDirectory;
-#pragma warning disable CS0612 // deprecated code
+#if SMAPI_DEPRECATED
this.ContentImpl = contentHelper ?? throw new ArgumentNullException(nameof(contentHelper));
-#pragma warning restore CS0612
+#endif
this.GameContent = gameContentHelper ?? throw new ArgumentNullException(nameof(gameContentHelper));
this.ModContent = modContentHelper ?? throw new ArgumentNullException(nameof(modContentHelper));
this.ContentPacks = contentPackHelper ?? throw new ArgumentNullException(nameof(contentPackHelper));
@@ -127,12 +133,14 @@ namespace StardewModdingAPI.Framework.ModHelpers
this.Events = events;
}
+#if SMAPI_DEPRECATED
/// <summary>Get the underlying instance for <see cref="IContentHelper"/>.</summary>
[Obsolete("This only exists to support legacy code and will be removed in SMAPI 4.0.0.")]
public ContentHelper GetLegacyContentHelper()
{
return this.ContentImpl;
}
+#endif
/****
** Mod config file
diff --git a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs
index e5aaa8ee..eb940c41 100644
--- a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs
+++ b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs
@@ -163,6 +163,7 @@ namespace StardewModdingAPI.Framework.ModLoading
this.AssemblyDefinitionResolver.Add(assembly.Definition);
}
+#if SMAPI_DEPRECATED
// special case: clear legacy-DLL warnings if the mod bundles a copy
if (mod.Warnings.HasFlag(ModWarning.DetectedLegacyCachingDll))
{
@@ -185,6 +186,7 @@ namespace StardewModdingAPI.Framework.ModLoading
if (File.Exists(Path.Combine(mod.DirectoryPath, "System.Security.Permissions.dll")))
mod.RemoveWarning(ModWarning.DetectedLegacyPermissionsDll);
}
+#endif
// throw if incompatibilities detected
if (!assumeCompatible && mod.Warnings.HasFlag(ModWarning.BrokenCodeLoaded))
@@ -452,6 +454,7 @@ namespace StardewModdingAPI.Framework.ModLoading
mod.SetWarning(ModWarning.AccessesShell);
break;
+#if SMAPI_DEPRECATED
case InstructionHandleResult.DetectedLegacyCachingDll:
template = $"{logPrefix}Detected reference to System.Runtime.Caching.dll, which will be removed in SMAPI 4.0.0.";
mod.SetWarning(ModWarning.DetectedLegacyCachingDll);
@@ -466,6 +469,7 @@ namespace StardewModdingAPI.Framework.ModLoading
template = $"{logPrefix}Detected reference to System.Security.Permissions.dll, which will be removed in SMAPI 4.0.0.";
mod.SetWarning(ModWarning.DetectedLegacyPermissionsDll);
break;
+#endif
case InstructionHandleResult.None:
break;
diff --git a/src/SMAPI/Framework/ModLoading/Finders/LegacyAssemblyFinder.cs b/src/SMAPI/Framework/ModLoading/Finders/LegacyAssemblyFinder.cs
index d3437b05..77380907 100644
--- a/src/SMAPI/Framework/ModLoading/Finders/LegacyAssemblyFinder.cs
+++ b/src/SMAPI/Framework/ModLoading/Finders/LegacyAssemblyFinder.cs
@@ -1,3 +1,4 @@
+#if SMAPI_DEPRECATED
using Mono.Cecil;
using StardewModdingAPI.Framework.ModLoading.Framework;
@@ -47,3 +48,4 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders
}
}
}
+#endif
diff --git a/src/SMAPI/Framework/ModLoading/InstructionHandleResult.cs b/src/SMAPI/Framework/ModLoading/InstructionHandleResult.cs
index 476c30d0..189ca64e 100644
--- a/src/SMAPI/Framework/ModLoading/InstructionHandleResult.cs
+++ b/src/SMAPI/Framework/ModLoading/InstructionHandleResult.cs
@@ -32,6 +32,7 @@ namespace StardewModdingAPI.Framework.ModLoading
/// <summary>The instruction accesses the OS shell or processes directly.</summary>
DetectedShellAccess,
+#if SMAPI_DEPRECATED
/// <summary>The module references the legacy <c>System.Configuration.ConfigurationManager</c> assembly and doesn't include a copy in the mod folder, so it'll break in SMAPI 4.0.0.</summary>
DetectedLegacyConfigurationDll,
@@ -40,5 +41,6 @@ namespace StardewModdingAPI.Framework.ModLoading
/// <summary>The module references the legacy <c>System.Security.Permissions</c> assembly and doesn't include a copy in the mod folder, so it'll break in SMAPI 4.0.0.</summary>
DetectedLegacyPermissionsDll
+#endif
}
}
diff --git a/src/SMAPI/Framework/ModLoading/ModMetadata.cs b/src/SMAPI/Framework/ModLoading/ModMetadata.cs
index aa4d2d8c..ac7a6bbd 100644
--- a/src/SMAPI/Framework/ModLoading/ModMetadata.cs
+++ b/src/SMAPI/Framework/ModLoading/ModMetadata.cs
@@ -83,7 +83,7 @@ namespace StardewModdingAPI.Framework.ModLoading
/// <inheritdoc />
[MemberNotNullWhen(true, nameof(ModMetadata.ContentPack))]
- [SuppressMessage("ReSharper", "ConstantConditionalAccessQualifier", Justification = "The manifest may be null for broken mods while loading.")]
+ [SuppressMessage("ReSharper", "ConditionalAccessQualifierIsNonNullableAccordingToAPIContract", Justification = "The manifest may be null for broken mods while loading.")]
public bool IsContentPack => this.Manifest?.ContentPackFor != null;
/// <summary>The fake content packs created by this mod, if any.</summary>
diff --git a/src/SMAPI/Framework/ModLoading/ModResolver.cs b/src/SMAPI/Framework/ModLoading/ModResolver.cs
index 3e7144f9..abc46d47 100644
--- a/src/SMAPI/Framework/ModLoading/ModResolver.cs
+++ b/src/SMAPI/Framework/ModLoading/ModResolver.cs
@@ -60,8 +60,8 @@ namespace StardewModdingAPI.Framework.ModLoading
/// <param name="getUpdateUrl">Get an update URL for an update key (if valid).</param>
/// <param name="getFileLookup">Get a file lookup for the given directory.</param>
/// <param name="validateFilesExist">Whether to validate that files referenced in the manifest (like <see cref="IManifest.EntryDll"/>) exist on disk. This can be disabled to only validate the manifest itself.</param>
- [SuppressMessage("ReSharper", "ConstantConditionalAccessQualifier", Justification = "Manifest values may be null before they're validated.")]
- [SuppressMessage("ReSharper", "ConditionIsAlwaysTrueOrFalse", Justification = "Manifest values may be null before they're validated.")]
+ [SuppressMessage("ReSharper", "ConditionalAccessQualifierIsNonNullableAccordingToAPIContract", Justification = "Manifest values may be null before they're validated.")]
+ [SuppressMessage("ReSharper", "ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract", Justification = "Manifest values may be null before they're validated.")]
public void ValidateManifests(IEnumerable<IModMetadata> mods, ISemanticVersion apiVersion, Func<string, string?> getUpdateUrl, Func<string, IFileLookup> getFileLookup, bool validateFilesExist = true)
{
mods = mods.ToArray();
diff --git a