From bd04d46dd1d66b30d4f21575bbbd2e541eabcef3 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 22 May 2018 22:53:44 -0400 Subject: refactor content API to fix load errors with decentralised cache (#524) --- .../Framework/ContentManagers/IContentManager.cs | 81 ++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/SMAPI/Framework/ContentManagers/IContentManager.cs (limited to 'src/SMAPI/Framework/ContentManagers/IContentManager.cs') diff --git a/src/SMAPI/Framework/ContentManagers/IContentManager.cs b/src/SMAPI/Framework/ContentManagers/IContentManager.cs new file mode 100644 index 00000000..aa5be9b6 --- /dev/null +++ b/src/SMAPI/Framework/ContentManagers/IContentManager.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.Contracts; +using Microsoft.Xna.Framework.Content; +using StardewModdingAPI.Framework.Exceptions; +using StardewValley; + +namespace StardewModdingAPI.Framework.ContentManagers +{ + /// A content manager which handles reading files. + internal interface IContentManager : IDisposable + { + /********* + ** Accessors + *********/ + /// A name for the mod manager. Not guaranteed to be unique. + string Name { get; } + + /// The current language as a constant. + LocalizedContentManager.LanguageCode Language { get; } + + /// The absolute path to the . + string FullRootDirectory { get; } + + /// Whether this content manager is for a mod folder. + bool IsModContentManager { get; } + + + /********* + ** Methods + *********/ + /// Load an asset that has been processed by the content pipeline. + /// The type of asset to load. + /// The asset path relative to the loader root directory, not including the .xnb extension. + T Load(string assetName); + + /// Load an asset that has been processed by the content pipeline. + /// The type of asset to load. + /// The asset path relative to the loader root directory, not including the .xnb extension. + /// The language code for which to load content. + T Load(string assetName, LocalizedContentManager.LanguageCode language); + + /// Inject an asset into the cache. + /// The type of asset to inject. + /// The asset path relative to the loader root directory, not including the .xnb extension. + /// The asset value. + void Inject(string assetName, T value); + + /// Normalise path separators in a file path. For asset keys, see instead. + /// The file path to normalise. + [Pure] + string NormalisePathSeparators(string path); + + /// Assert that the given key has a valid format and return a normalised form consistent with the underlying cache. + /// The asset key to check. + /// The asset key is empty or contains invalid characters. + [SuppressMessage("ReSharper", "ParameterOnlyUsedForPreconditionCheck.Local", Justification = "Parameter is only used for assertion checks by design.")] + string AssertAndNormaliseAssetName(string assetName); + + /// Get the current content locale. + string GetLocale(); + + /// The locale for a language. + /// The language. + string GetLocale(LocalizedContentManager.LanguageCode language); + + /// Get whether the content manager has already loaded and cached the given asset. + /// The asset path relative to the loader root directory, not including the .xnb extension. + bool IsLoaded(string assetName); + + /// Get the cached asset keys. + IEnumerable GetAssetKeys(); + + /// Purge matched assets from the cache. + /// Matches the asset keys to invalidate. + /// Whether to dispose invalidated assets. This should only be true when they're being invalidated as part of a dispose, to avoid crashing the game. + /// Returns the number of invalidated assets. + IEnumerable InvalidateCache(Func predicate, bool dispose = false); + } +} -- cgit From fa36e80a118b4bcaa021b349bff3e70e3b903976 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 30 May 2018 21:16:46 -0400 Subject: fix game content managers not cloning assets from IAssetLoader --- src/SMAPI/Framework/ContentCoordinator.cs | 23 +---------------- .../ContentManagers/BaseContentManager.cs | 29 ++++++++++++++++++++++ .../ContentManagers/GameContentManager.cs | 2 +- .../Framework/ContentManagers/IContentManager.cs | 5 ++++ 4 files changed, 36 insertions(+), 23 deletions(-) (limited to 'src/SMAPI/Framework/ContentManagers/IContentManager.cs') diff --git a/src/SMAPI/Framework/ContentCoordinator.cs b/src/SMAPI/Framework/ContentCoordinator.cs index c2614001..caa5b538 100644 --- a/src/SMAPI/Framework/ContentCoordinator.cs +++ b/src/SMAPI/Framework/ContentCoordinator.cs @@ -5,7 +5,6 @@ using System.IO; using System.Linq; using System.Reflection; using Microsoft.Xna.Framework.Content; -using Microsoft.Xna.Framework.Graphics; using StardewModdingAPI.Framework.Content; using StardewModdingAPI.Framework.ContentManagers; using StardewModdingAPI.Framework.Reflection; @@ -157,27 +156,7 @@ namespace StardewModdingAPI.Framework // get cloned asset T data = contentManager.Load(internalKey, language); - switch (data as object) - { - case Texture2D source: - { - int[] pixels = new int[source.Width * source.Height]; - source.GetData(pixels); - - Texture2D clone = new Texture2D(source.GraphicsDevice, source.Width, source.Height); - clone.SetData(pixels); - return (T)(object)clone; - } - - case Dictionary source: - return (T)(object)new Dictionary(source); - - case Dictionary source: - return (T)(object)new Dictionary(source); - - default: - return data; - } + return contentManager.CloneIfPossible(data); } /// Purge assets from the cache that match one of the interceptors. diff --git a/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs b/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs index ff0e2de4..18aae05b 100644 --- a/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs +++ b/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs @@ -6,6 +6,7 @@ using System.Globalization; using System.IO; using System.Linq; using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; using StardewModdingAPI.Framework.Content; using StardewModdingAPI.Framework.Exceptions; using StardewModdingAPI.Framework.Reflection; @@ -109,6 +110,34 @@ namespace StardewModdingAPI.Framework.ContentManagers } + /// Get a copy of the given asset if supported. + /// The asset type. + /// The asset to clone. + public T CloneIfPossible(T asset) + { + switch (asset as object) + { + case Texture2D source: + { + int[] pixels = new int[source.Width * source.Height]; + source.GetData(pixels); + + Texture2D clone = new Texture2D(source.GraphicsDevice, source.Width, source.Height); + clone.SetData(pixels); + return (T)(object)clone; + } + + case Dictionary source: + return (T)(object)new Dictionary(source); + + case Dictionary source: + return (T)(object)new Dictionary(source); + + default: + return asset; + } + } + /// Normalise path separators in a file path. For asset keys, see instead. /// The file path to normalise. [Pure] diff --git a/src/SMAPI/Framework/ContentManagers/GameContentManager.cs b/src/SMAPI/Framework/ContentManagers/GameContentManager.cs index cfedb5af..a53840bc 100644 --- a/src/SMAPI/Framework/ContentManagers/GameContentManager.cs +++ b/src/SMAPI/Framework/ContentManagers/GameContentManager.cs @@ -161,7 +161,7 @@ namespace StardewModdingAPI.Framework.ContentManagers T data; try { - data = loader.Load(info); + data = this.CloneIfPossible(loader.Load(info)); this.Monitor.Log($"{mod.DisplayName} loaded asset '{info.AssetName}'.", LogLevel.Trace); } catch (Exception ex) diff --git a/src/SMAPI/Framework/ContentManagers/IContentManager.cs b/src/SMAPI/Framework/ContentManagers/IContentManager.cs index aa5be9b6..1eb8b0ac 100644 --- a/src/SMAPI/Framework/ContentManagers/IContentManager.cs +++ b/src/SMAPI/Framework/ContentManagers/IContentManager.cs @@ -47,6 +47,11 @@ namespace StardewModdingAPI.Framework.ContentManagers /// The asset value. void Inject(string assetName, T value); + /// Get a copy of the given asset if supported. + /// The asset type. + /// The asset to clone. + T CloneIfPossible(T asset); + /// Normalise path separators in a file path. For asset keys, see instead. /// The file path to normalise. [Pure] -- cgit