From 614cdc6fddc61c2b8f27d6d15c998a4cbeaa90b7 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 25 Feb 2017 18:26:43 -0500 Subject: improve asset key normalisation (#173) --- src/StardewModdingAPI/Framework/SContentManager.cs | 41 ++++++++++++++-------- 1 file changed, 26 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/StardewModdingAPI/Framework/SContentManager.cs b/src/StardewModdingAPI/Framework/SContentManager.cs index 2781bec4..45f42bf6 100644 --- a/src/StardewModdingAPI/Framework/SContentManager.cs +++ b/src/StardewModdingAPI/Framework/SContentManager.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.IO; +using System.Linq; using System.Threading; using Microsoft.Xna.Framework; using StardewModdingAPI.AssemblyRewriters; @@ -16,14 +18,20 @@ namespace StardewModdingAPI.Framework /********* ** Accessors *********/ + /// The possible directory separator characters in an asset key. + private static readonly char[] PossiblePathSeparators = new[] { '/', '\\', Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }.Distinct().ToArray(); + + /// The preferred directory separator chaeacter in an asset key. + private static readonly string PreferredPathSeparator = Path.DirectorySeparatorChar.ToString(); + /// Encapsulates monitoring and logging. private readonly IMonitor Monitor; /// The underlying content manager's asset cache. private readonly IDictionary Cache; - /// Normalises an asset key to match the cache key. - private readonly Func NormaliseAssetKey; + /// Applies platform-specific asset key normalisation so it's consistent with the underlying cache. + private readonly Func NormaliseKeyForPlatform; /********* @@ -58,10 +66,10 @@ namespace StardewModdingAPI.Framework if (Constants.TargetPlatform == Platform.Windows) { IPrivateMethod method = reflection.GetPrivateMethod(typeof(TitleContainer), "GetCleanPath"); - this.NormaliseAssetKey = path => method.Invoke(path); + this.NormaliseKeyForPlatform = path => method.Invoke(path); } else - this.NormaliseAssetKey = this.NormaliseKeyForMono; + this.NormaliseKeyForPlatform = key => key.Replace('\\', '/'); // based on MonoGame's ContentManager.Load logic } /// Load an asset that has been processed by the content pipeline. @@ -69,20 +77,18 @@ namespace StardewModdingAPI.Framework /// The asset path relative to the loader root directory, not including the .xnb extension. public override T Load(string assetName) { - // pass through if no event handlers - if (!ContentEvents.HasAssetLoadingListeners()) - return base.Load(assetName); + // normalise key so can override the cache value later + assetName = this.NormaliseKey(assetName); - // skip if already loaded - string key = this.NormaliseAssetKey(assetName); - if (this.Cache.ContainsKey(key)) + // skip if no event handlers or already loaded + if (!ContentEvents.HasAssetLoadingListeners() || this.Cache.ContainsKey(assetName)) return base.Load(assetName); // intercept load T data = base.Load(assetName); - IContentEventHelper helper = new ContentEventHelper(key, data, this.NormaliseAssetKey); + IContentEventHelper helper = new ContentEventHelper(assetName, data, this.NormaliseKeyForPlatform); ContentEvents.InvokeAssetLoading(this.Monitor, helper); - this.Cache[key] = helper.Data; + this.Cache[assetName] = helper.Data; return (T)helper.Data; } @@ -90,11 +96,16 @@ namespace StardewModdingAPI.Framework /********* ** Private methods *********/ - /// Normalise an asset key for Mono. + /// Normalise an asset key so it's consistent with the underlying cache. /// The asset key. - private string NormaliseKeyForMono(string key) + private string NormaliseKey(string key) { - return key.Replace('\\', '/'); // based on MonoGame's ContentManager.Load logic + // ensure key format is consistent + string[] parts = key.Split(SContentManager.PossiblePathSeparators, StringSplitOptions.RemoveEmptyEntries); + key = string.Join(SContentManager.PreferredPathSeparator, parts); + + // apply platform normalisation logic + return this.NormaliseKeyForPlatform(key); } } } -- cgit