diff options
-rw-r--r-- | docs/release-notes.md | 6 | ||||
-rw-r--r-- | src/SMAPI.Tests/Utilities/PathUtilitiesTests.cs | 26 | ||||
-rw-r--r-- | src/SMAPI.Toolkit/Utilities/PathUtilities.cs | 15 | ||||
-rw-r--r-- | src/SMAPI/Framework/Content/AssetDataForMap.cs | 6 | ||||
-rw-r--r-- | src/SMAPI/Utilities/PathUtilities.cs | 17 |
5 files changed, 62 insertions, 8 deletions
diff --git a/docs/release-notes.md b/docs/release-notes.md index 45670c29..53640c93 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -9,11 +9,17 @@ * Updated compatibility list. * For mod authors: + * Added `PathUtilities.NormalizeAssetName` and `PathUtilities.PreferredAssetSeparator` to prepare for the upcoming Stardew Valley 1.5.5. * Fixed content packs created via `helper.ContentPacks.CreateFake` or `CreateTemporary` not initializing translations correctly. * For console commands: * Added `hurry_all` command which immediately warps all NPCs to their scheduled positions. +**Update note for mod authors:** +Stardew Valley 1.5.5 will change how asset names are formatted. If you use `PathUtilities.NormalizePath` +to format asset names, you should switch to `PathUtilities.NormalizeAssetName` now so your code will +continue working in the next game update. + ## 3.12.5 Released 26 August 2021 for Stardew Valley 1.5.4 or later. diff --git a/src/SMAPI.Tests/Utilities/PathUtilitiesTests.cs b/src/SMAPI.Tests/Utilities/PathUtilitiesTests.cs index 5a342974..c18f47a5 100644 --- a/src/SMAPI.Tests/Utilities/PathUtilitiesTests.cs +++ b/src/SMAPI.Tests/Utilities/PathUtilitiesTests.cs @@ -1,3 +1,4 @@ +using System.IO; using NUnit.Framework; using StardewModdingAPI.Toolkit.Utilities; @@ -175,9 +176,30 @@ namespace SMAPI.Tests.Utilities } /**** - ** NormalizePathSeparators + ** NormalizeAssetName ****/ - [Test(Description = "Assert that PathUtilities.NormalizePathSeparators normalizes paths correctly.")] + [Test(Description = "Assert that PathUtilities.NormalizeAssetName normalizes paths correctly.")] + [TestCaseSource(nameof(PathUtilitiesTests.SamplePaths))] + public void NormalizeAssetName(SamplePath path) + { + if (Path.IsPathRooted(path.OriginalPath) || path.OriginalPath.StartsWith("/") || path.OriginalPath.StartsWith("\\")) + Assert.Ignore("Absolute paths can't be used as asset names."); + + // act + string normalized = PathUtilities.NormalizeAssetName(path.OriginalPath); + + // assert +#if SMAPI_FOR_WINDOWS + Assert.AreEqual(path.NormalizedOnWindows, normalized); +#else + Assert.AreEqual(path.NormalizedOnUnix, normalized); +#endif + } + + /**** + ** NormalizePath + ****/ + [Test(Description = "Assert that PathUtilities.NormalizePath normalizes paths correctly.")] [TestCaseSource(nameof(PathUtilitiesTests.SamplePaths))] public void NormalizePath(SamplePath path) { diff --git a/src/SMAPI.Toolkit/Utilities/PathUtilities.cs b/src/SMAPI.Toolkit/Utilities/PathUtilities.cs index babc0981..020ebc6d 100644 --- a/src/SMAPI.Toolkit/Utilities/PathUtilities.cs +++ b/src/SMAPI.Toolkit/Utilities/PathUtilities.cs @@ -23,9 +23,12 @@ namespace StardewModdingAPI.Toolkit.Utilities /// <summary>The possible directory separator characters in a file path.</summary> public static readonly char[] PossiblePathSeparators = new[] { '/', '\\', Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }.Distinct().ToArray(); - /// <summary>The preferred directory separator character in an asset key.</summary> + /// <summary>The preferred directory separator character in a file path.</summary> public static readonly char PreferredPathSeparator = Path.DirectorySeparatorChar; + /// <summary>The preferred directory separator character in an asset key.</summary> + public static readonly char PreferredAssetSeparator = PathUtilities.PreferredPathSeparator; + /********* ** Public methods @@ -41,8 +44,16 @@ namespace StardewModdingAPI.Toolkit.Utilities : path.Split(PathUtilities.PossiblePathSeparators, StringSplitOptions.RemoveEmptyEntries); } - /// <summary>Normalize separators in a file path.</summary> + /// <summary>Normalize an asset name to match how MonoGame's content APIs would normalize and cache it.</summary> + /// <param name="assetName">The asset name to normalize.</param> + public static string NormalizeAssetName(string assetName) + { + return string.Join(PathUtilities.PreferredAssetSeparator.ToString(), PathUtilities.GetSegments(assetName)); // based on MonoGame's ContentManager.Load<T> logic + } + + /// <summary>Normalize separators in a file path for the current platform.</summary> /// <param name="path">The file path to normalize.</param> + /// <remarks>This should only be used for file paths. For asset names, use <see cref="NormalizeAssetName"/> instead.</remarks> [Pure] public static string NormalizePath(string path) { diff --git a/src/SMAPI/Framework/Content/AssetDataForMap.cs b/src/SMAPI/Framework/Content/AssetDataForMap.cs index 20f0ed0f..4f810948 100644 --- a/src/SMAPI/Framework/Content/AssetDataForMap.cs +++ b/src/SMAPI/Framework/Content/AssetDataForMap.cs @@ -153,9 +153,9 @@ namespace StardewModdingAPI.Framework.Content if (string.IsNullOrWhiteSpace(path)) return string.Empty; - path = PathUtilities.NormalizePath(path); - if (path.StartsWith($"Maps{PathUtilities.PreferredPathSeparator}", StringComparison.OrdinalIgnoreCase)) - path = path.Substring($"Maps{PathUtilities.PreferredPathSeparator}".Length); + path = PathUtilities.NormalizeAssetName(path); + if (path.StartsWith($"Maps{PathUtilities.PreferredAssetSeparator}", StringComparison.OrdinalIgnoreCase)) + path = path.Substring($"Maps{PathUtilities.PreferredAssetSeparator}".Length); if (path.EndsWith(".png", StringComparison.OrdinalIgnoreCase)) path = path.Substring(0, path.Length - 4); diff --git a/src/SMAPI/Utilities/PathUtilities.cs b/src/SMAPI/Utilities/PathUtilities.cs index 19f16ea9..541b163c 100644 --- a/src/SMAPI/Utilities/PathUtilities.cs +++ b/src/SMAPI/Utilities/PathUtilities.cs @@ -7,6 +7,13 @@ namespace StardewModdingAPI.Utilities public static class PathUtilities { /********* + ** Accessors + *********/ + /// <summary>The preferred directory separator character in an asset key.</summary> + public static char PreferredAssetSeparator { get; } = ToolkitPathUtilities.PreferredAssetSeparator; + + + /********* ** Public methods *********/ /// <summary>Get the segments from a path (e.g. <c>/usr/bin/example</c> => <c>usr</c>, <c>bin</c>, and <c>example</c>).</summary> @@ -18,8 +25,16 @@ namespace StardewModdingAPI.Utilities return ToolkitPathUtilities.GetSegments(path, limit); } - /// <summary>Normalize separators in a file path.</summary> + /// <summary>Normalize an asset name to match how MonoGame's content APIs would normalize and cache it.</summary> + /// <param name="assetName">The asset name to normalize.</param> + public static string NormalizeAssetName(string assetName) + { + return ToolkitPathUtilities.NormalizeAssetName(assetName); + } + + /// <summary>Normalize separators in a file path for the current platform.</summary> /// <param name="path">The file path to normalize.</param> + /// <remarks>This should only be used for file paths. For asset names, use <see cref="NormalizeAssetName"/> instead.</remarks> [Pure] public static string NormalizePath(string path) { |