summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2019-06-17 18:51:31 -0400
committerJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2019-09-14 18:10:41 -0400
commit1a8c7345c3986acd172f91716bbf04fc7192317b (patch)
tree913761e1c3586c91cbff0c8897e81130f79e2947
parenta7544e5afb4ba7f12d248503106cc8d407c2bad1 (diff)
downloadSMAPI-1a8c7345c3986acd172f91716bbf04fc7192317b.tar.gz
SMAPI-1a8c7345c3986acd172f91716bbf04fc7192317b.tar.bz2
SMAPI-1a8c7345c3986acd172f91716bbf04fc7192317b.zip
add stardewvalley.targets support to toolkit
-rw-r--r--docs/release-notes.md1
-rw-r--r--src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs46
2 files changed, 44 insertions, 3 deletions
diff --git a/docs/release-notes.md b/docs/release-notes.md
index 6d883baf..efac8f41 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -28,6 +28,7 @@ These changes have not been released yet.
* Added `Context.IsGameLaunched` field.
* Mods are now loaded much earlier in the game launch. This lets mods intercept any content asset, but the game is not fully initialised when `Entry` is called (use the `GameLaunched` event if you need to run code when the game is initialised).
* Added separate `LogNetworkTraffic` option to make verbose logging less overwhelmingly verbose.
+ * The installer now recognises custom game paths stored in `stardewvalley.targets`, if any.
* When a mod is incompatible, the trace logs now list all detected issues instead of the first one.
* Removed all deprecated APIs.
* Removed the `Monitor.ExitGameImmediately` method.
diff --git a/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs b/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs
index 1755a7db..60c7a682 100644
--- a/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs
+++ b/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs
@@ -2,6 +2,8 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Xml.Linq;
+using System.Xml.XPath;
using StardewModdingAPI.Toolkit.Utilities;
#if SMAPI_FOR_WINDOWS
using Microsoft.Win32;
@@ -19,12 +21,18 @@ namespace StardewModdingAPI.Toolkit.Framework.GameScanning
/// <remarks>This checks default game locations, and on Windows checks the Windows registry for GOG/Steam install data. A folder is considered 'valid' if it contains the Stardew Valley executable for the current OS.</remarks>
public IEnumerable<DirectoryInfo> Scan()
{
- // get unique candidate paths
+ // get OS info
Platform platform = EnvironmentUtility.DetectPlatform();
string executableFilename = EnvironmentUtility.GetExecutableName(platform);
- IEnumerable<string> paths = this.GetDefaultInstallPaths(platform).Select(PathUtilities.NormalisePathSeparators).Distinct(StringComparer.InvariantCultureIgnoreCase);
- // get valid folders
+ // get install paths
+ IEnumerable<string> paths = this
+ .GetCustomInstallPaths(platform)
+ .Concat(this.GetDefaultInstallPaths(platform))
+ .Select(PathUtilities.NormalisePathSeparators)
+ .Distinct(StringComparer.InvariantCultureIgnoreCase);
+
+ // yield valid folders
foreach (string path in paths)
{
DirectoryInfo folder = new DirectoryInfo(path);
@@ -98,6 +106,38 @@ namespace StardewModdingAPI.Toolkit.Framework.GameScanning
}
}
+ /// <summary>Get the custom install path from the <c>stardewvalley.targets</c> file in the home directory, if any.</summary>
+ /// <param name="platform">The target platform.</param>
+ private IEnumerable<string> GetCustomInstallPaths(Platform platform)
+ {
+ // get home path
+ string homePath = Environment.GetEnvironmentVariable(platform == Platform.Windows ? "USERPROFILE" : "HOME");
+ if (string.IsNullOrWhiteSpace(homePath))
+ yield break;
+
+ // get targets file
+ FileInfo file = new FileInfo(Path.Combine(homePath, "stardewvalley.targets"));
+ if (!file.Exists)
+ yield break;
+
+ // parse file
+ XElement root;
+ try
+ {
+ using (FileStream stream = file.OpenRead())
+ root = XElement.Load(stream);
+ }
+ catch
+ {
+ yield break;
+ }
+
+ // get install path
+ XElement element = root.XPathSelectElement("//*[local-name() = 'GamePath']"); // can't use '//GamePath' due to the default namespace
+ if (!string.IsNullOrWhiteSpace(element?.Value))
+ yield return element.Value.Trim();
+ }
+
#if SMAPI_FOR_WINDOWS
/// <summary>Get the value of a key in the Windows HKLM registry.</summary>
/// <param name="key">The full path of the registry key relative to HKLM.</param>