diff --git a/src/SMAPI/Events/AssetReadyEventArgs.cs b/src/SMAPI/Events/AssetReadyEventArgs.cs
index 946c9173..2c308f18 100644
--- a/src/SMAPI/Events/AssetReadyEventArgs.cs
+++ b/src/SMAPI/Events/AssetReadyEventArgs.cs
@@ -11,15 +11,21 @@ namespace StardewModdingAPI.Events
/// The name of the asset being requested.
public IAssetName Name { get; }
+ /// The with any locale codes stripped.
+ /// For example, if contains a locale like Data/Bundles.fr-FR, this will be the name without locale like Data/Bundles. If the name has no locale, this field is equivalent.
+ public IAssetName NameWithoutLocale { get; }
+
/*********
** Public methods
*********/
/// Construct an instance.
/// The name of the asset being requested.
- internal AssetReadyEventArgs(IAssetName name)
+ /// The with any locale codes stripped.
+ internal AssetReadyEventArgs(IAssetName name, IAssetName nameWithoutLocale)
{
this.Name = name;
+ this.NameWithoutLocale = nameWithoutLocale;
}
}
}
diff --git a/src/SMAPI/Events/AssetRequestedEventArgs.cs b/src/SMAPI/Events/AssetRequestedEventArgs.cs
index d022a4de..9e2cde7f 100644
--- a/src/SMAPI/Events/AssetRequestedEventArgs.cs
+++ b/src/SMAPI/Events/AssetRequestedEventArgs.cs
@@ -26,6 +26,10 @@ namespace StardewModdingAPI.Events
/// The name of the asset being requested.
public IAssetName Name { get; }
+ /// The with any locale codes stripped.
+ /// For example, if contains a locale like Data/Bundles.fr-FR, this will be the name without locale like Data/Bundles. If the name has no locale, this field is equivalent.
+ public IAssetName NameWithoutLocale { get; }
+
/// The load operations requested by the event handler.
internal IList LoadOperations { get; } = new List();
@@ -39,11 +43,13 @@ namespace StardewModdingAPI.Events
/// Construct an instance.
/// The mod handling the event.
/// The name of the asset being requested.
+ /// The with any locale codes stripped.
/// Get the mod metadata for a content pack, if it's a valid content pack for the mod.
- internal AssetRequestedEventArgs(IModMetadata mod, IAssetName name, Func getOnBehalfOf)
+ internal AssetRequestedEventArgs(IModMetadata mod, IAssetName name, IAssetName nameWithoutLocale, Func getOnBehalfOf)
{
this.Mod = mod;
this.Name = name;
+ this.NameWithoutLocale = nameWithoutLocale;
this.GetOnBehalfOf = getOnBehalfOf;
}
diff --git a/src/SMAPI/Events/AssetsInvalidatedEventArgs.cs b/src/SMAPI/Events/AssetsInvalidatedEventArgs.cs
index f3d83dd6..614cdf49 100644
--- a/src/SMAPI/Events/AssetsInvalidatedEventArgs.cs
+++ b/src/SMAPI/Events/AssetsInvalidatedEventArgs.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
-using System.Linq;
namespace StardewModdingAPI.Events
{
@@ -14,15 +13,21 @@ namespace StardewModdingAPI.Events
/// The asset names that were invalidated.
public IReadOnlySet Names { get; }
+ /// The with any locale codes stripped.
+ /// For example, if contains a locale like Data/Bundles.fr-FR, this will have the name without locale like Data/Bundles. If the name has no locale, this field is equivalent.
+ public IReadOnlySet NamesWithoutLocale { get; }
+
/*********
** Public methods
*********/
/// Construct an instance.
/// The asset names that were invalidated.
- internal AssetsInvalidatedEventArgs(IEnumerable names)
+ /// The with any locale codes stripped.
+ internal AssetsInvalidatedEventArgs(IEnumerable names, IEnumerable namesWithoutLocale)
{
this.Names = names.ToImmutableHashSet();
+ this.NamesWithoutLocale = namesWithoutLocale.ToImmutableHashSet();
}
}
}
diff --git a/src/SMAPI/Framework/Content/AssetInfo.cs b/src/SMAPI/Framework/Content/AssetInfo.cs
index 6a5b4f31..556f1c2a 100644
--- a/src/SMAPI/Framework/Content/AssetInfo.cs
+++ b/src/SMAPI/Framework/Content/AssetInfo.cs
@@ -23,8 +23,11 @@ namespace StardewModdingAPI.Framework.Content
public IAssetName Name { get; }
///
- [Obsolete($"Use {nameof(Name)} instead.")]
- public string AssetName => this.Name.Name;
+ public IAssetName NameWithoutLocale { get; }
+
+ ///
+ [Obsolete($"Use {nameof(Name)} or {nameof(NameWithoutLocale)} instead.")]
+ public string AssetName => this.NameWithoutLocale.Name;
///
public Type DataType { get; }
@@ -42,15 +45,16 @@ namespace StardewModdingAPI.Framework.Content
{
this.Locale = locale;
this.Name = assetName;
+ this.NameWithoutLocale = assetName.GetBaseAssetName();
this.DataType = type;
this.GetNormalizedPath = getNormalizedPath;
}
///
- [Obsolete($"Use {nameof(Name)}.{nameof(IAssetName.IsEquivalentTo)} instead.")]
+ [Obsolete($"Use {nameof(Name)}.{nameof(IAssetName.IsEquivalentTo)} or {nameof(NameWithoutLocale)}.{nameof(IAssetName.IsEquivalentTo)} instead.")]
public bool AssetNameEquals(string path)
{
- return this.Name.IsEquivalentTo(path);
+ return this.NameWithoutLocale.IsEquivalentTo(path);
}
diff --git a/src/SMAPI/Framework/Content/AssetName.cs b/src/SMAPI/Framework/Content/AssetName.cs
index 992647f8..7ce0f8ee 100644
--- a/src/SMAPI/Framework/Content/AssetName.cs
+++ b/src/SMAPI/Framework/Content/AssetName.cs
@@ -142,11 +142,20 @@ namespace StardewModdingAPI.Framework.Content
}
+ ///
public bool IsDirectlyUnderPath(string assetFolder)
{
return this.StartsWith(assetFolder + "/", allowPartialWord: false, allowSubfolder: false);
}
+ ///
+ IAssetName IAssetName.GetBaseAssetName()
+ {
+ return this.LocaleCode == null
+ ? this
+ : new AssetName(this.BaseName, null, null);
+ }
+
///
public bool Equals(IAssetName other)
{
diff --git a/src/SMAPI/Framework/ContentCoordinator.cs b/src/SMAPI/Framework/ContentCoordinator.cs
index 144832b2..fc137e50 100644
--- a/src/SMAPI/Framework/ContentCoordinator.cs
+++ b/src/SMAPI/Framework/ContentCoordinator.cs
@@ -53,7 +53,7 @@ namespace StardewModdingAPI.Framework
private readonly Action OnAssetLoaded;
/// A callback to invoke when any asset names have been invalidated from the cache.
- private readonly Action> OnAssetsInvalidated;
+ private readonly Action> OnAssetsInvalidated;
/// Get the load/edit operations to apply to an asset by querying registered event handlers.
private readonly Func> RequestAssetOperations;
@@ -118,7 +118,7 @@ namespace StardewModdingAPI.Framework
/// Whether to enable more aggressive memory optimizations.
/// A callback to invoke when any asset names have been invalidated from the cache.
/// Get the load/edit operations to apply to an asset by querying registered event handlers.
- public ContentCoordinator(IServiceProvider serviceProvider, string rootDirectory, CultureInfo currentCulture, IMonitor monitor, Reflector reflection, JsonHelper jsonHelper, Action onLoadingFirstAsset, Action onAssetLoaded, bool aggressiveMemoryOptimizations, Action> onAssetsInvalidated, Func> requestAssetOperations)
+ public ContentCoordinator(IServiceProvider serviceProvider, string rootDirectory, CultureInfo currentCulture, IMonitor monitor, Reflector reflection, JsonHelper jsonHelper, Action onLoadingFirstAsset, Action onAssetLoaded, bool aggressiveMemoryOptimizations, Action> onAssetsInvalidated, Func> requestAssetOperations)
{
this.AggressiveMemoryOptimizations = aggressiveMemoryOptimizations;
this.Monitor = monitor ?? throw new ArgumentNullException(nameof(monitor));
@@ -414,7 +414,7 @@ namespace StardewModdingAPI.Framework
this.AssetOperationsByKey.Remove(name);
// raise event
- this.OnAssetsInvalidated(invalidatedAssets.Keys);
+ this.OnAssetsInvalidated(invalidatedAssets.Keys.ToArray());
// propagate changes to the game
this.CoreAssets.Propagate(
diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs
index dd682e40..dd952dee 100644
--- a/src/SMAPI/Framework/SCore.cs
+++ b/src/SMAPI/Framework/SCore.cs
@@ -1113,15 +1113,15 @@ namespace StardewModdingAPI.Framework
private void OnAssetLoaded(IContentManager contentManager, IAssetName assetName)
{
if (this.EventManager.AssetReady.HasListeners())
- this.EventManager.AssetReady.Raise(new AssetReadyEventArgs(assetName));
+ this.EventManager.AssetReady.Raise(new AssetReadyEventArgs(assetName, assetName.GetBaseAssetName()));
}
/// A callback invoked after assets have been invalidated from the content cache.
/// The invalidated asset names.
- private void OnAssetsInvalidated(IEnumerable assetNames)
+ private void OnAssetsInvalidated(IList assetNames)
{
if (this.EventManager.AssetsInvalidated.HasListeners())
- this.EventManager.AssetsInvalidated.Raise(new AssetsInvalidatedEventArgs(assetNames));
+ this.EventManager.AssetsInvalidated.Raise(new AssetsInvalidatedEventArgs(assetNames, assetNames.Select(p => p.GetBaseAssetName())));
}
/// Get the load/edit operations to apply to an asset by querying registered event handlers.
@@ -1133,7 +1133,7 @@ namespace StardewModdingAPI.Framework
this.EventManager.AssetRequested.Raise(
invoke: (mod, invoke) =>
{
- AssetRequestedEventArgs args = new(mod, asset.Name, this.GetOnBehalfOfContentPack);
+ AssetRequestedEventArgs args = new(mod, asset.Name, asset.NameWithoutLocale, this.GetOnBehalfOfContentPack);
invoke(args);
diff --git a/src/SMAPI/IAssetInfo.cs b/src/SMAPI/IAssetInfo.cs
index 6ac8358d..c7b2ab62 100644
--- a/src/SMAPI/IAssetInfo.cs
+++ b/src/SMAPI/IAssetInfo.cs
@@ -14,8 +14,12 @@ namespace StardewModdingAPI
/// The asset name being read.
public IAssetName Name { get; }
+ /// The with any locale codes stripped.
+ /// For example, if contains a locale like Data/Bundles.fr-FR, this will be the name without locale like Data/Bundles. If the name has no locale, this field is equivalent.
+ public IAssetName NameWithoutLocale { get; }
+
/// The normalized asset name being read. The format may change between platforms; see to compare with a known path.
- [Obsolete($"Use {nameof(Name)} instead.")]
+ [Obsolete($"Use {nameof(Name)} or {nameof(NameWithoutLocale)} instead.")]
string AssetName { get; }
/// The content data type.
@@ -27,7 +31,7 @@ namespace StardewModdingAPI
*********/
/// Get whether the asset name being loaded matches a given name after normalization.
/// The expected asset path, relative to the game's content folder and without the .xnb extension or locale suffix (like 'Data\ObjectInformation').
- [Obsolete($"Use {nameof(Name)}.{nameof(IAssetName.IsEquivalentTo)} instead.")]
+ [Obsolete($"Use {nameof(Name)}.{nameof(IAssetName.IsEquivalentTo)} or {nameof(NameWithoutLocale)}.{nameof(IAssetName.IsEquivalentTo)} instead.")]
bool AssetNameEquals(string path);
}
}
diff --git a/src/SMAPI/IAssetName.cs b/src/SMAPI/IAssetName.cs
index a5bfea93..89f02adf 100644
--- a/src/SMAPI/IAssetName.cs
+++ b/src/SMAPI/IAssetName.cs
@@ -40,5 +40,8 @@ namespace StardewModdingAPI
/// For example, Characters/Dialogue/Abigail is directly under Characters/Dialogue but not Characters or Characters/Dialogue/Ab. To allow sub-paths, use instead.
/// The asset path to check. This doesn't need a trailing slash.
bool IsDirectlyUnderPath(string assetFolder);
+
+ /// Get an asset name representing the without locale.
+ internal IAssetName GetBaseAssetName();
}
}