summaryrefslogtreecommitdiff
path: root/src/StardewModdingAPI
diff options
context:
space:
mode:
Diffstat (limited to 'src/StardewModdingAPI')
-rw-r--r--src/StardewModdingAPI/Framework/ContentEventHelper.cs39
-rw-r--r--src/StardewModdingAPI/Framework/SContentManager.cs48
-rw-r--r--src/StardewModdingAPI/IContentEventHelper.cs14
3 files changed, 53 insertions, 48 deletions
diff --git a/src/StardewModdingAPI/Framework/ContentEventHelper.cs b/src/StardewModdingAPI/Framework/ContentEventHelper.cs
index d4a9bbb8..a58efe32 100644
--- a/src/StardewModdingAPI/Framework/ContentEventHelper.cs
+++ b/src/StardewModdingAPI/Framework/ContentEventHelper.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Text.RegularExpressions;
using Microsoft.Xna.Framework.Graphics;
namespace StardewModdingAPI.Framework
@@ -18,8 +17,11 @@ namespace StardewModdingAPI.Framework
/*********
** Accessors
*********/
- /// <summary>The normalised asset path being read. The format may change between platforms; see <see cref="IsPath"/> to compare with a known path.</summary>
- public string Path { get; }
+ /// <summary>The content's locale code, if the content is localised.</summary>
+ public string Locale { get; }
+
+ /// <summary>The normalised asset name being read. The format may change between platforms; see <see cref="IsAssetName"/> to compare with a known path.</summary>
+ public string AssetName { get; }
/// <summary>The content data being read.</summary>
public object Data { get; private set; }
@@ -29,37 +31,24 @@ namespace StardewModdingAPI.Framework
** Public methods
*********/
/// <summary>Construct an instance.</summary>
- /// <param name="path">The file path being read.</param>
+ /// <param name="locale">The content's locale code, if the content is localised.</param>
+ /// <param name="assetName">The normalised asset name being read.</param>
/// <param name="data">The content data being read.</param>
/// <param name="getNormalisedPath">Normalises an asset key to match the cache key.</param>
- public ContentEventHelper(string path, object data, Func<string, string> getNormalisedPath)
+ public ContentEventHelper(string locale, string assetName, object data, Func<string, string> getNormalisedPath)
{
- this.Path = path;
+ this.Locale = locale;
+ this.AssetName = assetName;
this.Data = data;
this.GetNormalisedPath = getNormalisedPath;
}
- /// <summary>Get whether the asset path being loaded matches a given path after normalisation.</summary>
- /// <param name="path">The expected asset path, relative to the game folder and without the .xnb extension (like 'Data\ObjectInformation').</param>
- /// <param name="matchLocalisedVersion">Whether to match a localised version of the asset file (like 'Data\ObjectInformation.ja-JP').</param>
- public bool IsPath(string path, bool matchLocalisedVersion = true)
+ /// <summary>Get whether the asset name being loaded matches a given name after normalisation.</summary>
+ /// <param name="path">The expected asset path, relative to the game's content folder and without the .xnb extension or locale suffix (like 'Data\ObjectInformation').</param>
+ public bool IsAssetName(string path)
{
path = this.GetNormalisedPath(path);
-
- // equivalent
- if (this.Path.Equals(path, StringComparison.InvariantCultureIgnoreCase))
- return true;
-
- // localised version
- if (matchLocalisedVersion)
- {
- return
- this.Path.StartsWith($"{path}.", StringComparison.InvariantCultureIgnoreCase) // starts with given path
- && Regex.IsMatch(this.Path.Substring(path.Length + 1), "^[a-z]+-[A-Z]+$"); // ends with locale (e.g. pt-BR)
- }
-
- // no match
- return false;
+ return this.AssetName.Equals(path, StringComparison.InvariantCultureIgnoreCase);
}
/// <summary>Get the data as a given type.</summary>
diff --git a/src/StardewModdingAPI/Framework/SContentManager.cs b/src/StardewModdingAPI/Framework/SContentManager.cs
index 45f42bf6..65c330db 100644
--- a/src/StardewModdingAPI/Framework/SContentManager.cs
+++ b/src/StardewModdingAPI/Framework/SContentManager.cs
@@ -31,7 +31,10 @@ namespace StardewModdingAPI.Framework
private readonly IDictionary<string, object> Cache;
/// <summary>Applies platform-specific asset key normalisation so it's consistent with the underlying cache.</summary>
- private readonly Func<string, string> NormaliseKeyForPlatform;
+ private readonly Func<string, string> NormaliseAssetNameForPlatform;
+
+ /// <summary>The private <see cref="LocalizedContentManager"/> method which generates the locale portion of an asset name.</summary>
+ private readonly IPrivateMethod GetKeyLocale;
/*********
@@ -57,19 +60,18 @@ namespace StardewModdingAPI.Framework
this.Monitor = monitor;
IReflectionHelper reflection = new ReflectionHelper();
- // get underlying asset cache
- this.Cache = reflection
- .GetPrivateField<Dictionary<string, object>>(this, "loadedAssets")
- .GetValue();
+ // get underlying fields for interception
+ this.Cache = reflection.GetPrivateField<Dictionary<string, object>>(this, "loadedAssets").GetValue();
+ this.GetKeyLocale = reflection.GetPrivateMethod(this, "languageCode");
// get asset key normalisation logic
if (Constants.TargetPlatform == Platform.Windows)
{
IPrivateMethod method = reflection.GetPrivateMethod(typeof(TitleContainer), "GetCleanPath");
- this.NormaliseKeyForPlatform = path => method.Invoke<string>(path);
+ this.NormaliseAssetNameForPlatform = path => method.Invoke<string>(path);
}
else
- this.NormaliseKeyForPlatform = key => key.Replace('\\', '/'); // based on MonoGame's ContentManager.Load<T> logic
+ this.NormaliseAssetNameForPlatform = key => key.Replace('\\', '/'); // based on MonoGame's ContentManager.Load<T> logic
}
/// <summary>Load an asset that has been processed by the content pipeline.</summary>
@@ -77,8 +79,8 @@ namespace StardewModdingAPI.Framework
/// <param name="assetName">The asset path relative to the loader root directory, not including the <c>.xnb</c> extension.</param>
public override T Load<T>(string assetName)
{
- // normalise key so can override the cache value later
- assetName = this.NormaliseKey(assetName);
+ // normalise asset name so can override the cache value later
+ assetName = this.NormaliseAssetName(assetName);
// skip if no event handlers or already loaded
if (!ContentEvents.HasAssetLoadingListeners() || this.Cache.ContainsKey(assetName))
@@ -86,7 +88,8 @@ namespace StardewModdingAPI.Framework
// intercept load
T data = base.Load<T>(assetName);
- IContentEventHelper helper = new ContentEventHelper(assetName, data, this.NormaliseKeyForPlatform);
+ string cacheLocale = this.GetCacheLocale(assetName, this.Cache);
+ IContentEventHelper helper = new ContentEventHelper(cacheLocale, assetName, data, this.NormaliseAssetName);
ContentEvents.InvokeAssetLoading(this.Monitor, helper);
this.Cache[assetName] = helper.Data;
return (T)helper.Data;
@@ -96,16 +99,27 @@ namespace StardewModdingAPI.Framework
/*********
** Private methods
*********/
- /// <summary>Normalise an asset key so it's consistent with the underlying cache.</summary>
- /// <param name="key">The asset key.</param>
- private string NormaliseKey(string key)
+ /// <summary>Normalise an asset name so it's consistent with the underlying cache.</summary>
+ /// <param name="assetName">The asset key.</param>
+ private string NormaliseAssetName(string assetName)
{
- // ensure key format is consistent
- string[] parts = key.Split(SContentManager.PossiblePathSeparators, StringSplitOptions.RemoveEmptyEntries);
- key = string.Join(SContentManager.PreferredPathSeparator, parts);
+ // ensure name format is consistent
+ string[] parts = assetName.Split(SContentManager.PossiblePathSeparators, StringSplitOptions.RemoveEmptyEntries);
+ assetName = string.Join(SContentManager.PreferredPathSeparator, parts);
// apply platform normalisation logic
- return this.NormaliseKeyForPlatform(key);
+ return this.NormaliseAssetNameForPlatform(assetName);
+ }
+
+ /// <summary>Get the locale for which the asset name was saved, if any.</summary>
+ /// <param name="normalisedAssetName">The normalised asset name.</param>
+ /// <param name="cache">The cache to search.</param>
+ private string GetCacheLocale(string normalisedAssetName, IDictionary<string, object> cache)
+ {
+ string locale = this.GetKeyLocale.Invoke<string>();
+ return this.Cache.ContainsKey($"{normalisedAssetName}.{this.GetKeyLocale.Invoke<string>()}")
+ ? locale
+ : null;
}
}
}
diff --git a/src/StardewModdingAPI/IContentEventHelper.cs b/src/StardewModdingAPI/IContentEventHelper.cs
index 98d074d9..be8290eb 100644
--- a/src/StardewModdingAPI/IContentEventHelper.cs
+++ b/src/StardewModdingAPI/IContentEventHelper.cs
@@ -8,8 +8,11 @@ namespace StardewModdingAPI
/*********
** Accessors
*********/
- /// <summary>The normalised asset path being read. The format may change between platforms; see <see cref="IsPath"/> to compare with a known path.</summary>
- string Path { get; }
+ /// <summary>The content's locale code, if the content is localised.</summary>
+ string Locale { get; }
+
+ /// <summary>The normalised asset name being read. The format may change between platforms; see <see cref="IsAssetName"/> to compare with a known path.</summary>
+ string AssetName { get; }
/// <summary>The content data being read.</summary>
object Data { get; }
@@ -18,10 +21,9 @@ namespace StardewModdingAPI
/*********
** Public methods
*********/
- /// <summary>Get whether the asset path being loaded matches a given path after normalisation.</summary>
- /// <param name="path">The expected asset path, relative to the game folder and without the .xnb extension (like 'Data\ObjectInformation').</param>
- /// <param name="matchLocalisedVersion">Whether to match a localised version of the asset file (like 'Data\ObjectInformation.ja-JP').</param>
- bool IsPath(string path, bool matchLocalisedVersion = true);
+ /// <summary>Get whether the asset name being loaded matches a given name after normalisation.</summary>
+ /// <param name="path">The expected asset path, relative to the game's content folder and without the .xnb extension or locale suffix (like 'Data\ObjectInformation').</param>
+ bool IsAssetName(string path);
/// <summary>Get the data as a given type.</summary>
/// <typeparam name="TData">The expected data type.</typeparam>