diff options
Diffstat (limited to 'src/SMAPI/Framework/ModHelpers/ContentHelper.cs')
-rw-r--r-- | src/SMAPI/Framework/ModHelpers/ContentHelper.cs | 108 |
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 + ); } |