diff options
Diffstat (limited to 'src/SMAPI/Framework/SGame.cs')
-rw-r--r-- | src/SMAPI/Framework/SGame.cs | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/src/SMAPI/Framework/SGame.cs b/src/SMAPI/Framework/SGame.cs index 47261862..4774233e 100644 --- a/src/SMAPI/Framework/SGame.cs +++ b/src/SMAPI/Framework/SGame.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -12,6 +13,7 @@ using Microsoft.Xna.Framework.Graphics; using Netcode; using StardewModdingAPI.Enums; using StardewModdingAPI.Events; +using StardewModdingAPI.Framework.Content; using StardewModdingAPI.Framework.Events; using StardewModdingAPI.Framework.Input; using StardewModdingAPI.Framework.Networking; @@ -99,7 +101,7 @@ namespace StardewModdingAPI.Framework private WatcherCore Watchers; /// <summary>A snapshot of the current <see cref="Watchers"/> state.</summary> - private WatcherSnapshot WatcherSnapshot = new WatcherSnapshot(); + private readonly WatcherSnapshot WatcherSnapshot = new WatcherSnapshot(); /// <summary>Whether post-game-startup initialization has been performed.</summary> private bool IsInitialized; @@ -133,6 +135,9 @@ namespace StardewModdingAPI.Framework /// <remarks>This property must be threadsafe, since it's accessed from a separate console input thread.</remarks> public ConcurrentQueue<string> CommandQueue { get; } = new ConcurrentQueue<string>(); + /// <summary>Asset interceptors added or removed since the last tick.</summary> + private readonly List<AssetInterceptorChange> ReloadAssetInterceptorsQueue = new List<AssetInterceptorChange>(); + /********* ** Protected methods @@ -249,6 +254,24 @@ namespace StardewModdingAPI.Framework this.Events.ReturnedToTitle.RaiseEmpty(); } + /// <summary>A callback invoked when a mod adds or removes an asset interceptor.</summary> + /// <param name="mod">The mod which added or removed interceptors.</param> + /// <param name="added">The added interceptors.</param> + /// <param name="removed">The removed interceptors.</param> + internal void OnAssetInterceptorsChanged(IModMetadata mod, IEnumerable added, IEnumerable removed) + { + if (added != null) + { + foreach (object instance in added) + this.ReloadAssetInterceptorsQueue.Add(new AssetInterceptorChange(mod, instance, wasAdded: true)); + } + if (removed != null) + { + foreach (object instance in removed) + this.ReloadAssetInterceptorsQueue.Add(new AssetInterceptorChange(mod, instance, wasAdded: false)); + } + } + /// <summary>Constructor a content manager to read XNB files.</summary> /// <param name="serviceProvider">The service provider to use to locate services.</param> /// <param name="rootDirectory">The root directory to search for content.</param> @@ -404,6 +427,31 @@ namespace StardewModdingAPI.Framework return; } + + /********* + ** Reload assets when interceptors are added/removed + *********/ + if (this.ReloadAssetInterceptorsQueue.Any()) + { + this.Monitor.Log("Invalidating cached assets for new editors & loaders...", LogLevel.Trace); + this.Monitor.Log( + "changed: " + + string.Join(", ", + this.ReloadAssetInterceptorsQueue + .GroupBy(p => p.Mod) + .OrderBy(p => p.Key.DisplayName) + .Select(modGroup => + $"{modGroup.Key.DisplayName} (" + + string.Join(", ", modGroup.GroupBy(p => p.WasAdded).ToDictionary(p => p.Key, p => p.Count()).Select(p => $"{(p.Key ? "added" : "removed")} {p.Value}")) + + ")" + ) + ) + ); + + this.ContentCore.InvalidateCache(asset => this.ReloadAssetInterceptorsQueue.Any(p => p.CanIntercept(asset))); + this.ReloadAssetInterceptorsQueue.Clear(); + } + /********* ** Execute commands *********/ |