From e3522edddd0636116bd4772b4e4dbfce9c7c0f8d Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 10 Mar 2017 12:00:11 -0500 Subject: extend base content helper to support null content (#173) --- .../Framework/Content/ContentEventBaseHelper.cs | 98 ------------------ .../Framework/Content/ContentEventData.cs | 111 +++++++++++++++++++++ .../Framework/Content/ContentEventHelper.cs | 2 +- .../Content/ContentEventHelperForDictionary.cs | 2 +- .../Content/ContentEventHelperForImage.cs | 2 +- 5 files changed, 114 insertions(+), 101 deletions(-) delete mode 100644 src/StardewModdingAPI/Framework/Content/ContentEventBaseHelper.cs create mode 100644 src/StardewModdingAPI/Framework/Content/ContentEventData.cs (limited to 'src/StardewModdingAPI/Framework/Content') diff --git a/src/StardewModdingAPI/Framework/Content/ContentEventBaseHelper.cs b/src/StardewModdingAPI/Framework/Content/ContentEventBaseHelper.cs deleted file mode 100644 index a89fe337..00000000 --- a/src/StardewModdingAPI/Framework/Content/ContentEventBaseHelper.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.Xna.Framework.Graphics; - -namespace StardewModdingAPI.Framework.Content -{ - /// Base implementation for a content helper which encapsulates access and changes to content being read from a data file. - /// The interface value type. - internal class ContentEventBaseHelper : EventArgs, IContentEventData - { - /********* - ** Properties - *********/ - /// Normalises an asset key to match the cache key. - protected readonly Func GetNormalisedPath; - - - /********* - ** Accessors - *********/ - /// The content's locale code, if the content is localised. - public string Locale { get; } - - /// The normalised asset name being read. The format may change between platforms; see to compare with a known path. - public string AssetName { get; } - - /// The content data being read. - public TValue Data { get; protected set; } - - - /********* - ** Public methods - *********/ - /// Construct an instance. - /// The content's locale code, if the content is localised. - /// The normalised asset name being read. - /// The content data being read. - /// Normalises an asset key to match the cache key. - public ContentEventBaseHelper(string locale, string assetName, TValue data, Func getNormalisedPath) - { - this.Locale = locale; - this.AssetName = assetName; - this.Data = data; - this.GetNormalisedPath = getNormalisedPath; - } - - /// Get whether the asset name being loaded matches a given name after normalisation. - /// The expected asset path, relative to the game's content folder and without the .xnb extension or locale suffix (like 'Data\ObjectInformation'). - public bool IsAssetName(string path) - { - path = this.GetNormalisedPath(path); - return this.AssetName.Equals(path, StringComparison.InvariantCultureIgnoreCase); - } - - /// Replace the entire content value with the given value. This is generally not recommended, since it may break compatibility with other mods or different versions of the game. - /// The new content value. - /// The is null. - /// The 's type is not compatible with the loaded asset's type. - public void ReplaceWith(TValue value) - { - if (value == null) - throw new ArgumentNullException(nameof(value), "Can't set a loaded asset to a null value."); - if (!this.Data.GetType().IsInstanceOfType(value)) - throw new InvalidCastException($"Can't replace loaded asset of type {this.GetFriendlyTypeName(this.Data.GetType())} with value of type {this.GetFriendlyTypeName(value.GetType())}. The new type must be compatible to prevent game errors."); - - this.Data = value; - } - - - /********* - ** Protected methods - *********/ - /// Get a human-readable type name. - /// The type to name. - protected string GetFriendlyTypeName(Type type) - { - // dictionary - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>)) - { - Type[] genericArgs = type.GetGenericArguments(); - return $"Dictionary<{this.GetFriendlyTypeName(genericArgs[0])}, {this.GetFriendlyTypeName(genericArgs[1])}>"; - } - - // texture - if (type == typeof(Texture2D)) - return type.Name; - - // native type - if (type == typeof(int)) - return "int"; - if (type == typeof(string)) - return "string"; - - // default - return type.FullName; - } - } -} diff --git a/src/StardewModdingAPI/Framework/Content/ContentEventData.cs b/src/StardewModdingAPI/Framework/Content/ContentEventData.cs new file mode 100644 index 00000000..1a1779d4 --- /dev/null +++ b/src/StardewModdingAPI/Framework/Content/ContentEventData.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using Microsoft.Xna.Framework.Graphics; + +namespace StardewModdingAPI.Framework.Content +{ + /// Base implementation for a content helper which encapsulates access and changes to content being read from a data file. + /// The interface value type. + internal class ContentEventData : EventArgs, IContentEventData + { + /********* + ** Properties + *********/ + /// Normalises an asset key to match the cache key. + protected readonly Func GetNormalisedPath; + + + /********* + ** Accessors + *********/ + /// The content's locale code, if the content is localised. + public string Locale { get; } + + /// The normalised asset name being read. The format may change between platforms; see to compare with a known path. + public string AssetName { get; } + + /// The content data being read. + public TValue Data { get; protected set; } + + /// The content data type. + public Type DataType { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The content's locale code, if the content is localised. + /// The normalised asset name being read. + /// The content data being read. + /// Normalises an asset key to match the cache key. + public ContentEventData(string locale, string assetName, TValue data, Func getNormalisedPath) + : this(locale, assetName, data, data.GetType(), getNormalisedPath) { } + + /// Construct an instance. + /// The content's locale code, if the content is localised. + /// The normalised asset name being read. + /// The content data being read. + /// The content data type being read. + /// Normalises an asset key to match the cache key. + public ContentEventData(string locale, string assetName, TValue data, Type dataType, Func getNormalisedPath) + { + this.Locale = locale; + this.AssetName = assetName; + this.Data = data; + this.DataType = dataType; + this.GetNormalisedPath = getNormalisedPath; + } + + /// Get whether the asset name being loaded matches a given name after normalisation. + /// The expected asset path, relative to the game's content folder and without the .xnb extension or locale suffix (like 'Data\ObjectInformation'). + public bool IsAssetName(string path) + { + path = this.GetNormalisedPath(path); + return this.AssetName.Equals(path, StringComparison.InvariantCultureIgnoreCase); + } + + /// Replace the entire content value with the given value. This is generally not recommended, since it may break compatibility with other mods or different versions of the game. + /// The new content value. + /// The is null. + /// The 's type is not compatible with the loaded asset's type. + public void ReplaceWith(TValue value) + { + if (value == null) + throw new ArgumentNullException(nameof(value), "Can't set a loaded asset to a null value."); + if (!this.DataType.IsInstanceOfType(value)) + throw new InvalidCastException($"Can't replace loaded asset of type {this.GetFriendlyTypeName(this.DataType)} with value of type {this.GetFriendlyTypeName(value.GetType())}. The new type must be compatible to prevent game errors."); + + this.Data = value; + } + + + /********* + ** Protected methods + *********/ + /// Get a human-readable type name. + /// The type to name. + protected string GetFriendlyTypeName(Type type) + { + // dictionary + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>)) + { + Type[] genericArgs = type.GetGenericArguments(); + return $"Dictionary<{this.GetFriendlyTypeName(genericArgs[0])}, {this.GetFriendlyTypeName(genericArgs[1])}>"; + } + + // texture + if (type == typeof(Texture2D)) + return type.Name; + + // native type + if (type == typeof(int)) + return "int"; + if (type == typeof(string)) + return "string"; + + // default + return type.FullName; + } + } +} diff --git a/src/StardewModdingAPI/Framework/Content/ContentEventHelper.cs b/src/StardewModdingAPI/Framework/Content/ContentEventHelper.cs index 26292cab..9bf1ea17 100644 --- a/src/StardewModdingAPI/Framework/Content/ContentEventHelper.cs +++ b/src/StardewModdingAPI/Framework/Content/ContentEventHelper.cs @@ -5,7 +5,7 @@ using Microsoft.Xna.Framework.Graphics; namespace StardewModdingAPI.Framework.Content { /// Encapsulates access and changes to content being read from a data file. - internal class ContentEventHelper : ContentEventBaseHelper, IContentEventHelper + internal class ContentEventHelper : ContentEventData, IContentEventHelper { /********* ** Public methods diff --git a/src/StardewModdingAPI/Framework/Content/ContentEventHelperForDictionary.cs b/src/StardewModdingAPI/Framework/Content/ContentEventHelperForDictionary.cs index 8a8a4845..26f059e4 100644 --- a/src/StardewModdingAPI/Framework/Content/ContentEventHelperForDictionary.cs +++ b/src/StardewModdingAPI/Framework/Content/ContentEventHelperForDictionary.cs @@ -5,7 +5,7 @@ using System.Linq; namespace StardewModdingAPI.Framework.Content { /// Encapsulates access and changes to dictionary content being read from a data file. - internal class ContentEventHelperForDictionary : ContentEventBaseHelper>, IContentEventHelperForDictionary + internal class ContentEventHelperForDictionary : ContentEventData>, IContentEventHelperForDictionary { /********* ** Public methods diff --git a/src/StardewModdingAPI/Framework/Content/ContentEventHelperForImage.cs b/src/StardewModdingAPI/Framework/Content/ContentEventHelperForImage.cs index 23760f0f..da30590b 100644 --- a/src/StardewModdingAPI/Framework/Content/ContentEventHelperForImage.cs +++ b/src/StardewModdingAPI/Framework/Content/ContentEventHelperForImage.cs @@ -5,7 +5,7 @@ using Microsoft.Xna.Framework.Graphics; namespace StardewModdingAPI.Framework.Content { /// Encapsulates access and changes to dictionary content being read from a data file. - internal class ContentEventHelperForImage : ContentEventBaseHelper, IContentEventHelperForImage + internal class ContentEventHelperForImage : ContentEventData, IContentEventHelperForImage { /********* ** Public methods -- cgit