From 271843d8614b916aa69273b778971cff0a02ce0d Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 9 Jun 2017 22:10:59 -0400 Subject: [PATCH] tweak asset interception code to simplify future work (#255) --- .../Framework/SContentManager.cs | 60 +++++++------------ 1 file changed, 22 insertions(+), 38 deletions(-) diff --git a/src/StardewModdingAPI/Framework/SContentManager.cs b/src/StardewModdingAPI/Framework/SContentManager.cs index 38457862..d269cafa 100644 --- a/src/StardewModdingAPI/Framework/SContentManager.cs +++ b/src/StardewModdingAPI/Framework/SContentManager.cs @@ -111,28 +111,16 @@ namespace StardewModdingAPI.Framework /// The asset path relative to the loader root directory, not including the .xnb extension. public override T Load(string assetName) { - // get normalised metadata assetName = this.NormaliseAssetName(assetName); - string cacheLocale = this.GetCacheLocale(assetName); // skip if already loaded if (this.IsNormalisedKeyLoaded(assetName)) return base.Load(assetName); - // let mods intercept content - IAssetInfo info = new AssetInfo(cacheLocale, assetName, typeof(T), this.NormaliseAssetName); - Lazy data = new Lazy(() => new AssetDataForObject(info.Locale, info.AssetName, base.Load(assetName), this.NormaliseAssetName)); - if (this.TryOverrideAssetLoad(info, data, out T result)) - { - if (result == null) - throw new InvalidCastException($"Can't override asset '{assetName}' with a null value."); - - this.Cache[assetName] = result; - return result; - } - - // fallback to default behavior - return base.Load(assetName); + // load asset + T asset = this.GetAssetWithInterceptors(this.GetLocale(), assetName, () => base.Load(assetName)); + this.Cache[assetName] = asset; + return asset; } /// Inject an asset into the cache. @@ -162,27 +150,21 @@ namespace StardewModdingAPI.Framework || this.Cache.ContainsKey($"{normalisedAssetName}.{this.GetKeyLocale.Invoke()}"); // translated asset } - /// Get the locale for which the asset name was saved, if any. - /// The normalised asset name. - private string GetCacheLocale(string normalisedAssetName) - { - string locale = this.GetKeyLocale.Invoke(); - return this.Cache.ContainsKey($"{normalisedAssetName}.{locale}") - ? locale - : null; - } - - /// Try to override an asset being loaded. + /// Read an asset with support for asset interceptors. /// The asset type. - /// The asset metadata. - /// The loaded asset data. - /// The asset to use instead. - /// Returns whether the asset should be overridden by . - private bool TryOverrideAssetLoad(IAssetInfo info, Lazy data, out T result) + /// The current content locale. + /// The normalised asset path relative to the loader root directory, not including the .xnb extension. + /// Get the asset from the underlying content manager. + private T GetAssetWithInterceptors(string locale, string normalisedKey, Func getData) { - bool edited = false; + // get metadata + IAssetInfo info = new AssetInfo(locale, normalisedKey, typeof(T), this.NormaliseAssetName); - // apply editors + // load asset + T asset = getData(); + + // edit asset + IAssetData data = new AssetDataForObject(info.Locale, info.AssetName, asset, this.NormaliseAssetName); foreach (var modEditors in this.Editors) { IModMetadata mod = modEditors.Key; @@ -192,14 +174,16 @@ namespace StardewModdingAPI.Framework continue; this.Monitor.Log($"{mod.DisplayName} intercepted {info.AssetName}.", LogLevel.Trace); - editor.Edit(data.Value); - edited = true; + editor.Edit(data); + if (data.Data == null) + throw new InvalidOperationException($"{mod.DisplayName} incorrectly set asset '{normalisedKey}' to a null value."); + if (!(data.Data is T)) + throw new InvalidOperationException($"{mod.DisplayName} incorrectly set asset '{normalisedKey}' to incompatible type '{data.Data.GetType()}', expected '{typeof(T)}'."); } } // return result - result = edited ? (T)data.Value.Data : default(T); - return edited; + return (T)data.Data; } } }