diff options
author | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2020-01-05 20:18:16 -0500 |
---|---|---|
committer | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2020-01-05 20:18:16 -0500 |
commit | f976b5c0f095a881fc20f6ce5dcf5a50ebb2b5da (patch) | |
tree | 260fa7579e1c361283bda09c2616783c3fdb5b9a /src/SMAPI/Framework/Content | |
parent | d34f369d35290bca96cc7225d9765d1a8a66fa8b (diff) | |
parent | 48959375b9ef52abf7c7a9404d43aac6ba780047 (diff) | |
download | SMAPI-f976b5c0f095a881fc20f6ce5dcf5a50ebb2b5da.tar.gz SMAPI-f976b5c0f095a881fc20f6ce5dcf5a50ebb2b5da.tar.bz2 SMAPI-f976b5c0f095a881fc20f6ce5dcf5a50ebb2b5da.zip |
Merge branch 'develop' into stable
Diffstat (limited to 'src/SMAPI/Framework/Content')
-rw-r--r-- | src/SMAPI/Framework/Content/AssetDataForImage.cs | 4 | ||||
-rw-r--r-- | src/SMAPI/Framework/Content/AssetInterceptorChange.cs | 93 | ||||
-rw-r--r-- | src/SMAPI/Framework/Content/ContentCache.cs | 5 |
3 files changed, 97 insertions, 5 deletions
diff --git a/src/SMAPI/Framework/Content/AssetDataForImage.cs b/src/SMAPI/Framework/Content/AssetDataForImage.cs index 4ae2ad68..aa615a0b 100644 --- a/src/SMAPI/Framework/Content/AssetDataForImage.cs +++ b/src/SMAPI/Framework/Content/AssetDataForImage.cs @@ -42,8 +42,8 @@ namespace StardewModdingAPI.Framework.Content Texture2D target = this.Data; // get areas - sourceArea = sourceArea ?? new Rectangle(0, 0, source.Width, source.Height); - targetArea = targetArea ?? new Rectangle(0, 0, Math.Min(sourceArea.Value.Width, target.Width), Math.Min(sourceArea.Value.Height, target.Height)); + sourceArea ??= new Rectangle(0, 0, source.Width, source.Height); + targetArea ??= new Rectangle(0, 0, Math.Min(sourceArea.Value.Width, target.Width), Math.Min(sourceArea.Value.Height, target.Height)); // validate if (sourceArea.Value.X < 0 || sourceArea.Value.Y < 0 || sourceArea.Value.Right > source.Width || sourceArea.Value.Bottom > source.Height) diff --git a/src/SMAPI/Framework/Content/AssetInterceptorChange.cs b/src/SMAPI/Framework/Content/AssetInterceptorChange.cs new file mode 100644 index 00000000..037d9f89 --- /dev/null +++ b/src/SMAPI/Framework/Content/AssetInterceptorChange.cs @@ -0,0 +1,93 @@ +using System; +using System.Reflection; + +namespace StardewModdingAPI.Framework.Content +{ + /// <summary>A wrapper for <see cref="IAssetEditor"/> and <see cref="IAssetLoader"/> for internal cache invalidation.</summary> + internal class AssetInterceptorChange + { + /********* + ** Accessors + *********/ + /// <summary>The mod which registered the interceptor.</summary> + public IModMetadata Mod { get; } + + /// <summary>The interceptor instance.</summary> + public object Instance { get; } + + /// <summary>Whether the asset interceptor was added since the last tick. Mutually exclusive with <see cref="WasRemoved"/>.</summary> + public bool WasAdded { get; } + + /// <summary>Whether the asset interceptor was removed since the last tick. Mutually exclusive with <see cref="WasRemoved"/>.</summary> + public bool WasRemoved => this.WasAdded; + + + /********* + ** Public methods + *********/ + /// <summary>Construct an instance.</summary> + /// <param name="mod">The mod registering the interceptor.</param> + /// <param name="instance">The interceptor. This must be an <see cref="IAssetEditor"/> or <see cref="IAssetLoader"/> instance.</param> + /// <param name="wasAdded">Whether the asset interceptor was added since the last tick; else removed.</param> + public AssetInterceptorChange(IModMetadata mod, object instance, bool wasAdded) + { + this.Mod = mod ?? throw new ArgumentNullException(nameof(mod)); + this.Instance = instance ?? throw new ArgumentNullException(nameof(instance)); + this.WasAdded = wasAdded; + + if (!(instance is IAssetEditor) && !(instance is IAssetLoader)) + throw new InvalidCastException($"The provided {nameof(instance)} value must be an {nameof(IAssetEditor)} or {nameof(IAssetLoader)} instance."); + } + + /// <summary>Get whether this instance can intercept the given asset.</summary> + /// <param name="asset">Basic metadata about the asset being loaded.</param> + public bool CanIntercept(IAssetInfo asset) + { + MethodInfo canIntercept = this.GetType().GetMethod(nameof(this.CanInterceptImpl), BindingFlags.Instance | BindingFlags.NonPublic); + if (canIntercept == null) + throw new InvalidOperationException($"SMAPI couldn't access the {nameof(AssetInterceptorChange)}.{nameof(this.CanInterceptImpl)} implementation."); + + return (bool)canIntercept.MakeGenericMethod(asset.DataType).Invoke(this, new object[] { asset }); + } + + + /********* + ** Private methods + *********/ + /// <summary>Get whether this instance can intercept the given asset.</summary> + /// <typeparam name="TAsset">The asset type.</typeparam> + /// <param name="asset">Basic metadata about the asset being loaded.</param> + private bool CanInterceptImpl<TAsset>(IAssetInfo asset) + { + // check edit + if (this.Instance is IAssetEditor editor) + { + try + { + if (editor.CanEdit<TAsset>(asset)) + return true; + } + catch (Exception ex) + { + this.Mod.LogAsMod($"Mod failed when checking whether it could edit asset '{asset.AssetName}'. Error details:\n{ex.GetLogSummary()}", LogLevel.Error); + } + } + + // check load + if (this.Instance is IAssetLoader loader) + { + try + { + if (loader.CanLoad<TAsset>(asset)) + return true; + } + catch (Exception ex) + { + this.Mod.LogAsMod($"Mod failed when checking whether it could load asset '{asset.AssetName}'. Error details:\n{ex.GetLogSummary()}", LogLevel.Error); + } + } + + return false; + } + } +} diff --git a/src/SMAPI/Framework/Content/ContentCache.cs b/src/SMAPI/Framework/Content/ContentCache.cs index 4178b663..f33ff84d 100644 --- a/src/SMAPI/Framework/Content/ContentCache.cs +++ b/src/SMAPI/Framework/Content/ContentCache.cs @@ -119,13 +119,12 @@ namespace StardewModdingAPI.Framework.Content /// <param name="predicate">Matches the asset keys to invalidate.</param> /// <param name="dispose">Whether to dispose invalidated assets. This should only be <c>true</c> when they're being invalidated as part of a dispose, to avoid crashing the game.</param> /// <returns>Returns the removed keys (if any).</returns> - public IEnumerable<string> Remove(Func<string, Type, bool> predicate, bool dispose = false) + public IEnumerable<string> Remove(Func<string, object, bool> predicate, bool dispose) { List<string> removed = new List<string>(); foreach (string key in this.Cache.Keys.ToArray()) { - Type type = this.Cache[key].GetType(); - if (predicate(key, type)) + if (predicate(key, this.Cache[key])) { this.Remove(key, dispose); removed.Add(key); |