summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework/ModHelpers/ContentHelper.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI/Framework/ModHelpers/ContentHelper.cs')
-rw-r--r--src/SMAPI/Framework/ModHelpers/ContentHelper.cs108
1 files changed, 80 insertions, 28 deletions
diff --git a/src/SMAPI/Framework/ModHelpers/ContentHelper.cs b/src/SMAPI/Framework/ModHelpers/ContentHelper.cs
index bfca2264..3c2441e8 100644
--- a/src/SMAPI/Framework/ModHelpers/ContentHelper.cs
+++ b/src/SMAPI/Framework/ModHelpers/ContentHelper.cs
@@ -7,12 +7,15 @@ using System.IO;
using System.Linq;
using StardewModdingAPI.Framework.Content;
using StardewModdingAPI.Framework.ContentManagers;
+using StardewModdingAPI.Framework.Deprecations;
using StardewModdingAPI.Framework.Exceptions;
+using StardewModdingAPI.Framework.Reflection;
using StardewValley;
namespace StardewModdingAPI.Framework.ModHelpers
{
/// <summary>Provides an API for loading content assets.</summary>
+ [Obsolete]
internal class ContentHelper : BaseHelper, IContentHelper
{
/*********
@@ -27,12 +30,12 @@ namespace StardewModdingAPI.Framework.ModHelpers
/// <summary>A content manager for this mod which manages files from the mod's folder.</summary>
private readonly ModContentManager ModContentManager;
- /// <summary>The friendly mod name for use in errors.</summary>
- private readonly string ModName;
-
/// <summary>Encapsulates monitoring and logging.</summary>
private readonly IMonitor Monitor;
+ /// <summary>Simplifies access to private code.</summary>
+ private readonly Reflector Reflection;
+
/*********
** Accessors
@@ -44,16 +47,42 @@ namespace StardewModdingAPI.Framework.ModHelpers
public LocalizedContentManager.LanguageCode CurrentLocaleConstant => this.GameContentManager.Language;
/// <summary>The observable implementation of <see cref="AssetEditors"/>.</summary>
- internal ObservableCollection<IAssetEditor> ObservableAssetEditors { get; } = new ObservableCollection<IAssetEditor>();
+ internal ObservableCollection<IAssetEditor> ObservableAssetEditors { get; } = new();
/// <summary>The observable implementation of <see cref="AssetLoaders"/>.</summary>
- internal ObservableCollection<IAssetLoader> ObservableAssetLoaders { get; } = new ObservableCollection<IAssetLoader>();
+ internal ObservableCollection<IAssetLoader> ObservableAssetLoaders { get; } = new();
/// <inheritdoc />
- public IList<IAssetLoader> AssetLoaders => this.ObservableAssetLoaders;
+ public IList<IAssetLoader> AssetLoaders
+ {
+ get
+ {
+ SCore.DeprecationManager.Warn(
+ source: this.Mod,
+ nounPhrase: $"{nameof(IContentHelper)}.{nameof(IContentHelper.AssetLoaders)}",
+ version: "3.14.0",
+ severity: DeprecationLevel.Notice
+ );
+
+ return this.ObservableAssetLoaders;
+ }
+ }
/// <inheritdoc />
- public IList<IAssetEditor> AssetEditors => this.ObservableAssetEditors;
+ public IList<IAssetEditor> AssetEditors
+ {
+ get
+ {
+ SCore.DeprecationManager.Warn(
+ source: this.Mod,
+ nounPhrase: $"{nameof(IContentHelper)}.{nameof(IContentHelper.AssetEditors)}",
+ version: "3.14.0",
+ severity: DeprecationLevel.Notice
+ );
+
+ return this.ObservableAssetEditors;
+ }
+ }
/*********
@@ -62,48 +91,62 @@ namespace StardewModdingAPI.Framework.ModHelpers
/// <summary>Construct an instance.</summary>
/// <param name="contentCore">SMAPI's core content logic.</param>
/// <param name="modFolderPath">The absolute path to the mod folder.</param>
- /// <param name="modID">The unique ID of the relevant mod.</param>
- /// <param name="modName">The friendly mod name for use in errors.</param>
+ /// <param name="mod">The mod using this instance.</param>
/// <param name="monitor">Encapsulates monitoring and logging.</param>
- public ContentHelper(ContentCoordinator contentCore, string modFolderPath, string modID, string modName, IMonitor monitor)
- : base(modID)
+ /// <param name="reflection">Simplifies access to private code.</param>
+ public ContentHelper(ContentCoordinator contentCore, string modFolderPath, IModMetadata mod, IMonitor monitor, Reflector reflection)
+ : base(mod)
{
- string managedAssetPrefix = contentCore.GetManagedAssetPrefix(modID);
+ string managedAssetPrefix = contentCore.GetManagedAssetPrefix(mod.Manifest.UniqueID);
this.ContentCore = contentCore;
this.GameContentManager = contentCore.CreateGameContentManager(managedAssetPrefix + ".content");
- this.ModContentManager = contentCore.CreateModContentManager(managedAssetPrefix, modName, modFolderPath, this.GameContentManager);
- this.ModName = modName;
+ this.ModContentManager = contentCore.CreateModContentManager(managedAssetPrefix, this.Mod.DisplayName, modFolderPath, this.GameContentManager);
this.Monitor = monitor;
+ this.Reflection = reflection;
}
/// <inheritdoc />
public T Load<T>(string key, ContentSource source = ContentSource.ModFolder)
+ where T : notnull
{
+ IAssetName assetName = this.ContentCore.ParseAssetName(key, allowLocales: source == ContentSource.GameContent);
+
try
{
this.AssertAndNormalizeAssetName(key);
switch (source)
{
case ContentSource.GameContent:
- return this.GameContentManager.Load<T>(key, this.CurrentLocaleConstant, useCache: false);
+ if (assetName.Name.EndsWith(".xnb", StringComparison.OrdinalIgnoreCase))
+ {
+ assetName = this.ContentCore.ParseAssetName(assetName.Name[..^4], allowLocales: true);
+ SCore.DeprecationManager.Warn(
+ this.Mod,
+ "loading assets from the Content folder with a .xnb file extension",
+ "3.14.0",
+ DeprecationLevel.Notice
+ );
+ }
+
+ return this.GameContentManager.LoadLocalized<T>(assetName, this.CurrentLocaleConstant, useCache: false);
case ContentSource.ModFolder:
- return this.ModContentManager.Load<T>(key, Constants.DefaultLanguage, useCache: false);
+ return this.ModContentManager.LoadExact<T>(assetName, useCache: false);
default:
- throw new SContentLoadException($"{this.ModName} failed loading content asset '{key}' from {source}: unknown content source '{source}'.");
+ throw new SContentLoadException($"{this.Mod.DisplayName} failed loading content asset '{key}' from {source}: unknown content source '{source}'.");
}
}
- catch (Exception ex) when (!(ex is SContentLoadException))
+ catch (Exception ex) when (ex is not SContentLoadException)
{
- throw new SContentLoadException($"{this.ModName} failed loading content asset '{key}' from {source}.", ex);
+ throw new SContentLoadException($"{this.Mod.DisplayName} failed loading content asset '{key}' from {source}.", ex);
}
}
/// <inheritdoc />
[Pure]
- public string NormalizeAssetName(string assetName)
+ public string NormalizeAssetName(string? assetName)
{
return this.ModContentManager.AssertAndNormalizeAssetName(assetName);
}
@@ -117,7 +160,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
return this.GameContentManager.AssertAndNormalizeAssetName(key);
case ContentSource.ModFolder:
- return this.ModContentManager.GetInternalAssetKey(key);
+ return this.ModContentManager.GetInternalAssetKey(key).Name;
default:
throw new NotSupportedException($"Unknown content source '{source}'.");
@@ -128,32 +171,41 @@ namespace StardewModdingAPI.Framework.ModHelpers
public bool InvalidateCache(string key)
{
string actualKey = this.GetActualAssetKey(key, ContentSource.GameContent);
- this.Monitor.Log($"Requested cache invalidation for '{actualKey}'.", LogLevel.Trace);
- return this.ContentCore.InvalidateCache(asset => asset.AssetNameEquals(actualKey)).Any();
+ this.Monitor.Log($"Requested cache invalidation for '{actualKey}'.");
+ return this.ContentCore.InvalidateCache(asset => asset.Name.IsEquivalentTo(actualKey)).Any();
}
/// <inheritdoc />
public bool InvalidateCache<T>()
+ where T : notnull
{
- this.Monitor.Log($"Requested cache invalidation for all assets of type {typeof(T)}. This is an expensive operation and should be avoided if possible.", LogLevel.Trace);
- return this.ContentCore.InvalidateCache((contentManager, key, type) => typeof(T).IsAssignableFrom(type)).Any();
+ this.Monitor.Log($"Requested cache invalidation for all assets of type {typeof(T)}. This is an expensive operation and should be avoided if possible.");
+ return this.ContentCore.InvalidateCache((_, _, type) => typeof(T).IsAssignableFrom(type)).Any();
}
/// <inheritdoc />
public bool InvalidateCache(Func<IAssetInfo, bool> predicate)
{
- this.Monitor.Log("Requested cache invalidation for all assets matching a predicate.", LogLevel.Trace);
+ this.Monitor.Log("Requested cache invalidation for all assets matching a predicate.");
return this.ContentCore.InvalidateCache(predicate).Any();
}
/// <inheritdoc />
- public IAssetData GetPatchHelper<T>(T data, string assetName = null)
+ public IAssetData GetPatchHelper<T>(T data, string? assetName = null)
+ where T : notnull
{
if (data == null)
throw new ArgumentNullException(nameof(data), "Can't get a patch helper for a null value.");
assetName ??= $"temp/{Guid.NewGuid():N}";
- return new AssetDataForObject(this.CurrentLocale, assetName, data, this.NormalizeAssetName);
+
+ return new AssetDataForObject(
+ locale: this.CurrentLocale,
+ assetName: this.ContentCore.ParseAssetName(assetName, allowLocales: true/* no way to know if it's a game or mod asset here*/),
+ data: data,
+ getNormalizedPath: this.NormalizeAssetName,
+ reflection: this.Reflection
+ );
}