summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework/SGame.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI/Framework/SGame.cs')
-rw-r--r--src/SMAPI/Framework/SGame.cs50
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
*********/