diff --git a/StardewXnbHack/Framework/PlatformContext.cs b/StardewXnbHack/Framework/PlatformContext.cs
index 184fe84..1a0fbd6 100644
--- a/StardewXnbHack/Framework/PlatformContext.cs
+++ b/StardewXnbHack/Framework/PlatformContext.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
using StardewModdingAPI.Toolkit;
@@ -26,35 +27,81 @@ public bool Is(params Platform[] platforms)
return platforms.Contains(this.Platform);
}
- /// Detect the game folder, if any.
- public string DetectGameFolder()
+ /// Get the absolute paths to the game and content folders, if found.
+ /// The game path specified by the user, if any.
+ /// The absolute path to the game folder, if found.
+ /// The absolute path to the content folder, if found.
+ /// Returns whether both the game and content folders were found.
+ public bool TryDetectGamePaths(string specifiedPath, out string gamePath, out string contentPath)
{
- string assemblyDirPath = AppDomain.CurrentDomain.BaseDirectory;
+ gamePath = null;
+ contentPath = null;
- return this.IsGameFolder(assemblyDirPath)
- ? assemblyDirPath
- : new ModToolkit().GetGameFolders().FirstOrDefault()?.FullName;
- }
+ // check possible game paths
+ foreach (string candidate in this.GetCandidateGamePaths(specifiedPath))
+ {
+ // detect paths
+ string curGamePath = this.TryGamePath(candidate);
+ string curContentPath = this.FindContentPath(curGamePath);
- /// Get the relative path from the game folder to the content folder.
- public string GetRelativeContentPath()
- {
- return this.Platform == Platform.Mac
- ? "../../Resources/Content"
- : "Content";
+ // valid game install found
+ if (curGamePath != null && curContentPath != null)
+ {
+ gamePath = curGamePath;
+ contentPath = curContentPath;
+ return true;
+ }
+
+ // if game folder exists without a content folder, track the first found game path (i.e. the highest-priority one)
+ gamePath = gamePath ?? curGamePath;
+ }
+
+ return false;
}
/*********
** Private methods
*********/
- /// Get whether a folder contains the game files.
- /// The absolute folder path to check.
- private bool IsGameFolder(string path)
+ /// Get the possible game paths.
+ /// The game path specified by the user, if any.
+ private IEnumerable GetCandidateGamePaths(string specifiedPath = null)
{
- return
- File.Exists(Path.Combine(path, this.GetExecutableFileName()))
- && Directory.Exists(Path.Combine(path, this.GetRelativeContentPath()));
+ // specified path
+ if (!string.IsNullOrWhiteSpace(specifiedPath))
+ yield return specifiedPath;
+
+ // current working directory
+ yield return AppDomain.CurrentDomain.BaseDirectory;
+
+ // detected game path
+ string detectedPath = new ModToolkit().GetGameFolders().FirstOrDefault()?.FullName;
+ if (detectedPath != null)
+ yield return detectedPath;
+ }
+
+ /// Get the absolute path to the game folder, if it's valid.
+ /// The path to check for a game install.
+ private string TryGamePath(string path)
+ {
+ // game path exists
+ if (path == null)
+ return null;
+ DirectoryInfo gameDir = new DirectoryInfo(path);
+ if (!gameDir.Exists)
+ return null;
+
+ // has game files
+ bool hasExecutable = File.Exists(Path.Combine(gameDir.FullName, this.GetExecutableFileName()));
+ if (!hasExecutable)
+ return null;
+
+ // isn't the build folder when compiled directly
+ bool isCompileFolder = File.Exists(Path.Combine(gameDir.FullName, "StardewXnbHack.exe.config"));
+ if (isCompileFolder)
+ return null;
+
+ return gameDir.FullName;
}
/// Get the filename for the Stardew Valley executable.
@@ -64,5 +111,44 @@ private string GetExecutableFileName()
? "Stardew Valley.exe"
: "StardewValley.exe";
}
+
+ /// Get the absolute path to the content folder for a given game, if found.
+ /// The absolute path to the game folder.
+ private string FindContentPath(string gamePath)
+ {
+ if (gamePath == null)
+ return null;
+
+ foreach (string relativePath in this.GetPossibleRelativeContentPaths())
+ {
+ DirectoryInfo folder = new DirectoryInfo(Path.Combine(gamePath, relativePath));
+ if (folder.Exists)
+ return folder.FullName;
+ }
+
+ return null;
+ }
+
+ /// Get the possible relative paths for the current platform.
+ private IEnumerable GetPossibleRelativeContentPaths()
+ {
+ // under game folder on most platforms
+ if (this.Platform != Platform.Mac)
+ yield return "Content";
+
+ // MacOS
+ else
+ {
+ // Steam paths
+ // - game path: StardewValley/Contents/MacOS
+ // - content: StardewValley/Contents/Resources/Content
+ yield return "../Resources/Content";
+
+ // GOG paths
+ // - game path: Stardew Valley.app/Contents/MacOS
+ // - content: Stardew Valley.app/Resources/Content
+ yield return "../../Resources/Content";
+ }
+ }
}
}
diff --git a/StardewXnbHack/Program.cs b/StardewXnbHack/Program.cs
index 7854d26..a4bfe79 100644
--- a/StardewXnbHack/Program.cs
+++ b/StardewXnbHack/Program.cs
@@ -85,18 +85,24 @@ public static void Run(Game1 game = null, string gamePath = null, FuncMIT
https://github.com/Pathoschild/StardewXnbHack
git
- 1.0.1
+ 1.0.2
net452
@@ -24,7 +24,7 @@
-
+
diff --git a/release-notes.md b/release-notes.md
index 993fd4c..48b6975 100644
--- a/release-notes.md
+++ b/release-notes.md
@@ -1,10 +1,18 @@
[← back to readme](README.md)
# Release notes
+## 1.0.2
+Released 07 December 2020.
+
+* Assets on MacOS are now unpacked into the game folder instead of resources, for consistency with other platforms.
+* Improved error if the game's content folder is missing.
+* Fixed duplicate tile index properties in some cases.
+* Fixed unpack error on MacOS with Steam.
+
## 1.0.1
Released 21 November 2020.
-* Updated TMXTile to 1.5.8 to fix `.tmx` map files losing tile index properties.
+* Fixed `.tmx` map files losing tile index properties.
## 1.0
Released 04 October 2020.