From 9c53a254d50718fee3b8043bb0b8bb840557e82f Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 25 Feb 2017 15:22:45 -0500 Subject: add prototype content event + helper to manipulate XNB data (#173) --- src/StardewModdingAPI/IContentEventHelper.cs | 53 ++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/StardewModdingAPI/IContentEventHelper.cs (limited to 'src/StardewModdingAPI/IContentEventHelper.cs') diff --git a/src/StardewModdingAPI/IContentEventHelper.cs b/src/StardewModdingAPI/IContentEventHelper.cs new file mode 100644 index 00000000..98d074d9 --- /dev/null +++ b/src/StardewModdingAPI/IContentEventHelper.cs @@ -0,0 +1,53 @@ +using System; + +namespace StardewModdingAPI +{ + /// Encapsulates access and changes to content being read from a data file. + public interface IContentEventHelper + { + /********* + ** Accessors + *********/ + /// The normalised asset path being read. The format may change between platforms; see to compare with a known path. + string Path { get; } + + /// The content data being read. + object Data { get; } + + + /********* + ** Public methods + *********/ + /// Get whether the asset path being loaded matches a given path after normalisation. + /// The expected asset path, relative to the game folder and without the .xnb extension (like 'Data\ObjectInformation'). + /// Whether to match a localised version of the asset file (like 'Data\ObjectInformation.ja-JP'). + bool IsPath(string path, bool matchLocalisedVersion = true); + + /// Get the data as a given type. + /// The expected data type. + /// The data can't be converted to . + TData GetData(); + + /// Add or replace an entry in the dictionary data. + /// The entry key type. + /// The entry value type. + /// The entry key. + /// The entry value. + /// The content being read isn't a dictionary. + void SetDictionaryEntry(TKey key, TValue value); + + /// Add or replace an entry in the dictionary data. + /// The entry key type. + /// The entry value type. + /// The entry key. + /// A callback which accepts the current value and returns the new value. + /// The content being read isn't a dictionary. + void SetDictionaryEntry(TKey key, Func value); + + /// 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. + void ReplaceWith(object value); + } +} -- cgit From 529e0dbb84548ac47d6b3ca9ac892b743171886e Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 25 Feb 2017 19:08:21 -0500 Subject: fix handling of localised XNB files (#173) --- .../Framework/ContentEventHelper.cs | 39 +++++++----------- src/StardewModdingAPI/Framework/SContentManager.cs | 48 ++++++++++++++-------- src/StardewModdingAPI/IContentEventHelper.cs | 14 ++++--- 3 files changed, 53 insertions(+), 48 deletions(-) (limited to 'src/StardewModdingAPI/IContentEventHelper.cs') 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 *********/ - /// The normalised asset path being read. The format may change between platforms; see to compare with a known path. - public string Path { get; } + /// 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 object Data { get; private set; } @@ -29,37 +31,24 @@ namespace StardewModdingAPI.Framework ** Public methods *********/ /// Construct an instance. - /// The file path being read. + /// 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 ContentEventHelper(string path, object data, Func getNormalisedPath) + public ContentEventHelper(string locale, string assetName, object data, Func getNormalisedPath) { - this.Path = path; + this.Locale = locale; + this.AssetName = assetName; this.Data = data; this.GetNormalisedPath = getNormalisedPath; } - /// Get whether the asset path being loaded matches a given path after normalisation. - /// The expected asset path, relative to the game folder and without the .xnb extension (like 'Data\ObjectInformation'). - /// Whether to match a localised version of the asset file (like 'Data\ObjectInformation.ja-JP'). - public bool IsPath(string path, bool matchLocalisedVersion = true) + /// 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); - - // 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); } /// Get the data as a given type. 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 Cache; /// Applies platform-specific asset key normalisation so it's consistent with the underlying cache. - private readonly Func NormaliseKeyForPlatform; + private readonly Func NormaliseAssetNameForPlatform; + + /// The private method which generates the locale portion of an asset name. + 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>(this, "loadedAssets") - .GetValue(); + // get underlying fields for interception + this.Cache = reflection.GetPrivateField>(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(path); + this.NormaliseAssetNameForPlatform = path => method.Invoke(path); } else - this.NormaliseKeyForPlatform = key => key.Replace('\\', '/'); // based on MonoGame's ContentManager.Load logic + this.NormaliseAssetNameForPlatform = key => key.Replace('\\', '/'); // based on MonoGame's ContentManager.Load logic } /// Load an asset that has been processed by the content pipeline. @@ -77,8 +79,8 @@ namespace StardewModdingAPI.Framework /// The asset path relative to the loader root directory, not including the .xnb extension. public override T Load(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(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 *********/ - /// Normalise an asset key so it's consistent with the underlying cache. - /// The asset key. - private string NormaliseKey(string key) + /// Normalise an asset name so it's consistent with the underlying cache. + /// The asset key. + 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); + } + + /// Get the locale for which the asset name was saved, if any. + /// The normalised asset name. + /// The cache to search. + private string GetCacheLocale(string normalisedAssetName, IDictionary cache) + { + string locale = this.GetKeyLocale.Invoke(); + return this.Cache.ContainsKey($"{normalisedAssetName}.{this.GetKeyLocale.Invoke()}") + ? 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 *********/ - /// The normalised asset path being read. The format may change between platforms; see to compare with a known path. - string Path { get; } + /// The content's locale code, if the content is localised. + string Locale { get; } + + /// The normalised asset name being read. The format may change between platforms; see to compare with a known path. + string AssetName { get; } /// The content data being read. object Data { get; } @@ -18,10 +21,9 @@ namespace StardewModdingAPI /********* ** Public methods *********/ - /// Get whether the asset path being loaded matches a given path after normalisation. - /// The expected asset path, relative to the game folder and without the .xnb extension (like 'Data\ObjectInformation'). - /// Whether to match a localised version of the asset file (like 'Data\ObjectInformation.ja-JP'). - bool IsPath(string path, bool matchLocalisedVersion = true); + /// 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'). + bool IsAssetName(string path); /// Get the data as a given type. /// The expected data type. -- cgit From 043508ed4264a3024b281665bfbf6e073c029fdf Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 3 Mar 2017 20:22:30 -0500 Subject: add texture patching to content events (#173) --- .../Framework/ContentEventHelper.cs | 51 ++++++++++++++++++++++ src/StardewModdingAPI/IContentEventHelper.cs | 12 +++++ src/StardewModdingAPI/PatchMode.cs | 12 +++++ src/StardewModdingAPI/StardewModdingAPI.csproj | 1 + 4 files changed, 76 insertions(+) create mode 100644 src/StardewModdingAPI/PatchMode.cs (limited to 'src/StardewModdingAPI/IContentEventHelper.cs') diff --git a/src/StardewModdingAPI/Framework/ContentEventHelper.cs b/src/StardewModdingAPI/Framework/ContentEventHelper.cs index a58efe32..ebd04692 100644 --- a/src/StardewModdingAPI/Framework/ContentEventHelper.cs +++ b/src/StardewModdingAPI/Framework/ContentEventHelper.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace StardewModdingAPI.Framework @@ -85,6 +86,56 @@ namespace StardewModdingAPI.Framework data[key] = value(data[key]); } + /// Overwrite part of the image. + /// The image to patch into the content. + /// The part of the to copy (or null to take the whole texture). This must be within the bounds of the texture. + /// The part of the content to patch (or null to patch the whole texture). The original content within this area will be erased. This must be within the bounds of the existing spritesheet. + /// Indicates how an image should be patched. + /// One of the arguments is null. + /// The is outside the bounds of the spritesheet. + /// The content being read isn't an image. + public void PatchImage(Texture2D source, Rectangle? sourceArea = null, Rectangle? targetArea = null, PatchMode patchMode = PatchMode.Replace) + { + // get texture + Texture2D target = this.GetData(); + + // get areas + sourceArea = sourceArea ?? new Rectangle(0, 0, source.Width, source.Height); + targetArea = targetArea ?? new Rectangle(0, 0, Math.Min(sourceArea.Value.Width, target.Width), Math.Min(sourceArea.Value.Height, target.Height)); + + // validate + if (source == null) + throw new ArgumentNullException(nameof(source), "Can't patch from a null source texture."); + if (sourceArea.Value.X < 0 || sourceArea.Value.Y < 0 || sourceArea.Value.Right > source.Width || sourceArea.Value.Bottom > source.Height) + throw new ArgumentOutOfRangeException(nameof(sourceArea), "The source area is outside the bounds of the source texture."); + if (targetArea.Value.X < 0 || targetArea.Value.Y < 0 || targetArea.Value.Right > target.Width || targetArea.Value.Bottom > target.Height) + throw new ArgumentOutOfRangeException(nameof(targetArea), "The target area is outside the bounds of the target texture."); + if (sourceArea.Value.Width != targetArea.Value.Width || sourceArea.Value.Height != targetArea.Value.Height) + throw new InvalidOperationException("The source and target areas must be the same size."); + + // get source data + int pixelCount = sourceArea.Value.Width * sourceArea.Value.Height; + Color[] sourceData = new Color[pixelCount]; + source.GetData(0, sourceArea, sourceData, 0, pixelCount); + + // merge data in overlay mode + if (patchMode == PatchMode.Overlay) + { + Color[] newData = new Color[targetArea.Value.Width * targetArea.Value.Height]; + target.GetData(0, targetArea, newData, 0, newData.Length); + for (int i = 0; i < sourceData.Length; i++) + { + Color pixel = sourceData[i]; + if (pixel.A != 0) // not transparent + newData[i] = pixel; + } + sourceData = newData; + } + + // patch target texture + target.SetData(0, targetArea, sourceData, 0, pixelCount); + } + /// 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. diff --git a/src/StardewModdingAPI/IContentEventHelper.cs b/src/StardewModdingAPI/IContentEventHelper.cs index be8290eb..7b8fd3bc 100644 --- a/src/StardewModdingAPI/IContentEventHelper.cs +++ b/src/StardewModdingAPI/IContentEventHelper.cs @@ -1,4 +1,6 @@ using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; namespace StardewModdingAPI { @@ -46,6 +48,16 @@ namespace StardewModdingAPI /// The content being read isn't a dictionary. void SetDictionaryEntry(TKey key, Func value); + /// Overwrite part of the image. + /// The image to patch into the content. + /// The part of the to copy (or null to take the whole texture). This must be within the bounds of the texture. + /// The part of the content to patch (or null to patch the whole texture). The original content within this area will be erased. This must be within the bounds of the existing spritesheet. + /// Indicates how an image should be patched. + /// One of the arguments is null. + /// The is outside the bounds of the spritesheet. + /// The content being read isn't an image. + void PatchImage(Texture2D source, Rectangle? sourceArea = null, Rectangle? targetArea = null, PatchMode patchMode = PatchMode.Replace); + /// 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. diff --git a/src/StardewModdingAPI/PatchMode.cs b/src/StardewModdingAPI/PatchMode.cs new file mode 100644 index 00000000..b4286a89 --- /dev/null +++ b/src/StardewModdingAPI/PatchMode.cs @@ -0,0 +1,12 @@ +namespace StardewModdingAPI +{ + /// Indicates how an image should be patched. + public enum PatchMode + { + /// Erase the original content within the area before drawing the new content. + Replace, + + /// Draw the new content over the original content, so the original content shows through any transparent pixels. + Overlay + } +} diff --git a/src/StardewModdingAPI/StardewModdingAPI.csproj b/src/StardewModdingAPI/StardewModdingAPI.csproj index 4d782f56..40f964b9 100644 --- a/src/StardewModdingAPI/StardewModdingAPI.csproj +++ b/src/StardewModdingAPI/StardewModdingAPI.csproj @@ -196,6 +196,7 @@ + -- cgit From b2e88bccf63545d950f4cbf47a0466321c614245 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 8 Mar 2017 15:25:30 -0500 Subject: add dictionary/image content helpers for more intuitive usage (#173) --- .../Framework/Content/ContentEventBaseHelper.cs | 98 +++++++++++ .../Framework/Content/ContentEventHelper.cs | 47 ++++++ .../Content/ContentEventHelperForDictionary.cs | 36 ++++ .../Content/ContentEventHelperForImage.cs | 70 ++++++++ .../Framework/ContentEventHelper.cs | 182 --------------------- src/StardewModdingAPI/Framework/SContentManager.cs | 1 + src/StardewModdingAPI/IContentEventHelper.cs | 38 ++--- .../IContentEventHelperForDictionary.cs | 44 +++++ .../IContentEventHelperForImage.cs | 45 +++++ src/StardewModdingAPI/StardewModdingAPI.csproj | 7 +- 10 files changed, 357 insertions(+), 211 deletions(-) create mode 100644 src/StardewModdingAPI/Framework/Content/ContentEventBaseHelper.cs create mode 100644 src/StardewModdingAPI/Framework/Content/ContentEventHelper.cs create mode 100644 src/StardewModdingAPI/Framework/Content/ContentEventHelperForDictionary.cs create mode 100644 src/StardewModdingAPI/Framework/Content/ContentEventHelperForImage.cs delete mode 100644 src/StardewModdingAPI/Framework/ContentEventHelper.cs create mode 100644 src/StardewModdingAPI/IContentEventHelperForDictionary.cs create mode 100644 src/StardewModdingAPI/IContentEventHelperForImage.cs (limited to 'src/StardewModdingAPI/IContentEventHelper.cs') diff --git a/src/StardewModdingAPI/Framework/Content/ContentEventBaseHelper.cs b/src/StardewModdingAPI/Framework/Content/ContentEventBaseHelper.cs new file mode 100644 index 00000000..736cdc70 --- /dev/null +++ b/src/StardewModdingAPI/Framework/Content/ContentEventBaseHelper.cs @@ -0,0 +1,98 @@ +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 + { + /********* + ** 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/ContentEventHelper.cs b/src/StardewModdingAPI/Framework/Content/ContentEventHelper.cs new file mode 100644 index 00000000..26292cab --- /dev/null +++ b/src/StardewModdingAPI/Framework/Content/ContentEventHelper.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +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 + { + /********* + ** 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 ContentEventHelper(string locale, string assetName, object data, Func getNormalisedPath) + : base(locale, assetName, data, getNormalisedPath) { } + + /// Get a helper to manipulate the data as a dictionary. + /// The expected dictionary key. + /// The expected dictionary balue. + /// The content being read isn't a dictionary. + public IContentEventHelperForDictionary AsDictionary() + { + return new ContentEventHelperForDictionary(this.Locale, this.AssetName, this.GetData>(), this.GetNormalisedPath); + } + + /// Get a helper to manipulate the data as an image. + /// The content being read isn't an image. + public IContentEventHelperForImage AsImage() + { + return new ContentEventHelperForImage(this.Locale, this.AssetName, this.GetData(), this.GetNormalisedPath); + } + + /// Get the data as a given type. + /// The expected data type. + /// The data can't be converted to . + public TData GetData() + { + if (!(this.Data is TData)) + throw new InvalidCastException($"The content data of type {this.Data.GetType().FullName} can't be converted to the requested {typeof(TData).FullName}."); + return (TData)this.Data; + } + } +} diff --git a/src/StardewModdingAPI/Framework/Content/ContentEventHelperForDictionary.cs b/src/StardewModdingAPI/Framework/Content/ContentEventHelperForDictionary.cs new file mode 100644 index 00000000..8fcaae3c --- /dev/null +++ b/src/StardewModdingAPI/Framework/Content/ContentEventHelperForDictionary.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; + +namespace StardewModdingAPI.Framework.Content +{ + /// Encapsulates access and changes to dictionary content being read from a data file. + internal class ContentEventHelperForDictionary : ContentEventBaseHelper>, IContentEventHelperForDictionary + { + /********* + ** 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 ContentEventHelperForDictionary(string locale, string assetName, IDictionary data, Func getNormalisedPath) + : base(locale, assetName, data, getNormalisedPath) { } + + /// Add or replace an entry in the dictionary data. + /// The entry key. + /// The entry value. + public void SetEntry(TKey key, TValue value) + { + this.Data[key] = value; + } + + /// Add or replace an entry in the dictionary data. + /// The entry key. + /// A callback which accepts the current value and returns the new value. + public void SetEntry(TKey key, Func value) + { + this.Data[key] = value(this.Data[key]); + } + } +} diff --git a/src/StardewModdingAPI/Framework/Content/ContentEventHelperForImage.cs b/src/StardewModdingAPI/Framework/Content/ContentEventHelperForImage.cs new file mode 100644 index 00000000..23760f0f --- /dev/null +++ b/src/StardewModdingAPI/Framework/Content/ContentEventHelperForImage.cs @@ -0,0 +1,70 @@ +using System; +using Microsoft.Xna.Framework; +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 + { + /********* + ** 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 ContentEventHelperForImage(string locale, string assetName, Texture2D data, Func getNormalisedPath) + : base(locale, assetName, data, getNormalisedPath) { } + + /// Overwrite part of the image. + /// The image to patch into the content. + /// The part of the to copy (or null to take the whole texture). This must be within the bounds of the texture. + /// The part of the content to patch (or null to patch the whole texture). The original content within this area will be erased. This must be within the bounds of the existing spritesheet. + /// Indicates how an image should be patched. + /// One of the arguments is null. + /// The is outside the bounds of the spritesheet. + public void PatchImage(Texture2D source, Rectangle? sourceArea = null, Rectangle? targetArea = null, PatchMode patchMode = PatchMode.Replace) + { + // get texture + Texture2D target = this.Data; + + // get areas + sourceArea = sourceArea ?? new Rectangle(0, 0, source.Width, source.Height); + targetArea = targetArea ?? new Rectangle(0, 0, Math.Min(sourceArea.Value.Width, target.Width), Math.Min(sourceArea.Value.Height, target.Height)); + + // validate + if (source == null) + throw new ArgumentNullException(nameof(source), "Can't patch from a null source texture."); + if (sourceArea.Value.X < 0 || sourceArea.Value.Y < 0 || sourceArea.Value.Right > source.Width || sourceArea.Value.Bottom > source.Height) + throw new ArgumentOutOfRangeException(nameof(sourceArea), "The source area is outside the bounds of the source texture."); + if (targetArea.Value.X < 0 || targetArea.Value.Y < 0 || targetArea.Value.Right > target.Width || targetArea.Value.Bottom > target.Height) + throw new ArgumentOutOfRangeException(nameof(targetArea), "The target area is outside the bounds of the target texture."); + if (sourceArea.Value.Width != targetArea.Value.Width || sourceArea.Value.Height != targetArea.Value.Height) + throw new InvalidOperationException("The source and target areas must be the same size."); + + // get source data + int pixelCount = sourceArea.Value.Width * sourceArea.Value.Height; + Color[] sourceData = new Color[pixelCount]; + source.GetData(0, sourceArea, sourceData, 0, pixelCount); + + // merge data in overlay mode + if (patchMode == PatchMode.Overlay) + { + Color[] newData = new Color[targetArea.Value.Width * targetArea.Value.Height]; + target.GetData(0, targetArea, newData, 0, newData.Length); + for (int i = 0; i < sourceData.Length; i++) + { + Color pixel = sourceData[i]; + if (pixel.A != 0) // not transparent + newData[i] = pixel; + } + sourceData = newData; + } + + // patch target texture + target.SetData(0, targetArea, sourceData, 0, pixelCount); + } + } +} diff --git a/src/StardewModdingAPI/Framework/ContentEventHelper.cs b/src/StardewModdingAPI/Framework/ContentEventHelper.cs deleted file mode 100644 index ebd04692..00000000 --- a/src/StardewModdingAPI/Framework/ContentEventHelper.cs +++ /dev/null @@ -1,182 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; - -namespace StardewModdingAPI.Framework -{ - /// Encapsulates access and changes to content being read from a data file. - internal class ContentEventHelper : EventArgs, IContentEventHelper - { - /********* - ** Properties - *********/ - /// Normalises an asset key to match the cache key. - private 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 object Data { get; private 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 ContentEventHelper(string locale, string assetName, object 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); - } - - /// Get the data as a given type. - /// The expected data type. - /// The data can't be converted to . - public TData GetData() - { - if (!(this.Data is TData)) - throw new InvalidCastException($"The content data of type {this.Data.GetType().FullName} can't be converted to the requested {typeof(TData).FullName}."); - return (TData)this.Data; - } - - /// Add or replace an entry in the dictionary data. - /// The entry key type. - /// The entry value type. - /// The entry key. - /// The entry value. - /// The content being read isn't a dictionary. - public void SetDictionaryEntry(TKey key, TValue value) - { - IDictionary data = this.GetData>(); - data[key] = value; - } - - /// Add or replace an entry in the dictionary data. - /// The entry key type. - /// The entry value type. - /// The entry key. - /// A callback which accepts the current value and returns the new value. - /// The content being read isn't a dictionary. - public void SetDictionaryEntry(TKey key, Func value) - { - IDictionary data = this.GetData>(); - data[key] = value(data[key]); - } - - /// Overwrite part of the image. - /// The image to patch into the content. - /// The part of the to copy (or null to take the whole texture). This must be within the bounds of the texture. - /// The part of the content to patch (or null to patch the whole texture). The original content within this area will be erased. This must be within the bounds of the existing spritesheet. - /// Indicates how an image should be patched. - /// One of the arguments is null. - /// The is outside the bounds of the spritesheet. - /// The content being read isn't an image. - public void PatchImage(Texture2D source, Rectangle? sourceArea = null, Rectangle? targetArea = null, PatchMode patchMode = PatchMode.Replace) - { - // get texture - Texture2D target = this.GetData(); - - // get areas - sourceArea = sourceArea ?? new Rectangle(0, 0, source.Width, source.Height); - targetArea = targetArea ?? new Rectangle(0, 0, Math.Min(sourceArea.Value.Width, target.Width), Math.Min(sourceArea.Value.Height, target.Height)); - - // validate - if (source == null) - throw new ArgumentNullException(nameof(source), "Can't patch from a null source texture."); - if (sourceArea.Value.X < 0 || sourceArea.Value.Y < 0 || sourceArea.Value.Right > source.Width || sourceArea.Value.Bottom > source.Height) - throw new ArgumentOutOfRangeException(nameof(sourceArea), "The source area is outside the bounds of the source texture."); - if (targetArea.Value.X < 0 || targetArea.Value.Y < 0 || targetArea.Value.Right > target.Width || targetArea.Value.Bottom > target.Height) - throw new ArgumentOutOfRangeException(nameof(targetArea), "The target area is outside the bounds of the target texture."); - if (sourceArea.Value.Width != targetArea.Value.Width || sourceArea.Value.Height != targetArea.Value.Height) - throw new InvalidOperationException("The source and target areas must be the same size."); - - // get source data - int pixelCount = sourceArea.Value.Width * sourceArea.Value.Height; - Color[] sourceData = new Color[pixelCount]; - source.GetData(0, sourceArea, sourceData, 0, pixelCount); - - // merge data in overlay mode - if (patchMode == PatchMode.Overlay) - { - Color[] newData = new Color[targetArea.Value.Width * targetArea.Value.Height]; - target.GetData(0, targetArea, newData, 0, newData.Length); - for (int i = 0; i < sourceData.Length; i++) - { - Color pixel = sourceData[i]; - if (pixel.A != 0) // not transparent - newData[i] = pixel; - } - sourceData = newData; - } - - // patch target texture - target.SetData(0, targetArea, sourceData, 0, pixelCount); - } - - /// 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(object 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; - } - - - /********* - ** Private methods - *********/ - /// Get a human-readable type name. - /// The type to name. - private 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/SContentManager.cs b/src/StardewModdingAPI/Framework/SContentManager.cs index 65c330db..97472d53 100644 --- a/src/StardewModdingAPI/Framework/SContentManager.cs +++ b/src/StardewModdingAPI/Framework/SContentManager.cs @@ -7,6 +7,7 @@ using System.Threading; using Microsoft.Xna.Framework; using StardewModdingAPI.AssemblyRewriters; using StardewModdingAPI.Events; +using StardewModdingAPI.Framework.Content; using StardewModdingAPI.Framework.Reflection; using StardewValley; diff --git a/src/StardewModdingAPI/IContentEventHelper.cs b/src/StardewModdingAPI/IContentEventHelper.cs index 7b8fd3bc..341778b4 100644 --- a/src/StardewModdingAPI/IContentEventHelper.cs +++ b/src/StardewModdingAPI/IContentEventHelper.cs @@ -1,6 +1,4 @@ using System; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; namespace StardewModdingAPI { @@ -27,37 +25,21 @@ namespace StardewModdingAPI /// The expected asset path, relative to the game's content folder and without the .xnb extension or locale suffix (like 'Data\ObjectInformation'). bool IsAssetName(string path); + /// Get a helper to manipulate the data as a dictionary. + /// The expected dictionary key. + /// The expected dictionary balue. + /// The content being read isn't a dictionary. + IContentEventHelperForDictionary AsDictionary(); + + /// Get a helper to manipulate the data as an image. + /// The content being read isn't an image. + IContentEventHelperForImage AsImage(); + /// Get the data as a given type. /// The expected data type. /// The data can't be converted to . TData GetData(); - /// Add or replace an entry in the dictionary data. - /// The entry key type. - /// The entry value type. - /// The entry key. - /// The entry value. - /// The content being read isn't a dictionary. - void SetDictionaryEntry(TKey key, TValue value); - - /// Add or replace an entry in the dictionary data. - /// The entry key type. - /// The entry value type. - /// The entry key. - /// A callback which accepts the current value and returns the new value. - /// The content being read isn't a dictionary. - void SetDictionaryEntry(TKey key, Func value); - - /// Overwrite part of the image. - /// The image to patch into the content. - /// The part of the to copy (or null to take the whole texture). This must be within the bounds of the texture. - /// The part of the content to patch (or null to patch the whole texture). The original content within this area will be erased. This must be within the bounds of the existing spritesheet. - /// Indicates how an image should be patched. - /// One of the arguments is null. - /// The is outside the bounds of the spritesheet. - /// The content being read isn't an image. - void PatchImage(Texture2D source, Rectangle? sourceArea = null, Rectangle? targetArea = null, PatchMode patchMode = PatchMode.Replace); - /// 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. diff --git a/src/StardewModdingAPI/IContentEventHelperForDictionary.cs b/src/StardewModdingAPI/IContentEventHelperForDictionary.cs new file mode 100644 index 00000000..1f259920 --- /dev/null +++ b/src/StardewModdingAPI/IContentEventHelperForDictionary.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; + +namespace StardewModdingAPI +{ + /// Encapsulates access and changes to dictionary content being read from a data file. + public interface IContentEventHelperForDictionary + { + /********* + ** Accessors + *********/ + /// The content's locale code, if the content is localised. + string Locale { get; } + + /// The normalised asset name being read. The format may change between platforms; see to compare with a known path. + string AssetName { get; } + + /// The content data being read. + IDictionary Data { get; } + + + /********* + ** Public methods + *********/ + /// 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'). + bool IsAssetName(string path); + + /// Add or replace an entry in the dictionary data. + /// The entry key. + /// The entry value. + void SetEntry(TKey key, TValue value); + + /// Add or replace an entry in the dictionary data. + /// The entry key. + /// A callback which accepts the current value and returns the new value. + void SetEntry(TKey key, Func value); + + /// 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. + void ReplaceWith(IDictionary value); + } +} diff --git a/src/StardewModdingAPI/IContentEventHelperForImage.cs b/src/StardewModdingAPI/IContentEventHelperForImage.cs new file mode 100644 index 00000000..14bc23a4 --- /dev/null +++ b/src/StardewModdingAPI/IContentEventHelperForImage.cs @@ -0,0 +1,45 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace StardewModdingAPI +{ + /// Encapsulates access and changes to dictionary content being read from a data file. + public interface IContentEventHelperForImage + { + /********* + ** Accessors + *********/ + /// The content's locale code, if the content is localised. + string Locale { get; } + + /// The normalised asset name being read. The format may change between platforms; see to compare with a known path. + string AssetName { get; } + + /// The content data being read. + Texture2D Data { get; } + + + /********* + ** Public methods + *********/ + /// 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'). + bool IsAssetName(string path); + + /// Overwrite part of the image. + /// The image to patch into the content. + /// The part of the to copy (or null to take the whole texture). This must be within the bounds of the texture. + /// The part of the content to patch (or null to patch the whole texture). The original content within this area will be erased. This must be within the bounds of the existing spritesheet. + /// Indicates how an image should be patched. + /// One of the arguments is null. + /// The is outside the bounds of the spritesheet. + /// The content being read isn't an image. + void PatchImage(Texture2D source, Rectangle? sourceArea = null, Rectangle? targetArea = null, PatchMode patchMode = PatchMode.Replace); + + /// 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. + void ReplaceWith(Texture2D value); + } +} diff --git a/src/StardewModdingAPI/StardewModdingAPI.csproj b/src/StardewModdingAPI/StardewModdingAPI.csproj index 727da30f..478d1af0 100644 --- a/src/StardewModdingAPI/StardewModdingAPI.csproj +++ b/src/StardewModdingAPI/StardewModdingAPI.csproj @@ -150,7 +150,10 @@ - + + + + @@ -163,6 +166,8 @@ + + -- cgit From ff39e9b1716104e02c92dfd56bb919887873bd3d Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 10 Mar 2017 11:05:17 -0500 Subject: move generic content properties & methods into separate interface (#173) --- .../Framework/Content/ContentEventBaseHelper.cs | 2 +- src/StardewModdingAPI/IContentEventData.cs | 35 ++++++++++++++++++++++ src/StardewModdingAPI/IContentEventHelper.cs | 25 +--------------- .../IContentEventHelperForDictionary.cs | 24 +-------------- .../IContentEventHelperForImage.cs | 24 +-------------- src/StardewModdingAPI/StardewModdingAPI.csproj | 1 + 6 files changed, 40 insertions(+), 71 deletions(-) create mode 100644 src/StardewModdingAPI/IContentEventData.cs (limited to 'src/StardewModdingAPI/IContentEventHelper.cs') diff --git a/src/StardewModdingAPI/Framework/Content/ContentEventBaseHelper.cs b/src/StardewModdingAPI/Framework/Content/ContentEventBaseHelper.cs index 736cdc70..a89fe337 100644 --- a/src/StardewModdingAPI/Framework/Content/ContentEventBaseHelper.cs +++ b/src/StardewModdingAPI/Framework/Content/ContentEventBaseHelper.cs @@ -6,7 +6,7 @@ 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 + internal class ContentEventBaseHelper : EventArgs, IContentEventData { /********* ** Properties diff --git a/src/StardewModdingAPI/IContentEventData.cs b/src/StardewModdingAPI/IContentEventData.cs new file mode 100644 index 00000000..a21861d2 --- /dev/null +++ b/src/StardewModdingAPI/IContentEventData.cs @@ -0,0 +1,35 @@ +using System; + +namespace StardewModdingAPI +{ + /// Generic metadata and methods for a content asset being loaded. + /// The expected data type. + public interface IContentEventData + { + /********* + ** Accessors + *********/ + /// The content's locale code, if the content is localised. + string Locale { get; } + + /// The normalised asset name being read. The format may change between platforms; see to compare with a known path. + string AssetName { get; } + + /// The content data being read. + TValue Data { get; } + + + /********* + ** Public methods + *********/ + /// 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'). + bool IsAssetName(string path); + + /// 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. + void ReplaceWith(TValue value); + } +} diff --git a/src/StardewModdingAPI/IContentEventHelper.cs b/src/StardewModdingAPI/IContentEventHelper.cs index 341778b4..421a1e06 100644 --- a/src/StardewModdingAPI/IContentEventHelper.cs +++ b/src/StardewModdingAPI/IContentEventHelper.cs @@ -3,28 +3,11 @@ namespace StardewModdingAPI { /// Encapsulates access and changes to content being read from a data file. - public interface IContentEventHelper + public interface IContentEventHelper : IContentEventData { - /********* - ** Accessors - *********/ - /// The content's locale code, if the content is localised. - string Locale { get; } - - /// The normalised asset name being read. The format may change between platforms; see to compare with a known path. - string AssetName { get; } - - /// The content data being read. - object Data { get; } - - /********* ** Public methods *********/ - /// 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'). - bool IsAssetName(string path); - /// Get a helper to manipulate the data as a dictionary. /// The expected dictionary key. /// The expected dictionary balue. @@ -39,11 +22,5 @@ namespace StardewModdingAPI /// The expected data type. /// The data can't be converted to . TData GetData(); - - /// 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. - void ReplaceWith(object value); } } diff --git a/src/StardewModdingAPI/IContentEventHelperForDictionary.cs b/src/StardewModdingAPI/IContentEventHelperForDictionary.cs index 34e69d42..2f9d5a65 100644 --- a/src/StardewModdingAPI/IContentEventHelperForDictionary.cs +++ b/src/StardewModdingAPI/IContentEventHelperForDictionary.cs @@ -4,28 +4,11 @@ using System.Collections.Generic; namespace StardewModdingAPI { /// Encapsulates access and changes to dictionary content being read from a data file. - public interface IContentEventHelperForDictionary + public interface IContentEventHelperForDictionary : IContentEventData> { - /********* - ** Accessors - *********/ - /// The content's locale code, if the content is localised. - string Locale { get; } - - /// The normalised asset name being read. The format may change between platforms; see to compare with a known path. - string AssetName { get; } - - /// The content data being read. - IDictionary Data { get; } - - /********* ** Public methods *********/ - /// 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'). - bool IsAssetName(string path); - /// Add or replace an entry in the dictionary. /// The entry key. /// The entry value. @@ -39,10 +22,5 @@ namespace StardewModdingAPI /// Dynamically replace values in the dictionary. /// A lambda which takes the current key and value for an entry, and returns the new value. void Set(Func replacer); - - /// 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. - void ReplaceWith(IDictionary value); } } diff --git a/src/StardewModdingAPI/IContentEventHelperForImage.cs b/src/StardewModdingAPI/IContentEventHelperForImage.cs index 14bc23a4..1158c868 100644 --- a/src/StardewModdingAPI/IContentEventHelperForImage.cs +++ b/src/StardewModdingAPI/IContentEventHelperForImage.cs @@ -5,28 +5,11 @@ using Microsoft.Xna.Framework.Graphics; namespace StardewModdingAPI { /// Encapsulates access and changes to dictionary content being read from a data file. - public interface IContentEventHelperForImage + public interface IContentEventHelperForImage : IContentEventData { - /********* - ** Accessors - *********/ - /// The content's locale code, if the content is localised. - string Locale { get; } - - /// The normalised asset name being read. The format may change between platforms; see to compare with a known path. - string AssetName { get; } - - /// The content data being read. - Texture2D Data { get; } - - /********* ** Public methods *********/ - /// 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'). - bool IsAssetName(string path); - /// Overwrite part of the image. /// The image to patch into the content. /// The part of the to copy (or null to take the whole texture). This must be within the bounds of the texture. @@ -36,10 +19,5 @@ namespace StardewModdingAPI /// The is outside the bounds of the spritesheet. /// The content being read isn't an image. void PatchImage(Texture2D source, Rectangle? sourceArea = null, Rectangle? targetArea = null, PatchMode patchMode = PatchMode.Replace); - - /// 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. - void ReplaceWith(Texture2D value); } } diff --git a/src/StardewModdingAPI/StardewModdingAPI.csproj b/src/StardewModdingAPI/StardewModdingAPI.csproj index 478d1af0..445f6f37 100644 --- a/src/StardewModdingAPI/StardewModdingAPI.csproj +++ b/src/StardewModdingAPI/StardewModdingAPI.csproj @@ -168,6 +168,7 @@ + -- cgit