add support for propagating map asset changes
This commit is contained in:
parent
43f11cfe51
commit
fb253941df
|
@ -4,6 +4,7 @@
|
||||||
* Fixed cryptic error when running the installer from inside a zip file on Windows.
|
* Fixed cryptic error when running the installer from inside a zip file on Windows.
|
||||||
|
|
||||||
* For modders:
|
* For modders:
|
||||||
|
* Reloading a map asset will now automatically update affected locations.
|
||||||
* Fixed newlines in most manifest fields not being ignored.
|
* Fixed newlines in most manifest fields not being ignored.
|
||||||
|
|
||||||
* For the web UI:
|
* For the web UI:
|
||||||
|
|
|
@ -238,28 +238,30 @@ namespace StardewModdingAPI.Framework
|
||||||
public IEnumerable<string> InvalidateCache(Func<string, Type, bool> predicate, bool dispose = false)
|
public IEnumerable<string> InvalidateCache(Func<string, Type, bool> predicate, bool dispose = false)
|
||||||
{
|
{
|
||||||
// invalidate cache
|
// invalidate cache
|
||||||
HashSet<string> removedAssetNames = new HashSet<string>();
|
IDictionary<string, Type> removedAssetNames = new Dictionary<string, Type>(StringComparer.InvariantCultureIgnoreCase);
|
||||||
foreach (IContentManager contentManager in this.ContentManagers)
|
foreach (IContentManager contentManager in this.ContentManagers)
|
||||||
{
|
{
|
||||||
foreach (string name in contentManager.InvalidateCache(predicate, dispose))
|
foreach (Tuple<string, Type> asset in contentManager.InvalidateCache(predicate, dispose))
|
||||||
removedAssetNames.Add(name);
|
removedAssetNames[asset.Item1] = asset.Item2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reload core game assets
|
// reload core game assets
|
||||||
int reloaded = 0;
|
int reloaded = 0;
|
||||||
foreach (string key in removedAssetNames)
|
foreach (var pair in removedAssetNames)
|
||||||
{
|
{
|
||||||
if (this.CoreAssets.Propagate(this.MainContentManager, key)) // use an intercepted content manager
|
string key = pair.Key;
|
||||||
|
Type type = pair.Value;
|
||||||
|
if (this.CoreAssets.Propagate(this.MainContentManager, key, type)) // use an intercepted content manager
|
||||||
reloaded++;
|
reloaded++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// report result
|
// report result
|
||||||
if (removedAssetNames.Any())
|
if (removedAssetNames.Any())
|
||||||
this.Monitor.Log($"Invalidated {removedAssetNames.Count} asset names: {string.Join(", ", removedAssetNames.OrderBy(p => p, StringComparer.InvariantCultureIgnoreCase))}. Reloaded {reloaded} core assets.", LogLevel.Trace);
|
this.Monitor.Log($"Invalidated {removedAssetNames.Count} asset names: {string.Join(", ", removedAssetNames.Keys.OrderBy(p => p, StringComparer.InvariantCultureIgnoreCase))}. Reloaded {reloaded} core assets.", LogLevel.Trace);
|
||||||
else
|
else
|
||||||
this.Monitor.Log("Invalidated 0 cache entries.", LogLevel.Trace);
|
this.Monitor.Log("Invalidated 0 cache entries.", LogLevel.Trace);
|
||||||
|
|
||||||
return removedAssetNames;
|
return removedAssetNames.Keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Dispose held resources.</summary>
|
/// <summary>Dispose held resources.</summary>
|
||||||
|
|
|
@ -200,23 +200,25 @@ namespace StardewModdingAPI.Framework.ContentManagers
|
||||||
/// <summary>Purge matched assets from the cache.</summary>
|
/// <summary>Purge matched assets from the cache.</summary>
|
||||||
/// <param name="predicate">Matches the asset keys to invalidate.</param>
|
/// <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>
|
/// <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 number of invalidated assets.</returns>
|
/// <returns>Returns the invalidated asset names and types.</returns>
|
||||||
public IEnumerable<string> InvalidateCache(Func<string, Type, bool> predicate, bool dispose = false)
|
public IEnumerable<Tuple<string, Type>> InvalidateCache(Func<string, Type, bool> predicate, bool dispose = false)
|
||||||
{
|
{
|
||||||
HashSet<string> removeAssetNames = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
|
Dictionary<string, Type> removeAssetNames = new Dictionary<string, Type>(StringComparer.InvariantCultureIgnoreCase);
|
||||||
this.Cache.Remove((key, type) =>
|
this.Cache.Remove((key, type) =>
|
||||||
{
|
{
|
||||||
this.ParseCacheKey(key, out string assetName, out _);
|
this.ParseCacheKey(key, out string assetName, out _);
|
||||||
|
|
||||||
if (removeAssetNames.Contains(assetName) || predicate(assetName, type))
|
if (removeAssetNames.ContainsKey(assetName))
|
||||||
|
return true;
|
||||||
|
if (predicate(assetName, type))
|
||||||
{
|
{
|
||||||
removeAssetNames.Add(assetName);
|
removeAssetNames[assetName] = type;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
return removeAssetNames;
|
return removeAssetNames.Select(p => Tuple.Create(p.Key, p.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Dispose held resources.</summary>
|
/// <summary>Dispose held resources.</summary>
|
||||||
|
|
|
@ -80,7 +80,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
|
||||||
/// <summary>Purge matched assets from the cache.</summary>
|
/// <summary>Purge matched assets from the cache.</summary>
|
||||||
/// <param name="predicate">Matches the asset keys to invalidate.</param>
|
/// <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>
|
/// <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 number of invalidated assets.</returns>
|
/// <returns>Returns the invalidated asset names and types.</returns>
|
||||||
IEnumerable<string> InvalidateCache(Func<string, Type, bool> predicate, bool dispose = false);
|
IEnumerable<Tuple<string, Type>> InvalidateCache(Func<string, Type, bool> predicate, bool dispose = false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ using StardewValley.Menus;
|
||||||
using StardewValley.Objects;
|
using StardewValley.Objects;
|
||||||
using StardewValley.Projectiles;
|
using StardewValley.Projectiles;
|
||||||
using StardewValley.TerrainFeatures;
|
using StardewValley.TerrainFeatures;
|
||||||
|
using xTile;
|
||||||
using xTile.Tiles;
|
using xTile.Tiles;
|
||||||
|
|
||||||
namespace StardewModdingAPI.Metadata
|
namespace StardewModdingAPI.Metadata
|
||||||
|
@ -45,10 +46,11 @@ namespace StardewModdingAPI.Metadata
|
||||||
/// <summary>Reload one of the game's core assets (if applicable).</summary>
|
/// <summary>Reload one of the game's core assets (if applicable).</summary>
|
||||||
/// <param name="content">The content manager through which to reload the asset.</param>
|
/// <param name="content">The content manager through which to reload the asset.</param>
|
||||||
/// <param name="key">The asset key to reload.</param>
|
/// <param name="key">The asset key to reload.</param>
|
||||||
|
/// <param name="type">The asset type to reload.</param>
|
||||||
/// <returns>Returns whether an asset was reloaded.</returns>
|
/// <returns>Returns whether an asset was reloaded.</returns>
|
||||||
public bool Propagate(LocalizedContentManager content, string key)
|
public bool Propagate(LocalizedContentManager content, string key, Type type)
|
||||||
{
|
{
|
||||||
object result = this.PropagateImpl(content, key);
|
object result = this.PropagateImpl(content, key, type);
|
||||||
if (result is bool b)
|
if (result is bool b)
|
||||||
return b;
|
return b;
|
||||||
return result != null;
|
return result != null;
|
||||||
|
@ -61,9 +63,12 @@ namespace StardewModdingAPI.Metadata
|
||||||
/// <summary>Reload one of the game's core assets (if applicable).</summary>
|
/// <summary>Reload one of the game's core assets (if applicable).</summary>
|
||||||
/// <param name="content">The content manager through which to reload the asset.</param>
|
/// <param name="content">The content manager through which to reload the asset.</param>
|
||||||
/// <param name="key">The asset key to reload.</param>
|
/// <param name="key">The asset key to reload.</param>
|
||||||
/// <returns>Returns any non-null value to indicate an asset was loaded.</returns>
|
/// <param name="type">The asset type to reload.</param>
|
||||||
private object PropagateImpl(LocalizedContentManager content, string key)
|
/// <returns>Returns whether an asset was loaded. The return value may be true or false, or a non-null value for true.</returns>
|
||||||
|
private object PropagateImpl(LocalizedContentManager content, string key, Type type)
|
||||||
{
|
{
|
||||||
|
key = this.GetNormalisedPath(key);
|
||||||
|
|
||||||
/****
|
/****
|
||||||
** Special case: current map tilesheet
|
** Special case: current map tilesheet
|
||||||
** We only need to do this for the current location, since tilesheets are reloaded when you enter a location.
|
** We only need to do this for the current location, since tilesheets are reloaded when you enter a location.
|
||||||
|
@ -78,6 +83,23 @@ namespace StardewModdingAPI.Metadata
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****
|
||||||
|
** Propagate map changes
|
||||||
|
****/
|
||||||
|
if (type == typeof(Map))
|
||||||
|
{
|
||||||
|
bool anyChanged = false;
|
||||||
|
foreach (GameLocation location in this.GetLocations())
|
||||||
|
{
|
||||||
|
if (this.GetNormalisedPath(location.mapPath.Value) == key)
|
||||||
|
{
|
||||||
|
this.Reflection.GetMethod(location, "reloadMap").Invoke();
|
||||||
|
anyChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return anyChanged;
|
||||||
|
}
|
||||||
|
|
||||||
/****
|
/****
|
||||||
** Propagate by key
|
** Propagate by key
|
||||||
****/
|
****/
|
||||||
|
|
Loading…
Reference in New Issue