diff options
Diffstat (limited to 'src/SMAPI/Framework/ModHelpers')
-rw-r--r-- | src/SMAPI/Framework/ModHelpers/ContentHelper.cs | 9 | ||||
-rw-r--r-- | src/SMAPI/Framework/ModHelpers/GameContentHelper.cs | 129 | ||||
-rw-r--r-- | src/SMAPI/Framework/ModHelpers/ModContentHelper.cs | 75 | ||||
-rw-r--r-- | src/SMAPI/Framework/ModHelpers/ModHelper.cs | 38 |
4 files changed, 240 insertions, 11 deletions
diff --git a/src/SMAPI/Framework/ModHelpers/ContentHelper.cs b/src/SMAPI/Framework/ModHelpers/ContentHelper.cs index 3a5c8938..b0064532 100644 --- a/src/SMAPI/Framework/ModHelpers/ContentHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ContentHelper.cs @@ -13,6 +13,7 @@ using StardewValley; namespace StardewModdingAPI.Framework.ModHelpers { /// <summary>Provides an API for loading content assets.</summary> + [Obsolete] internal class ContentHelper : BaseHelper, IContentHelper { /********* @@ -44,11 +45,9 @@ namespace StardewModdingAPI.Framework.ModHelpers public LocalizedContentManager.LanguageCode CurrentLocaleConstant => this.GameContentManager.Language; /// <summary>The observable implementation of <see cref="AssetEditors"/>.</summary> - [Obsolete] internal ObservableCollection<IAssetEditor> ObservableAssetEditors { get; } = new(); /// <summary>The observable implementation of <see cref="AssetLoaders"/>.</summary> - [Obsolete] internal ObservableCollection<IAssetLoader> ObservableAssetLoaders { get; } = new(); /// <inheritdoc /> @@ -106,12 +105,6 @@ namespace StardewModdingAPI.Framework.ModHelpers } /// <inheritdoc /> - public IAssetName ParseAssetName(string rawName) - { - return this.ContentCore.ParseAssetName(rawName); - } - - /// <inheritdoc /> public T Load<T>(string key, ContentSource source = ContentSource.ModFolder) { IAssetName assetName = this.ContentCore.ParseAssetName(key); diff --git a/src/SMAPI/Framework/ModHelpers/GameContentHelper.cs b/src/SMAPI/Framework/ModHelpers/GameContentHelper.cs new file mode 100644 index 00000000..42a4de20 --- /dev/null +++ b/src/SMAPI/Framework/ModHelpers/GameContentHelper.cs @@ -0,0 +1,129 @@ +using System; +using System.Linq; +using StardewModdingAPI.Framework.Content; +using StardewModdingAPI.Framework.ContentManagers; +using StardewModdingAPI.Framework.Exceptions; +using StardewValley; + +namespace StardewModdingAPI.Framework.ModHelpers +{ + /// <inheritdoc cref="IGameContentHelper"/> + internal class GameContentHelper : BaseHelper, IGameContentHelper + { + /********* + ** Fields + *********/ + /// <summary>SMAPI's core content logic.</summary> + private readonly ContentCoordinator ContentCore; + + /// <summary>The underlying game content manager.</summary> + private readonly IContentManager GameContentManager; + + /// <summary>The friendly mod name for use in errors.</summary> + private readonly string ModName; + + /// <summary>Encapsulates monitoring and logging.</summary> + private readonly IMonitor Monitor; + + + /********* + ** Accessors + *********/ + /// <inheritdoc /> + public string CurrentLocale => this.GameContentManager.GetLocale(); + + /// <inheritdoc /> + public LocalizedContentManager.LanguageCode CurrentLocaleConstant => this.GameContentManager.Language; + + + /********* + ** Public methods + *********/ + /// <summary>Construct an instance.</summary> + /// <param name="contentCore">SMAPI's core content logic.</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="monitor">Encapsulates monitoring and logging.</param> + public GameContentHelper(ContentCoordinator contentCore, string modID, string modName, IMonitor monitor) + : base(modID) + { + string managedAssetPrefix = contentCore.GetManagedAssetPrefix(modID); + + this.ContentCore = contentCore; + this.GameContentManager = contentCore.CreateGameContentManager(managedAssetPrefix + ".content"); + this.ModName = modName; + this.Monitor = monitor; + } + + /// <inheritdoc /> + public IAssetName ParseAssetName(string rawName) + { + return this.ContentCore.ParseAssetName(rawName); + } + + /// <inheritdoc /> + public T Load<T>(string key) + { + IAssetName assetName = this.ContentCore.ParseAssetName(key); + return this.Load<T>(assetName); + } + + /// <inheritdoc /> + public T Load<T>(IAssetName assetName) + { + try + { + return this.GameContentManager.LoadLocalized<T>(assetName, this.CurrentLocaleConstant, useCache: false); + } + catch (Exception ex) when (ex is not SContentLoadException) + { + throw new SContentLoadException($"{this.ModName} failed loading content asset '{assetName}' from the game content.", ex); + } + } + + /// <inheritdoc /> + public bool InvalidateCache(string key) + { + IAssetName assetName = this.ParseAssetName(key); + return this.InvalidateCache(assetName); + } + + /// <inheritdoc /> + public bool InvalidateCache(IAssetName assetName) + { + this.Monitor.Log($"Requested cache invalidation for '{assetName}'."); + return this.ContentCore.InvalidateCache(asset => asset.Name.IsEquivalentTo(assetName)).Any(); + } + + /// <inheritdoc /> + public bool InvalidateCache<T>() + { + 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."); + return this.ContentCore.InvalidateCache(predicate).Any(); + } + + /// <inheritdoc /> + public IAssetData GetPatchHelper<T>(T data, string assetName = null) + { + 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, this.ContentCore.ParseAssetName(assetName), data, key => this.ParseAssetName(key).Name); + } + + /// <summary>Get the underlying game content manager.</summary> + internal IContentManager GetUnderlyingContentManager() + { + return this.GameContentManager; + } + } +} diff --git a/src/SMAPI/Framework/ModHelpers/ModContentHelper.cs b/src/SMAPI/Framework/ModHelpers/ModContentHelper.cs new file mode 100644 index 00000000..45899dd7 --- /dev/null +++ b/src/SMAPI/Framework/ModHelpers/ModContentHelper.cs @@ -0,0 +1,75 @@ +using System; +using StardewModdingAPI.Framework.Content; +using StardewModdingAPI.Framework.ContentManagers; +using StardewModdingAPI.Framework.Exceptions; + +namespace StardewModdingAPI.Framework.ModHelpers +{ + /// <inheritdoc cref="IModContentHelper"/> + internal class ModContentHelper : BaseHelper, IModContentHelper + { + /********* + ** Fields + *********/ + /// <summary>SMAPI's core content logic.</summary> + private readonly ContentCoordinator ContentCore; + + /// <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; + + + /********* + ** Public methods + *********/ + /// <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="gameContentManager">The game content manager used for map tilesheets not provided by the mod.</param> + public ModContentHelper(ContentCoordinator contentCore, string modFolderPath, string modID, string modName, IContentManager gameContentManager) + : base(modID) + { + string managedAssetPrefix = contentCore.GetManagedAssetPrefix(modID); + + this.ContentCore = contentCore; + this.ModContentManager = contentCore.CreateModContentManager(managedAssetPrefix, modName, modFolderPath, gameContentManager); + this.ModName = modName; + } + + /// <inheritdoc /> + public T Load<T>(string relativePath) + { + IAssetName assetName = this.ContentCore.ParseAssetName(relativePath); + + try + { + return this.ModContentManager.LoadExact<T>(assetName, useCache: false); + } + catch (Exception ex) when (ex is not SContentLoadException) + { + throw new SContentLoadException($"{this.ModName} failed loading content asset '{relativePath}' from its mod folder.", ex); + } + } + + /// <inheritdoc /> + public IAssetName GetInternalAssetName(string relativePath) + { + return this.ModContentManager.GetInternalAssetKey(relativePath); + } + + /// <inheritdoc /> + public IAssetData GetPatchHelper<T>(T data, string relativePath = null) + { + if (data == null) + throw new ArgumentNullException(nameof(data), "Can't get a patch helper for a null value."); + + relativePath ??= $"temp/{Guid.NewGuid():N}"; + + return new AssetDataForObject(this.ContentCore.GetLocale(), this.ContentCore.ParseAssetName(relativePath), data, key => this.ContentCore.ParseAssetName(key).Name); + } + } +} diff --git a/src/SMAPI/Framework/ModHelpers/ModHelper.cs b/src/SMAPI/Framework/ModHelpers/ModHelper.cs index 058bff83..d28faacc 100644 --- a/src/SMAPI/Framework/ModHelpers/ModHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ModHelper.cs @@ -9,6 +9,14 @@ namespace StardewModdingAPI.Framework.ModHelpers internal class ModHelper : BaseHelper, IModHelper, IDisposable { /********* + ** Fields + *********/ + /// <summary>The backing field for <see cref="Content"/>.</summary> + [Obsolete] + private readonly IContentHelper ContentImpl; + + + /********* ** Accessors *********/ /// <inheritdoc /> @@ -18,7 +26,27 @@ namespace StardewModdingAPI.Framework.ModHelpers public IModEvents Events { get; } /// <inheritdoc /> - public IContentHelper Content { get; } + [Obsolete] + public IContentHelper Content + { + get + { + SCore.DeprecationManager.Warn( + source: SCore.DeprecationManager.GetSourceName(this.ModID), + nounPhrase: $"{nameof(IModHelper)}.{nameof(IModHelper.Content)}", + version: "3.14.0", + severity: DeprecationLevel.Notice + ); + + return this.ContentImpl; + } + } + + /// <inheritdoc /> + public IGameContentHelper GameContent { get; } + + /// <inheritdoc /> + public IModContentHelper ModContent { get; } /// <inheritdoc /> public IContentPackHelper ContentPacks { get; } @@ -54,6 +82,8 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <param name="currentInputState">Manages the game's input state for the current player instance. That may not be the main player in split-screen mode.</param> /// <param name="events">Manages access to events raised by SMAPI.</param> /// <param name="contentHelper">An API for loading content assets.</param> + /// <param name="gameContentHelper">An API for loading content assets from the game's <c>Content</c> folder or via <see cref="IModEvents.Content"/>.</param> + /// <param name="modContentHelper">An API for loading content assets from your mod's files.</param> /// <param name="contentPackHelper">An API for managing content packs.</param> /// <param name="commandHelper">An API for managing console commands.</param> /// <param name="dataHelper">An API for reading and writing persistent mod data.</param> @@ -63,7 +93,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <param name="translationHelper">An API for reading translations stored in the mod's <c>i18n</c> folder.</param> /// <exception cref="ArgumentNullException">An argument is null or empty.</exception> /// <exception cref="InvalidOperationException">The <paramref name="modDirectory"/> path does not exist on disk.</exception> - public ModHelper(string modID, string modDirectory, Func<SInputState> currentInputState, IModEvents events, IContentHelper contentHelper, IContentPackHelper contentPackHelper, ICommandHelper commandHelper, IDataHelper dataHelper, IModRegistry modRegistry, IReflectionHelper reflectionHelper, IMultiplayerHelper multiplayer, ITranslationHelper translationHelper) + public ModHelper(string modID, string modDirectory, Func<SInputState> currentInputState, IModEvents events, IContentHelper contentHelper, IGameContentHelper gameContentHelper, IModContentHelper modContentHelper, IContentPackHelper contentPackHelper, ICommandHelper commandHelper, IDataHelper dataHelper, IModRegistry modRegistry, IReflectionHelper reflectionHelper, IMultiplayerHelper multiplayer, ITranslationHelper translationHelper) : base(modID) { // validate directory @@ -74,7 +104,9 @@ namespace StardewModdingAPI.Framework.ModHelpers // initialize this.DirectoryPath = modDirectory; - this.Content = contentHelper ?? throw new ArgumentNullException(nameof(contentHelper)); + this.ContentImpl = contentHelper ?? throw new ArgumentNullException(nameof(contentHelper)); + this.GameContent = gameContentHelper ?? throw new ArgumentNullException(nameof(gameContentHelper)); + this.ModContent = modContentHelper ?? throw new ArgumentNullException(nameof(modContentHelper)); this.ContentPacks = contentPackHelper ?? throw new ArgumentNullException(nameof(contentPackHelper)); this.Data = dataHelper ?? throw new ArgumentNullException(nameof(dataHelper)); this.Input = new InputHelper(modID, currentInputState); |