diff --git a/src/SMAPI/Framework/ContentManagers/ModContentManager.cs b/src/SMAPI/Framework/ContentManagers/ModContentManager.cs
index 87e2809c..52287445 100644
--- a/src/SMAPI/Framework/ContentManagers/ModContentManager.cs
+++ b/src/SMAPI/Framework/ContentManagers/ModContentManager.cs
@@ -30,6 +30,9 @@ internal sealed class ModContentManager : BaseContentManager
/*********
** Fields
*********/
+ /// A path segment which navigates to the parent directory.
+ private const string DirectoryClimbingPathSegment = "..";
+
/// Encapsulates SMAPI's JSON file parsing.
private readonly JsonHelper JsonHelper;
@@ -420,7 +423,7 @@ internal sealed class ModContentManager : BaseContentManager
// 2. Can only climb once (to avoid escaping the `Content` folder).
// 3. Always relative to the `Content/Maps` folder (not the map file).
{
- const string climbSegment = "..";
+ const string climbSegment = ModContentManager.DirectoryClimbingPathSegment;
string[] pathSegments = PathUtilities.GetSegments(imageSource);
if (pathSegments.Contains(climbSegment))
{
@@ -481,7 +484,8 @@ internal sealed class ModContentManager : BaseContentManager
}
// get relative to map file unless path has directory climbing
- if (!relativePath.StartsWith("..") && PathUtilities.GetSegments(relativePath, 2)[0] != "..") // directory climbing can only be at the start of the path
+ const string climbSegment = ModContentManager.DirectoryClimbingPathSegment;
+ if (!relativePath.StartsWith(climbSegment) && PathUtilities.GetSegments(relativePath, 2)[0] != climbSegment) // directory climbing can only be at the start of the path
{
string localKey = Path.Combine(modRelativeMapFolder, relativePath);
if (this.GetModFile(localKey).Exists)
@@ -536,15 +540,17 @@ internal sealed class ModContentManager : BaseContentManager
private string GetContentKeyForTilesheetImageSource(string relativePath)
{
string key = relativePath;
- string topFolder = PathUtilities.GetSegments(key, limit: 2)[0];
- // remove previously validated directory climbing if it exists
- if (topFolder.Equals("..", StringComparison.OrdinalIgnoreCase))
- key = key[2..];
+ // make path relative to Content folder
+ {
+ string topFolder = PathUtilities.GetSegments(key, limit: 2)[0];
+ const string climbSegment = ModContentManager.DirectoryClimbingPathSegment;
- // else convert image source relative to map file into asset key
- else if (!topFolder.Equals("Maps", StringComparison.OrdinalIgnoreCase))
- key = Path.Combine("Maps", key);
+ if (topFolder == climbSegment)
+ key = key[(climbSegment.Length + 1)..];
+ else if (!topFolder.Equals("Maps", StringComparison.OrdinalIgnoreCase))
+ key = Path.Combine("Maps", key);
+ }
// remove file extension from unpacked file
if (key.EndsWith(".png", StringComparison.OrdinalIgnoreCase))