From 51b7b9fe06d91d59461f9b9d6d3c1b1c736dc34d Mon Sep 17 00:00:00 2001 From: Ameisen <14104310+ameisen@users.noreply.github.com> Date: Wed, 9 Feb 2022 18:00:15 -0600 Subject: Cleanup and performance/allocation improvement for AssetDataForImage.PatchImage --- src/SMAPI/Framework/Content/AssetDataForImage.cs | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src/SMAPI/Framework/Content') diff --git a/src/SMAPI/Framework/Content/AssetDataForImage.cs b/src/SMAPI/Framework/Content/AssetDataForImage.cs index 529fb93a..c75514bc 100644 --- a/src/SMAPI/Framework/Content/AssetDataForImage.cs +++ b/src/SMAPI/Framework/Content/AssetDataForImage.cs @@ -41,39 +41,40 @@ namespace StardewModdingAPI.Framework.Content targetArea ??= new Rectangle(0, 0, Math.Min(sourceArea.Value.Width, target.Width), Math.Min(sourceArea.Value.Height, target.Height)); // validate - if (sourceArea.Value.X < 0 || sourceArea.Value.Y < 0 || sourceArea.Value.Right > source.Width || sourceArea.Value.Bottom > source.Height) + if (!source.Bounds.Contains(sourceArea.Value)) 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) + if (!target.Bounds.Contains(targetArea.Value)) 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) + if (sourceArea.Value.Size != targetArea.Value.Size) 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]; + Color[] sourceData = GC.AllocateUninitializedArray(pixelCount); source.GetData(0, sourceArea, sourceData, 0, pixelCount); // merge data in overlay mode if (patchMode == PatchMode.Overlay) { // get target data - Color[] targetData = new Color[pixelCount]; + Color[] targetData = GC.AllocateUninitializedArray(pixelCount); target.GetData(0, targetArea, targetData, 0, pixelCount); // merge pixels - 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 above = sourceData[i]; Color below = targetData[i]; // shortcut transparency - if (above.A < AssetDataForImage.MinOpacity) + if (above.A < MinOpacity) + { + sourceData[i] = below; continue; - if (below.A < AssetDataForImage.MinOpacity) + } + if (below.A < MinOpacity) { - newData[i] = above; + sourceData[i] = above; continue; } @@ -84,14 +85,13 @@ namespace StardewModdingAPI.Framework.Content // Note: don't use named arguments here since they're different between // Linux/macOS and Windows. float alphaBelow = 1 - (above.A / 255f); - newData[i] = new Color( + sourceData[i] = new Color( (int)(above.R + (below.R * alphaBelow)), // r (int)(above.G + (below.G * alphaBelow)), // g (int)(above.B + (below.B * alphaBelow)), // b Math.Max(above.A, below.A) // a ); } - sourceData = newData; } // patch target texture @@ -105,7 +105,7 @@ namespace StardewModdingAPI.Framework.Content return false; Texture2D original = this.Data; - Texture2D texture = new Texture2D(Game1.graphics.GraphicsDevice, Math.Max(original.Width, minWidth), Math.Max(original.Height, minHeight)); + Texture2D texture = new(Game1.graphics.GraphicsDevice, Math.Max(original.Width, minWidth), Math.Max(original.Height, minHeight)); this.ReplaceWith(texture); this.PatchImage(original); return true; -- cgit From a2190df08cc3f1b4a8dcb394056d65921d10702e Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 18 Feb 2022 15:39:49 -0500 Subject: add AssetName to encapsulate asset name handling (#766) --- src/SMAPI/Framework/Content/AssetData.cs | 4 +- .../Framework/Content/AssetDataForDictionary.cs | 4 +- src/SMAPI/Framework/Content/AssetDataForImage.cs | 4 +- src/SMAPI/Framework/Content/AssetDataForMap.cs | 4 +- src/SMAPI/Framework/Content/AssetDataForObject.cs | 12 +- src/SMAPI/Framework/Content/AssetInfo.cs | 16 +- .../Framework/Content/AssetInterceptorChange.cs | 4 +- src/SMAPI/Framework/Content/AssetName.cs | 173 +++++++++++++++++++++ 8 files changed, 199 insertions(+), 22 deletions(-) create mode 100644 src/SMAPI/Framework/Content/AssetName.cs (limited to 'src/SMAPI/Framework/Content') diff --git a/src/SMAPI/Framework/Content/AssetData.cs b/src/SMAPI/Framework/Content/AssetData.cs index 5c90d83b..05be8a3b 100644 --- a/src/SMAPI/Framework/Content/AssetData.cs +++ b/src/SMAPI/Framework/Content/AssetData.cs @@ -25,11 +25,11 @@ namespace StardewModdingAPI.Framework.Content *********/ /// Construct an instance. /// The content's locale code, if the content is localized. - /// The normalized asset name being read. + /// The asset name being read. /// The content data being read. /// Normalizes an asset key to match the cache key. /// A callback to invoke when the data is replaced (if any). - public AssetData(string locale, string assetName, TValue data, Func getNormalizedPath, Action onDataReplaced) + public AssetData(string locale, IAssetName assetName, TValue data, Func getNormalizedPath, Action onDataReplaced) : base(locale, assetName, data.GetType(), getNormalizedPath) { this.Data = data; diff --git a/src/SMAPI/Framework/Content/AssetDataForDictionary.cs b/src/SMAPI/Framework/Content/AssetDataForDictionary.cs index 26cbff5a..735b651c 100644 --- a/src/SMAPI/Framework/Content/AssetDataForDictionary.cs +++ b/src/SMAPI/Framework/Content/AssetDataForDictionary.cs @@ -11,11 +11,11 @@ namespace StardewModdingAPI.Framework.Content *********/ /// Construct an instance. /// The content's locale code, if the content is localized. - /// The normalized asset name being read. + /// The asset name being read. /// The content data being read. /// Normalizes an asset key to match the cache key. /// A callback to invoke when the data is replaced (if any). - public AssetDataForDictionary(string locale, string assetName, IDictionary data, Func getNormalizedPath, Action> onDataReplaced) + public AssetDataForDictionary(string locale, IAssetName assetName, IDictionary data, Func getNormalizedPath, Action> onDataReplaced) : base(locale, assetName, data, getNormalizedPath, onDataReplaced) { } } } diff --git a/src/SMAPI/Framework/Content/AssetDataForImage.cs b/src/SMAPI/Framework/Content/AssetDataForImage.cs index c75514bc..b0f1b5c7 100644 --- a/src/SMAPI/Framework/Content/AssetDataForImage.cs +++ b/src/SMAPI/Framework/Content/AssetDataForImage.cs @@ -21,11 +21,11 @@ namespace StardewModdingAPI.Framework.Content *********/ /// Construct an instance. /// The content's locale code, if the content is localized. - /// The normalized asset name being read. + /// The asset name being read. /// The content data being read. /// Normalizes an asset key to match the cache key. /// A callback to invoke when the data is replaced (if any). - public AssetDataForImage(string locale, string assetName, Texture2D data, Func getNormalizedPath, Action onDataReplaced) + public AssetDataForImage(string locale, IAssetName assetName, Texture2D data, Func getNormalizedPath, Action onDataReplaced) : base(locale, assetName, data, getNormalizedPath, onDataReplaced) { } /// diff --git a/src/SMAPI/Framework/Content/AssetDataForMap.cs b/src/SMAPI/Framework/Content/AssetDataForMap.cs index 0a5fa7e7..26e4986e 100644 --- a/src/SMAPI/Framework/Content/AssetDataForMap.cs +++ b/src/SMAPI/Framework/Content/AssetDataForMap.cs @@ -18,11 +18,11 @@ namespace StardewModdingAPI.Framework.Content *********/ /// Construct an instance. /// The content's locale code, if the content is localized. - /// The normalized asset name being read. + /// The asset name being read. /// The content data being read. /// Normalizes an asset key to match the cache key. /// A callback to invoke when the data is replaced (if any). - public AssetDataForMap(string locale, string assetName, Map data, Func getNormalizedPath, Action onDataReplaced) + public AssetDataForMap(string locale, IAssetName assetName, Map data, Func getNormalizedPath, Action onDataReplaced) : base(locale, assetName, data, getNormalizedPath, onDataReplaced) { } /// diff --git a/src/SMAPI/Framework/Content/AssetDataForObject.cs b/src/SMAPI/Framework/Content/AssetDataForObject.cs index b7e8dfeb..d91873ae 100644 --- a/src/SMAPI/Framework/Content/AssetDataForObject.cs +++ b/src/SMAPI/Framework/Content/AssetDataForObject.cs @@ -13,10 +13,10 @@ namespace StardewModdingAPI.Framework.Content *********/ /// Construct an instance. /// The content's locale code, if the content is localized. - /// The normalized asset name being read. + /// The asset name being read. /// The content data being read. /// Normalizes an asset key to match the cache key. - public AssetDataForObject(string locale, string assetName, object data, Func getNormalizedPath) + public AssetDataForObject(string locale, IAssetName assetName, object data, Func getNormalizedPath) : base(locale, assetName, data, getNormalizedPath, onDataReplaced: null) { } /// Construct an instance. @@ -24,24 +24,24 @@ namespace StardewModdingAPI.Framework.Content /// The content data being read. /// Normalizes an asset key to match the cache key. public AssetDataForObject(IAssetInfo info, object data, Func getNormalizedPath) - : this(info.Locale, info.AssetName, data, getNormalizedPath) { } + : this(info.Locale, info.Name, data, getNormalizedPath) { } /// public IAssetDataForDictionary AsDictionary() { - return new AssetDataForDictionary(this.Locale, this.AssetName, this.GetData>(), this.GetNormalizedPath, this.ReplaceWith); + return new AssetDataForDictionary(this.Locale, this.Name, this.GetData>(), this.GetNormalizedPath, this.ReplaceWith); } /// public IAssetDataForImage AsImage() { - return new AssetDataForImage(this.Locale, this.AssetName, this.GetData(), this.GetNormalizedPath, this.ReplaceWith); + return new AssetDataForImage(this.Locale, this.Name, this.GetData(), this.GetNormalizedPath, this.ReplaceWith); } /// public IAssetDataForMap AsMap() { - return new AssetDataForMap(this.Locale, this.AssetName, this.GetData(), this.GetNormalizedPath, this.ReplaceWith); + return new AssetDataForMap(this.Locale, this.Name, this.GetData(), this.GetNormalizedPath, this.ReplaceWith); } /// diff --git a/src/SMAPI/Framework/Content/AssetInfo.cs b/src/SMAPI/Framework/Content/AssetInfo.cs index d8106439..6a5b4f31 100644 --- a/src/SMAPI/Framework/Content/AssetInfo.cs +++ b/src/SMAPI/Framework/Content/AssetInfo.cs @@ -20,7 +20,11 @@ namespace StardewModdingAPI.Framework.Content public string Locale { get; } /// - public string AssetName { get; } + public IAssetName Name { get; } + + /// + [Obsolete($"Use {nameof(Name)} instead.")] + public string AssetName => this.Name.Name; /// public Type DataType { get; } @@ -31,22 +35,22 @@ namespace StardewModdingAPI.Framework.Content *********/ /// Construct an instance. /// The content's locale code, if the content is localized. - /// The normalized asset name being read. + /// The asset name being read. /// The content type being read. /// Normalizes an asset key to match the cache key. - public AssetInfo(string locale, string assetName, Type type, Func getNormalizedPath) + public AssetInfo(string locale, IAssetName assetName, Type type, Func getNormalizedPath) { this.Locale = locale; - this.AssetName = assetName; + this.Name = assetName; this.DataType = type; this.GetNormalizedPath = getNormalizedPath; } /// + [Obsolete($"Use {nameof(Name)}.{nameof(IAssetName.IsEquivalentTo)} instead.")] public bool AssetNameEquals(string path) { - path = this.GetNormalizedPath(path); - return this.AssetName.Equals(path, StringComparison.OrdinalIgnoreCase); + return this.Name.IsEquivalentTo(path); } diff --git a/src/SMAPI/Framework/Content/AssetInterceptorChange.cs b/src/SMAPI/Framework/Content/AssetInterceptorChange.cs index 10488b84..981eed40 100644 --- a/src/SMAPI/Framework/Content/AssetInterceptorChange.cs +++ b/src/SMAPI/Framework/Content/AssetInterceptorChange.cs @@ -70,7 +70,7 @@ namespace StardewModdingAPI.Framework.Content } catch (Exception ex) { - this.Mod.LogAsMod($"Mod failed when checking whether it could edit asset '{asset.AssetName}'. Error details:\n{ex.GetLogSummary()}", LogLevel.Error); + this.Mod.LogAsMod($"Mod failed when checking whether it could edit asset '{asset.Name}'. Error details:\n{ex.GetLogSummary()}", LogLevel.Error); } } @@ -84,7 +84,7 @@ namespace StardewModdingAPI.Framework.Content } catch (Exception ex) { - this.Mod.LogAsMod($"Mod failed when checking whether it could load asset '{asset.AssetName}'. Error details:\n{ex.GetLogSummary()}", LogLevel.Error); + this.Mod.LogAsMod($"Mod failed when checking whether it could load asset '{asset.Name}'. Error details:\n{ex.GetLogSummary()}", LogLevel.Error); } } diff --git a/src/SMAPI/Framework/Content/AssetName.cs b/src/SMAPI/Framework/Content/AssetName.cs new file mode 100644 index 00000000..992647f8 --- /dev/null +++ b/src/SMAPI/Framework/Content/AssetName.cs @@ -0,0 +1,173 @@ +using System; +using StardewModdingAPI.Toolkit.Utilities; +using StardewValley; + +namespace StardewModdingAPI.Framework.Content +{ + /// An asset name that can be loaded through the content pipeline. + internal class AssetName : IAssetName + { + /********* + ** Fields + *********/ + /// A lowercase version of used for consistent hash codes and equality checks. + private readonly string ComparableName; + + + /********* + ** Accessors + *********/ + /// + public string Name { get; } + + /// + public string BaseName { get; } + + /// + public string LocaleCode { get; } + + /// + public LocalizedContentManager.LanguageCode? LanguageCode { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The base asset name without the locale code. + /// The locale code specified in the , if it's a valid code recognized by the game content. + /// The language code matching the , if applicable. + public AssetName(string baseName, string localeCode, LocalizedContentManager.LanguageCode? languageCode) + { + // validate + if (string.IsNullOrWhiteSpace(baseName)) + throw new ArgumentException("The asset name can't be null or empty.", nameof(baseName)); + if (string.IsNullOrWhiteSpace(localeCode)) + localeCode = null; + + // set base values + this.BaseName = PathUtilities.NormalizeAssetName(baseName); + this.LocaleCode = localeCode; + this.LanguageCode = languageCode; + + // set derived values + this.Name = localeCode != null + ? string.Concat(this.BaseName, '.', this.LocaleCode) + : this.BaseName; + this.ComparableName = this.Name.ToLowerInvariant(); + } + + /// Parse a raw asset name into an instance. + /// The raw asset name to parse. + /// Get the language code for a given locale, if it's valid. + /// The is null or empty. + public static AssetName Parse(string rawName, Func parseLocale) + { + if (string.IsNullOrWhiteSpace(rawName)) + throw new ArgumentException("The asset name can't be null or empty.", nameof(rawName)); + + string baseName = rawName; + string localeCode = null; + LocalizedContentManager.LanguageCode? languageCode = null; + + int lastPeriodIndex = rawName.LastIndexOf('.'); + if (lastPeriodIndex > 0 && rawName.Length > lastPeriodIndex + 1) + { + string possibleLocaleCode = rawName[(lastPeriodIndex + 1)..]; + LocalizedContentManager.LanguageCode? possibleLanguageCode = parseLocale(possibleLocaleCode); + + if (possibleLanguageCode != null) + { + baseName = rawName[..lastPeriodIndex]; + localeCode = possibleLocaleCode; + languageCode = possibleLanguageCode; + } + } + + return new AssetName(baseName, localeCode, languageCode); + } + + /// + public bool IsEquivalentTo(string assetName, bool useBaseName = false) + { + // empty asset key is never equivalent + if (string.IsNullOrWhiteSpace(assetName)) + return false; + + assetName = PathUtilities.NormalizeAssetName(assetName); + + string compareTo = useBaseName ? this.BaseName : this.Name; + return compareTo.Equals(assetName, StringComparison.OrdinalIgnoreCase); + } + + /// + public bool StartsWith(string prefix, bool allowPartialWord = true, bool allowSubfolder = true) + { + // asset keys never start with null + if (prefix is null) + return false; + + // asset keys can't have a leading slash, but NormalizeAssetName will trim them + { + string trimmed = prefix.TrimStart(); + if (trimmed.StartsWith('/') || trimmed.StartsWith('\\')) + return false; + } + + // normalize prefix + { + string normalized = PathUtilities.NormalizeAssetName(prefix); + + string trimmed = prefix.TrimEnd(); + if (trimmed.EndsWith('/') || trimmed.EndsWith('\\')) + normalized += PathUtilities.PreferredAssetSeparator; + + prefix = normalized; + } + + // compare + return + this.Name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase) + && ( + allowPartialWord + || this.Name.Length == prefix.Length + || !char.IsLetterOrDigit(prefix[^1]) // last character in suffix is word separator + || !char.IsLetterOrDigit(this.Name[prefix.Length]) // or first character after it is + ) + && ( + allowSubfolder + || this.Name.Length == prefix.Length + || !this.Name[prefix.Length..].Contains(PathUtilities.PreferredAssetSeparator) + ); + } + + + public bool IsDirectlyUnderPath(string assetFolder) + { + return this.StartsWith(assetFolder + "/", allowPartialWord: false, allowSubfolder: false); + } + + /// + public bool Equals(IAssetName other) + { + return other switch + { + null => false, + AssetName otherImpl => this.ComparableName == otherImpl.ComparableName, + _ => StringComparer.OrdinalIgnoreCase.Equals(this.Name, other.Name) + }; + } + + /// + public override int GetHashCode() + { + return this.ComparableName.GetHashCode(); + } + + /// + public override string ToString() + { + return this.Name; + } + } +} -- cgit From a42926868ae5878ed59d6406ca085b587299ba07 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 20 Mar 2022 12:53:27 -0400 Subject: encapsulate editor/loader operations (#766) These will be used by the new content API, and allow handling the old one the same way. --- src/SMAPI/Framework/Content/AssetEditOperation.cs | 30 +++++++++++++++++++++++ src/SMAPI/Framework/Content/AssetLoadOperation.cs | 30 +++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/SMAPI/Framework/Content/AssetEditOperation.cs create mode 100644 src/SMAPI/Framework/Content/AssetLoadOperation.cs (limited to 'src/SMAPI/Framework/Content') diff --git a/src/SMAPI/Framework/Content/AssetEditOperation.cs b/src/SMAPI/Framework/Content/AssetEditOperation.cs new file mode 100644 index 00000000..fa189d44 --- /dev/null +++ b/src/SMAPI/Framework/Content/AssetEditOperation.cs @@ -0,0 +1,30 @@ +using System; + +namespace StardewModdingAPI.Framework.Content +{ + /// An edit to apply to an asset when it's requested from the content pipeline. + internal class AssetEditOperation + { + /********* + ** Accessors + *********/ + /// The mod applying the edit. + public IModMetadata Mod { get; } + + /// Apply the edit to an asset. + public Action ApplyEdit { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The mod applying the edit. + /// Apply the edit to an asset. + public AssetEditOperation(IModMetadata mod, Action applyEdit) + { + this.Mod = mod; + this.ApplyEdit = applyEdit; + } + } +} diff --git a/src/SMAPI/Framework/Content/AssetLoadOperation.cs b/src/SMAPI/Framework/Content/AssetLoadOperation.cs new file mode 100644 index 00000000..d773cadd --- /dev/null +++ b/src/SMAPI/Framework/Content/AssetLoadOperation.cs @@ -0,0 +1,30 @@ +using System; + +namespace StardewModdingAPI.Framework.Content +{ + /// An operation which provides the initial instance of an asset when it's requested from the content pipeline. + internal class AssetLoadOperation + { + /********* + ** Accessors + *********/ + /// The mod applying the edit. + public IModMetadata Mod { get; } + + /// Load the initial value for an asset. + public Func GetData { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The mod applying the edit. + /// Load the initial value for an asset. + public AssetLoadOperation(IModMetadata mod, Func getData) + { + this.Mod = mod; + this.GetData = getData; + } + } +} -- cgit From b07d2340a9a6da22ee0fd95f2c6ccca3939cb7ab Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 22 Mar 2022 23:00:18 -0400 Subject: encapsulate & cache asset operation groups (#766) This is needed for the upcoming Stardew Valley 1.6 to avoid duplicate checks between DoesAssetExist and Load calls, and to make sure the answer doesn't change between them. --- src/SMAPI/Framework/Content/AssetOperationGroup.cs | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/SMAPI/Framework/Content/AssetOperationGroup.cs (limited to 'src/SMAPI/Framework/Content') diff --git a/src/SMAPI/Framework/Content/AssetOperationGroup.cs b/src/SMAPI/Framework/Content/AssetOperationGroup.cs new file mode 100644 index 00000000..a2fcb722 --- /dev/null +++ b/src/SMAPI/Framework/Content/AssetOperationGroup.cs @@ -0,0 +1,33 @@ +namespace StardewModdingAPI.Framework.Content +{ + /// A set of operations to apply to an asset for a given or implementation. + internal class AssetOperationGroup + { + /********* + ** Accessors + *********/ + /// The mod applying the changes. + public IModMetadata Mod { get; } + + /// The load operations to apply. + public AssetLoadOperation[] LoadOperations { get; } + + /// The edit operations to apply. + public AssetEditOperation[] EditOperations { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The mod applying the changes. + /// The load operations to apply. + /// The edit operations to apply. + public AssetOperationGroup(IModMetadata mod, AssetLoadOperation[] loadOperations, AssetEditOperation[] editOperations) + { + this.Mod = mod; + this.LoadOperations = loadOperations; + this.EditOperations = editOperations; + } + } +} -- cgit From e1fc566e0afeb6eb92418bb039365611abd33829 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 25 Mar 2022 21:46:37 -0400 Subject: add content pack labels (#766) --- src/SMAPI/Framework/Content/AssetEditOperation.cs | 7 ++++++- src/SMAPI/Framework/Content/AssetLoadOperation.cs | 9 +++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'src/SMAPI/Framework/Content') diff --git a/src/SMAPI/Framework/Content/AssetEditOperation.cs b/src/SMAPI/Framework/Content/AssetEditOperation.cs index fa189d44..14db231c 100644 --- a/src/SMAPI/Framework/Content/AssetEditOperation.cs +++ b/src/SMAPI/Framework/Content/AssetEditOperation.cs @@ -11,6 +11,9 @@ namespace StardewModdingAPI.Framework.Content /// The mod applying the edit. public IModMetadata Mod { get; } + /// The content pack on whose behalf the edit is being applied, if any. + public IModMetadata OnBehalfOf { get; } + /// Apply the edit to an asset. public Action ApplyEdit { get; } @@ -20,10 +23,12 @@ namespace StardewModdingAPI.Framework.Content *********/ /// Construct an instance. /// The mod applying the edit. + /// The content pack on whose behalf the edit is being applied, if any. /// Apply the edit to an asset. - public AssetEditOperation(IModMetadata mod, Action applyEdit) + public AssetEditOperation(IModMetadata mod, IModMetadata onBehalfOf, Action applyEdit) { this.Mod = mod; + this.OnBehalfOf = onBehalfOf; this.ApplyEdit = applyEdit; } } diff --git a/src/SMAPI/Framework/Content/AssetLoadOperation.cs b/src/SMAPI/Framework/Content/AssetLoadOperation.cs index d773cadd..29bf1518 100644 --- a/src/SMAPI/Framework/Content/AssetLoadOperation.cs +++ b/src/SMAPI/Framework/Content/AssetLoadOperation.cs @@ -8,9 +8,12 @@ namespace StardewModdingAPI.Framework.Content /********* ** Accessors *********/ - /// The mod applying the edit. + /// The mod loading the asset. public IModMetadata Mod { get; } + /// The content pack on whose behalf the asset is being loaded, if any. + public IModMetadata OnBehalfOf { get; } + /// Load the initial value for an asset. public Func GetData { get; } @@ -20,10 +23,12 @@ namespace StardewModdingAPI.Framework.Content *********/ /// Construct an instance. /// The mod applying the edit. + /// The content pack on whose behalf the asset is being loaded, if any. /// Load the initial value for an asset. - public AssetLoadOperation(IModMetadata mod, Func getData) + public AssetLoadOperation(IModMetadata mod, IModMetadata onBehalfOf, Func getData) { this.Mod = mod; + this.OnBehalfOf = onBehalfOf; this.GetData = getData; } } -- cgit From 021891ff0ceb6b327bc196c336aa56ddfaf99b0e Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 25 Mar 2022 22:49:14 -0400 Subject: add load conflict resolution option (#766) --- src/SMAPI/Framework/Content/AssetLoadOperation.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/SMAPI/Framework/Content') diff --git a/src/SMAPI/Framework/Content/AssetLoadOperation.cs b/src/SMAPI/Framework/Content/AssetLoadOperation.cs index 29bf1518..36baf1aa 100644 --- a/src/SMAPI/Framework/Content/AssetLoadOperation.cs +++ b/src/SMAPI/Framework/Content/AssetLoadOperation.cs @@ -14,6 +14,9 @@ namespace StardewModdingAPI.Framework.Content /// The content pack on whose behalf the asset is being loaded, if any. public IModMetadata OnBehalfOf { get; } + /// Whether to allow skipping this operation to resolve a load conflict. + public bool AllowSkipOnConflict { get; } + /// Load the initial value for an asset. public Func GetData { get; } @@ -23,11 +26,13 @@ namespace StardewModdingAPI.Framework.Content *********/ /// Construct an instance. /// The mod applying the edit. + /// Whether to allow skipping this operation to resolve a load conflict. /// The content pack on whose behalf the asset is being loaded, if any. /// Load the initial value for an asset. - public AssetLoadOperation(IModMetadata mod, IModMetadata onBehalfOf, Func getData) + public AssetLoadOperation(IModMetadata mod, bool allowSkipOnConflict, IModMetadata onBehalfOf, Func getData) { this.Mod = mod; + this.AllowSkipOnConflict = allowSkipOnConflict; this.OnBehalfOf = onBehalfOf; this.GetData = getData; } -- cgit From 3707f481a567df5149aea00ffb14cddb7b14fccb Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 25 Mar 2022 23:53:30 -0400 Subject: extend load conflict resolution into load priority (#766) --- src/SMAPI/Framework/Content/AssetLoadOperation.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/SMAPI/Framework/Content') diff --git a/src/SMAPI/Framework/Content/AssetLoadOperation.cs b/src/SMAPI/Framework/Content/AssetLoadOperation.cs index 36baf1aa..b12958d6 100644 --- a/src/SMAPI/Framework/Content/AssetLoadOperation.cs +++ b/src/SMAPI/Framework/Content/AssetLoadOperation.cs @@ -1,4 +1,5 @@ using System; +using StardewModdingAPI.Events; namespace StardewModdingAPI.Framework.Content { @@ -14,8 +15,8 @@ namespace StardewModdingAPI.Framework.Content /// The content pack on whose behalf the asset is being loaded, if any. public IModMetadata OnBehalfOf { get; } - /// Whether to allow skipping this operation to resolve a load conflict. - public bool AllowSkipOnConflict { get; } + /// If there are multiple loads that apply to the same asset, the priority with which this one should be applied. + public AssetLoadPriority Priority { get; } /// Load the initial value for an asset. public Func GetData { get; } @@ -26,13 +27,13 @@ namespace StardewModdingAPI.Framework.Content *********/ /// Construct an instance. /// The mod applying the edit. - /// Whether to allow skipping this operation to resolve a load conflict. + /// If there are multiple loads that apply to the same asset, the priority with which this one should be applied. /// The content pack on whose behalf the asset is being loaded, if any. /// Load the initial value for an asset. - public AssetLoadOperation(IModMetadata mod, bool allowSkipOnConflict, IModMetadata onBehalfOf, Func getData) + public AssetLoadOperation(IModMetadata mod, AssetLoadPriority priority, IModMetadata onBehalfOf, Func getData) { this.Mod = mod; - this.AllowSkipOnConflict = allowSkipOnConflict; + this.Priority = priority; this.OnBehalfOf = onBehalfOf; this.GetData = getData; } -- cgit From e40907ab8b97bd8a557adf683a406413646b1fc5 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 26 Mar 2022 01:19:44 -0400 Subject: add NameWithoutLocale fields (#766) --- src/SMAPI/Framework/Content/AssetInfo.cs | 12 ++++++++---- src/SMAPI/Framework/Content/AssetName.cs | 9 +++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) (limited to 'src/SMAPI/Framework/Content') diff --git a/src/SMAPI/Framework/Content/AssetInfo.cs b/src/SMAPI/Framework/Content/AssetInfo.cs index 6a5b4f31..556f1c2a 100644 --- a/src/SMAPI/Framework/Content/AssetInfo.cs +++ b/src/SMAPI/Framework/Content/AssetInfo.cs @@ -23,8 +23,11 @@ namespace StardewModdingAPI.Framework.Content public IAssetName Name { get; } /// - [Obsolete($"Use {nameof(Name)} instead.")] - public string AssetName => this.Name.Name; + public IAssetName NameWithoutLocale { get; } + + /// + [Obsolete($"Use {nameof(Name)} or {nameof(NameWithoutLocale)} instead.")] + public string AssetName => this.NameWithoutLocale.Name; /// public Type DataType { get; } @@ -42,15 +45,16 @@ namespace StardewModdingAPI.Framework.Content { this.Locale = locale; this.Name = assetName; + this.NameWithoutLocale = assetName.GetBaseAssetName(); this.DataType = type; this.GetNormalizedPath = getNormalizedPath; } /// - [Obsolete($"Use {nameof(Name)}.{nameof(IAssetName.IsEquivalentTo)} instead.")] + [Obsolete($"Use {nameof(Name)}.{nameof(IAssetName.IsEquivalentTo)} or {nameof(NameWithoutLocale)}.{nameof(IAssetName.IsEquivalentTo)} instead.")] public bool AssetNameEquals(string path) { - return this.Name.IsEquivalentTo(path); + return this.NameWithoutLocale.IsEquivalentTo(path); } diff --git a/src/SMAPI/Framework/Content/AssetName.cs b/src/SMAPI/Framework/Content/AssetName.cs index 992647f8..7ce0f8ee 100644 --- a/src/SMAPI/Framework/Content/AssetName.cs +++ b/src/SMAPI/Framework/Content/AssetName.cs @@ -142,11 +142,20 @@ namespace StardewModdingAPI.Framework.Content } + /// public bool IsDirectlyUnderPath(string assetFolder) { return this.StartsWith(assetFolder + "/", allowPartialWord: false, allowSubfolder: false); } + /// + IAssetName IAssetName.GetBaseAssetName() + { + return this.LocaleCode == null + ? this + : new AssetName(this.BaseName, null, null); + } + /// public bool Equals(IAssetName other) { -- cgit From ad8912047beaf84ce34f4918703d55841be13ff0 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 26 Mar 2022 01:43:40 -0400 Subject: add asset edit priority (#766) --- src/SMAPI/Framework/Content/AssetEditOperation.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/SMAPI/Framework/Content') diff --git a/src/SMAPI/Framework/Content/AssetEditOperation.cs b/src/SMAPI/Framework/Content/AssetEditOperation.cs index 14db231c..818209fa 100644 --- a/src/SMAPI/Framework/Content/AssetEditOperation.cs +++ b/src/SMAPI/Framework/Content/AssetEditOperation.cs @@ -1,4 +1,5 @@ using System; +using StardewModdingAPI.Events; namespace StardewModdingAPI.Framework.Content { @@ -11,6 +12,9 @@ namespace StardewModdingAPI.Framework.Content /// The mod applying the edit. public IModMetadata Mod { get; } + /// If there are multiple edits that apply to the same asset, the priority with which this one should be applied. + public AssetEditPriority Priority { get; } + /// The content pack on whose behalf the edit is being applied, if any. public IModMetadata OnBehalfOf { get; } @@ -23,11 +27,13 @@ namespace StardewModdingAPI.Framework.Content *********/ /// Construct an instance. /// The mod applying the edit. + /// If there are multiple edits that apply to the same asset, the priority with which this one should be applied. /// The content pack on whose behalf the edit is being applied, if any. /// Apply the edit to an asset. - public AssetEditOperation(IModMetadata mod, IModMetadata onBehalfOf, Action applyEdit) + public AssetEditOperation(IModMetadata mod, AssetEditPriority priority, IModMetadata onBehalfOf, Action applyEdit) { this.Mod = mod; + this.Priority = priority; this.OnBehalfOf = onBehalfOf; this.ApplyEdit = applyEdit; } -- cgit From 8d704153762fa73416a3ccb44ee71032952802eb Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 26 Mar 2022 15:02:11 -0400 Subject: add deprecation notices for SMAPI 4.0.0 (#766) --- src/SMAPI/Framework/Content/AssetInfo.cs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'src/SMAPI/Framework/Content') diff --git a/src/SMAPI/Framework/Content/AssetInfo.cs b/src/SMAPI/Framework/Content/AssetInfo.cs index 556f1c2a..6e93c33c 100644 --- a/src/SMAPI/Framework/Content/AssetInfo.cs +++ b/src/SMAPI/Framework/Content/AssetInfo.cs @@ -27,7 +27,20 @@ namespace StardewModdingAPI.Framework.Content /// [Obsolete($"Use {nameof(Name)} or {nameof(NameWithoutLocale)} instead.")] - public string AssetName => this.NameWithoutLocale.Name; + public string AssetName + { + get + { + SCore.DeprecationManager.Warn( + source: SCore.DeprecationManager.GetSourceNameFromStack(), + nounPhrase: $"{nameof(IAssetInfo)}.{nameof(IAssetInfo.AssetName)}", + version: "3.14.0", + severity: DeprecationLevel.Notice + ); + + return this.NameWithoutLocale.Name; + } + } /// public Type DataType { get; } @@ -54,6 +67,14 @@ namespace StardewModdingAPI.Framework.Content [Obsolete($"Use {nameof(Name)}.{nameof(IAssetName.IsEquivalentTo)} or {nameof(NameWithoutLocale)}.{nameof(IAssetName.IsEquivalentTo)} instead.")] public bool AssetNameEquals(string path) { + SCore.DeprecationManager.Warn( + source: SCore.DeprecationManager.GetSourceNameFromStack(), + nounPhrase: $"{nameof(IAssetInfo)}.{nameof(IAssetInfo.AssetNameEquals)}", + version: "3.14.0", + severity: DeprecationLevel.Notice + ); + + return this.NameWithoutLocale.IsEquivalentTo(path); } -- cgit From eebd8d54dc068cff2b5127a4b8f03d0b54b89542 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 26 Mar 2022 18:34:49 -0400 Subject: expand obsolete attributes (#766) --- src/SMAPI/Framework/Content/AssetInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/SMAPI/Framework/Content') diff --git a/src/SMAPI/Framework/Content/AssetInfo.cs b/src/SMAPI/Framework/Content/AssetInfo.cs index 6e93c33c..f5da5d69 100644 --- a/src/SMAPI/Framework/Content/AssetInfo.cs +++ b/src/SMAPI/Framework/Content/AssetInfo.cs @@ -26,7 +26,7 @@ namespace StardewModdingAPI.Framework.Content public IAssetName NameWithoutLocale { get; } /// - [Obsolete($"Use {nameof(Name)} or {nameof(NameWithoutLocale)} instead.")] + [Obsolete($"Use {nameof(Name)} or {nameof(NameWithoutLocale)} instead. This property will be removed in SMAPI 4.0.0.")] public string AssetName { get @@ -64,7 +64,7 @@ namespace StardewModdingAPI.Framework.Content } /// - [Obsolete($"Use {nameof(Name)}.{nameof(IAssetName.IsEquivalentTo)} or {nameof(NameWithoutLocale)}.{nameof(IAssetName.IsEquivalentTo)} instead.")] + [Obsolete($"Use {nameof(Name)}.{nameof(IAssetName.IsEquivalentTo)} or {nameof(NameWithoutLocale)}.{nameof(IAssetName.IsEquivalentTo)} instead. This method will be removed in SMAPI 4.0.0.")] public bool AssetNameEquals(string path) { SCore.DeprecationManager.Warn( -- cgit From 1d3c99cc25f6c0d504fd5e43ea71ef327b6e9066 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 27 Mar 2022 13:42:14 -0400 Subject: split helper.Content API into game/mod content APIs --- src/SMAPI/Framework/Content/AssetName.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/SMAPI/Framework/Content') diff --git a/src/SMAPI/Framework/Content/AssetName.cs b/src/SMAPI/Framework/Content/AssetName.cs index 7ce0f8ee..a1d37b0b 100644 --- a/src/SMAPI/Framework/Content/AssetName.cs +++ b/src/SMAPI/Framework/Content/AssetName.cs @@ -100,6 +100,18 @@ namespace StardewModdingAPI.Framework.Content return compareTo.Equals(assetName, StringComparison.OrdinalIgnoreCase); } + /// + public bool IsEquivalentTo(IAssetName assetName, bool useBaseName = false) + { + if (useBaseName) + return this.BaseName.Equals(assetName?.BaseName, StringComparison.OrdinalIgnoreCase); + + if (assetName is AssetName impl) + return this.ComparableName == impl?.ComparableName; + + return this.Name.Equals(assetName?.Name, StringComparison.OrdinalIgnoreCase); + } + /// public bool StartsWith(string prefix, bool allowPartialWord = true, bool allowSubfolder = true) { -- cgit From a593eda30f82af474887d91458b0e9158f66fefc Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 6 Apr 2022 18:24:59 -0400 Subject: use target-typed new --- src/SMAPI/Framework/Content/AssetDataForMap.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/SMAPI/Framework/Content') diff --git a/src/SMAPI/Framework/Content/AssetDataForMap.cs b/src/SMAPI/Framework/Content/AssetDataForMap.cs index 26e4986e..0458f80a 100644 --- a/src/SMAPI/Framework/Content/AssetDataForMap.cs +++ b/src/SMAPI/Framework/Content/AssetDataForMap.cs @@ -96,8 +96,8 @@ namespace StardewModdingAPI.Framework.Content for (int y = 0; y < sourceArea.Value.Height; y++) { // calculate tile positions - Point sourcePos = new Point(sourceArea.Value.X + x, sourceArea.Value.Y + y); - Point targetPos = new Point(targetArea.Value.X + x, targetArea.Value.Y + y); + Point sourcePos = new(sourceArea.Value.X + x, sourceArea.Value.Y + y); + Point targetPos = new(targetArea.Value.X + x, targetArea.Value.Y + y); // replace tiles on target-only layers if (replaceAll) -- cgit From b6c8cfc28b2c94e6dc3cb07d3058371dd6775e70 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 6 Apr 2022 18:24:59 -0400 Subject: simplify 'is not' patterns --- src/SMAPI/Framework/Content/AssetDataForObject.cs | 2 +- src/SMAPI/Framework/Content/AssetInterceptorChange.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/SMAPI/Framework/Content') diff --git a/src/SMAPI/Framework/Content/AssetDataForObject.cs b/src/SMAPI/Framework/Content/AssetDataForObject.cs index d91873ae..40f49190 100644 --- a/src/SMAPI/Framework/Content/AssetDataForObject.cs +++ b/src/SMAPI/Framework/Content/AssetDataForObject.cs @@ -47,7 +47,7 @@ namespace StardewModdingAPI.Framework.Content /// public TData GetData() { - if (!(this.Data is TData)) + if (this.Data is not 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/SMAPI/Framework/Content/AssetInterceptorChange.cs b/src/SMAPI/Framework/Content/AssetInterceptorChange.cs index 981eed40..03d6da5a 100644 --- a/src/SMAPI/Framework/Content/AssetInterceptorChange.cs +++ b/src/SMAPI/Framework/Content/AssetInterceptorChange.cs @@ -36,7 +36,7 @@ namespace StardewModdingAPI.Framework.Content this.Instance = instance ?? throw new ArgumentNullException(nameof(instance)); this.WasAdded = wasAdded; - if (!(instance is IAssetEditor) && !(instance is IAssetLoader)) + if (instance is not (IAssetEditor or IAssetLoader)) throw new InvalidCastException($"The provided {nameof(instance)} value must be an {nameof(IAssetEditor)} or {nameof(IAssetLoader)} instance."); } -- cgit From 0539bb8f3705e5c50d0e5790e2af97f39aed04b8 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 6 Apr 2022 18:25:00 -0400 Subject: simplify with newer pattern features --- src/SMAPI/Framework/Content/AssetDataForObject.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/SMAPI/Framework/Content') diff --git a/src/SMAPI/Framework/Content/AssetDataForObject.cs b/src/SMAPI/Framework/Content/AssetDataForObject.cs index 40f49190..bafd8941 100644 --- a/src/SMAPI/Framework/Content/AssetDataForObject.cs +++ b/src/SMAPI/Framework/Content/AssetDataForObject.cs @@ -47,9 +47,9 @@ namespace StardewModdingAPI.Framework.Content /// public TData GetData() { - if (this.Data is not TData) + if (this.Data is not TData data) 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; + return data; } } } -- cgit From 077d8e4f401ad1806c6af0540f432366314a2300 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 6 Apr 2022 18:25:00 -0400 Subject: remove some unused/redundant code --- src/SMAPI/Framework/Content/AssetDataForMap.cs | 2 +- src/SMAPI/Framework/Content/AssetName.cs | 2 +- src/SMAPI/Framework/Content/TilesheetReference.cs | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src/SMAPI/Framework/Content') diff --git a/src/SMAPI/Framework/Content/AssetDataForMap.cs b/src/SMAPI/Framework/Content/AssetDataForMap.cs index 0458f80a..5986e797 100644 --- a/src/SMAPI/Framework/Content/AssetDataForMap.cs +++ b/src/SMAPI/Framework/Content/AssetDataForMap.cs @@ -147,7 +147,7 @@ namespace StardewModdingAPI.Framework.Content { switch (sourceTile) { - case StaticTile _: + case StaticTile: return new StaticTile(targetLayer, targetSheet, sourceTile.BlendMode, sourceTile.TileIndex); case AnimatedTile animatedTile: diff --git a/src/SMAPI/Framework/Content/AssetName.cs b/src/SMAPI/Framework/Content/AssetName.cs index a1d37b0b..4973b444 100644 --- a/src/SMAPI/Framework/Content/AssetName.cs +++ b/src/SMAPI/Framework/Content/AssetName.cs @@ -107,7 +107,7 @@ namespace StardewModdingAPI.Framework.Content return this.BaseName.Equals(assetName?.BaseName, StringComparison.OrdinalIgnoreCase); if (assetName is AssetName impl) - return this.ComparableName == impl?.ComparableName; + return this.ComparableName == impl.ComparableName; return this.Name.Equals(assetName?.Name, StringComparison.OrdinalIgnoreCase); } diff --git a/src/SMAPI/Framework/Content/TilesheetReference.cs b/src/SMAPI/Framework/Content/TilesheetReference.cs index 0919bb44..0339b802 100644 --- a/src/SMAPI/Framework/Content/TilesheetReference.cs +++ b/src/SMAPI/Framework/Content/TilesheetReference.cs @@ -1,4 +1,3 @@ -using System.Numerics; using xTile.Dimensions; namespace StardewModdingAPI.Framework.Content -- cgit From 2e7c233f6c9bf6430672b39f970a3324deba79dd Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 6 Apr 2022 21:48:55 -0400 Subject: enable nullable annotations by default (#837) This adds `#nullable disable` to all existing code (except where null is impossible like enum files), so it can be migrated incrementally. --- src/SMAPI/Framework/Content/AssetData.cs | 2 ++ src/SMAPI/Framework/Content/AssetDataForDictionary.cs | 2 ++ src/SMAPI/Framework/Content/AssetDataForImage.cs | 2 ++ src/SMAPI/Framework/Content/AssetDataForMap.cs | 2 ++ src/SMAPI/Framework/Content/AssetDataForObject.cs | 2 ++ src/SMAPI/Framework/Content/AssetEditOperation.cs | 2 ++ src/SMAPI/Framework/Content/AssetInfo.cs | 2 ++ src/SMAPI/Framework/Content/AssetInterceptorChange.cs | 2 ++ src/SMAPI/Framework/Content/AssetLoadOperation.cs | 2 ++ src/SMAPI/Framework/Content/AssetName.cs | 2 ++ src/SMAPI/Framework/Content/AssetOperationGroup.cs | 2 ++ src/SMAPI/Framework/Content/ContentCache.cs | 2 ++ src/SMAPI/Framework/Content/TilesheetReference.cs | 2 ++ 13 files changed, 26 insertions(+) (limited to 'src/SMAPI/Framework/Content') diff --git a/src/SMAPI/Framework/Content/AssetData.cs b/src/SMAPI/Framework/Content/AssetData.cs index 05be8a3b..be4a7ce6 100644 --- a/src/SMAPI/Framework/Content/AssetData.cs +++ b/src/SMAPI/Framework/Content/AssetData.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; namespace StardewModdingAPI.Framework.Content diff --git a/src/SMAPI/Framework/Content/AssetDataForDictionary.cs b/src/SMAPI/Framework/Content/AssetDataForDictionary.cs index 735b651c..06dbe259 100644 --- a/src/SMAPI/Framework/Content/AssetDataForDictionary.cs +++ b/src/SMAPI/Framework/Content/AssetDataForDictionary.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; diff --git a/src/SMAPI/Framework/Content/AssetDataForImage.cs b/src/SMAPI/Framework/Content/AssetDataForImage.cs index b0f1b5c7..8e59cd27 100644 --- a/src/SMAPI/Framework/Content/AssetDataForImage.cs +++ b/src/SMAPI/Framework/Content/AssetDataForImage.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; diff --git a/src/SMAPI/Framework/Content/AssetDataForMap.cs b/src/SMAPI/Framework/Content/AssetDataForMap.cs index 5986e797..0425e195 100644 --- a/src/SMAPI/Framework/Content/AssetDataForMap.cs +++ b/src/SMAPI/Framework/Content/AssetDataForMap.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/src/SMAPI/Framework/Content/AssetDataForObject.cs b/src/SMAPI/Framework/Content/AssetDataForObject.cs index bafd8941..4a6df64b 100644 --- a/src/SMAPI/Framework/Content/AssetDataForObject.cs +++ b/src/SMAPI/Framework/Content/AssetDataForObject.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using Microsoft.Xna.Framework.Graphics; diff --git a/src/SMAPI/Framework/Content/AssetEditOperation.cs b/src/SMAPI/Framework/Content/AssetEditOperation.cs index 818209fa..1b7d0c93 100644 --- a/src/SMAPI/Framework/Content/AssetEditOperation.cs +++ b/src/SMAPI/Framework/Content/AssetEditOperation.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using StardewModdingAPI.Events; diff --git a/src/SMAPI/Framework/Content/AssetInfo.cs b/src/SMAPI/Framework/Content/AssetInfo.cs index f5da5d69..51dcc61f 100644 --- a/src/SMAPI/Framework/Content/AssetInfo.cs +++ b/src/SMAPI/Framework/Content/AssetInfo.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using Microsoft.Xna.Framework.Graphics; diff --git a/src/SMAPI/Framework/Content/AssetInterceptorChange.cs b/src/SMAPI/Framework/Content/AssetInterceptorChange.cs index 03d6da5a..7f53db9b 100644 --- a/src/SMAPI/Framework/Content/AssetInterceptorChange.cs +++ b/src/SMAPI/Framework/Content/AssetInterceptorChange.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Reflection; using StardewModdingAPI.Internal; diff --git a/src/SMAPI/Framework/Content/AssetLoadOperation.cs b/src/SMAPI/Framework/Content/AssetLoadOperation.cs index b12958d6..73e60e24 100644 --- a/src/SMAPI/Framework/Content/AssetLoadOperation.cs +++ b/src/SMAPI/Framework/Content/AssetLoadOperation.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using StardewModdingAPI.Events; diff --git a/src/SMAPI/Framework/Content/AssetName.cs b/src/SMAPI/Framework/Content/AssetName.cs index 4973b444..4d583d82 100644 --- a/src/SMAPI/Framework/Content/AssetName.cs +++ b/src/SMAPI/Framework/Content/AssetName.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using StardewModdingAPI.Toolkit.Utilities; using StardewValley; diff --git a/src/SMAPI/Framework/Content/AssetOperationGroup.cs b/src/SMAPI/Framework/Content/AssetOperationGroup.cs index a2fcb722..e3c3f92c 100644 --- a/src/SMAPI/Framework/Content/AssetOperationGroup.cs +++ b/src/SMAPI/Framework/Content/AssetOperationGroup.cs @@ -1,3 +1,5 @@ +#nullable disable + namespace StardewModdingAPI.Framework.Content { /// A set of operations to apply to an asset for a given or implementation. diff --git a/src/SMAPI/Framework/Content/ContentCache.cs b/src/SMAPI/Framework/Content/ContentCache.cs index 8e0c6228..4e620d28 100644 --- a/src/SMAPI/Framework/Content/ContentCache.cs +++ b/src/SMAPI/Framework/Content/ContentCache.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics.Contracts; diff --git a/src/SMAPI/Framework/Content/TilesheetReference.cs b/src/SMAPI/Framework/Content/TilesheetReference.cs index 0339b802..cdc4bc62 100644 --- a/src/SMAPI/Framework/Content/TilesheetReference.cs +++ b/src/SMAPI/Framework/Content/TilesheetReference.cs @@ -1,3 +1,5 @@ +#nullable disable + using xTile.Dimensions; namespace StardewModdingAPI.Framework.Content -- cgit From 1e61309d3dce484d5b646b1a8d15c825beac813f Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Mon, 11 Apr 2022 22:56:14 -0400 Subject: add IAssetDataForMap.ExtendMap --- src/SMAPI/Framework/Content/AssetDataForMap.cs | 54 ++++++++++++++++++++++- src/SMAPI/Framework/Content/AssetDataForObject.cs | 23 +++++++--- 2 files changed, 70 insertions(+), 7 deletions(-) (limited to 'src/SMAPI/Framework/Content') diff --git a/src/SMAPI/Framework/Content/AssetDataForMap.cs b/src/SMAPI/Framework/Content/AssetDataForMap.cs index 0425e195..93148277 100644 --- a/src/SMAPI/Framework/Content/AssetDataForMap.cs +++ b/src/SMAPI/Framework/Content/AssetDataForMap.cs @@ -4,17 +4,27 @@ using System; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; +using StardewModdingAPI.Framework.Reflection; using StardewModdingAPI.Toolkit.Utilities; using StardewValley; using xTile; +using xTile.Dimensions; using xTile.Layers; using xTile.Tiles; +using Rectangle = Microsoft.Xna.Framework.Rectangle; namespace StardewModdingAPI.Framework.Content { /// Encapsulates access and changes to image content being read from a data file. internal class AssetDataForMap : AssetData, IAssetDataForMap { + /********* + ** Fields + *********/ + /// Simplifies access to private code. + private readonly Reflector Reflection; + + /********* ** Public methods *********/ @@ -24,8 +34,12 @@ namespace StardewModdingAPI.Framework.Content /// The content data being read. /// Normalizes an asset key to match the cache key. /// A callback to invoke when the data is replaced (if any). - public AssetDataForMap(string locale, IAssetName assetName, Map data, Func getNormalizedPath, Action onDataReplaced) - : base(locale, assetName, data, getNormalizedPath, onDataReplaced) { } + /// Simplifies access to private code. + public AssetDataForMap(string locale, IAssetName assetName, Map data, Func getNormalizedPath, Action onDataReplaced, Reflector reflection) + : base(locale, assetName, data, getNormalizedPath, onDataReplaced) + { + this.Reflection = reflection; + } /// /// Derived from with a few changes: @@ -137,6 +151,42 @@ namespace StardewModdingAPI.Framework.Content } } + /// + public bool ExtendMap(Map map, int minWidth, int minHeight) + { + bool resized = false; + + // resize layers + foreach (Layer layer in map.Layers) + { + // check if resize needed + if (layer.LayerWidth >= minWidth && layer.LayerHeight >= minHeight) + continue; + resized = true; + + // build new tile matrix + int width = Math.Max(minWidth, layer.LayerWidth); + int height = Math.Max(minHeight, layer.LayerHeight); + Tile[,] tiles = new Tile[width, height]; + for (int x = 0; x < layer.LayerWidth; x++) + { + for (int y = 0; y < layer.LayerHeight; y++) + tiles[x, y] = layer.Tiles[x, y]; + } + + // update fields + this.Reflection.GetField(layer, "m_tiles").SetValue(tiles); + this.Reflection.GetField(layer, "m_tileArray").SetValue(new TileArray(layer, tiles)); + this.Reflection.GetField(layer, "m_layerSize").SetValue(new Size(width, height)); + } + + // resize map + if (resized) + this.Reflection.GetMethod(map, "UpdateDisplaySize").Invoke(); + + return resized; + } + /**