Merge pull request #875 from pizzaoverhead/steamLibrarySupport

Find installs in alternate Steam library locations
This commit is contained in:
Jesse Plamondon-Willard 2022-10-08 21:33:26 -04:00 committed by GitHub
commit fce1b1bd0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 2 deletions

View File

@ -154,7 +154,7 @@ foreach ($folder in $folders) {
cp -Recurse "$smapiBin/i18n" "$bundlePath/smapi-internal" cp -Recurse "$smapiBin/i18n" "$bundlePath/smapi-internal"
# bundle smapi-internal # bundle smapi-internal
foreach ($name in @("0Harmony.dll", "0Harmony.xml", "Mono.Cecil.dll", "Mono.Cecil.Mdb.dll", "Mono.Cecil.Pdb.dll", "MonoMod.Common.dll", "Newtonsoft.Json.dll", "Pathoschild.Http.Client.dll", "Pintail.dll", "TMXTile.dll", "SMAPI.Toolkit.dll", "SMAPI.Toolkit.pdb", "SMAPI.Toolkit.xml", "SMAPI.Toolkit.CoreInterfaces.dll", "SMAPI.Toolkit.CoreInterfaces.pdb", "SMAPI.Toolkit.CoreInterfaces.xml", "System.Net.Http.Formatting.dll")) { foreach ($name in @("0Harmony.dll", "0Harmony.xml", "Mono.Cecil.dll", "Mono.Cecil.Mdb.dll", "Mono.Cecil.Pdb.dll", "MonoMod.Common.dll", "Newtonsoft.Json.dll", "Pathoschild.Http.Client.dll", "Pintail.dll", "TMXTile.dll", "SMAPI.Toolkit.dll", "SMAPI.Toolkit.pdb", "SMAPI.Toolkit.xml", "SMAPI.Toolkit.CoreInterfaces.dll", "SMAPI.Toolkit.CoreInterfaces.pdb", "SMAPI.Toolkit.CoreInterfaces.xml", "System.Net.Http.Formatting.dll", "VdfConverter.dll")) {
cp "$smapiBin/$name" "$bundlePath/smapi-internal" cp "$smapiBin/$name" "$bundlePath/smapi-internal"
} }

View File

@ -9,6 +9,7 @@ using StardewModdingAPI.Toolkit.Utilities;
using System.Reflection; using System.Reflection;
#if SMAPI_FOR_WINDOWS #if SMAPI_FOR_WINDOWS
using Microsoft.Win32; using Microsoft.Win32;
using VdfParser;
#endif #endif
namespace StardewModdingAPI.Toolkit.Framework.GameScanning namespace StardewModdingAPI.Toolkit.Framework.GameScanning
@ -23,6 +24,9 @@ namespace StardewModdingAPI.Toolkit.Framework.GameScanning
/// <summary>The current OS.</summary> /// <summary>The current OS.</summary>
private readonly Platform Platform; private readonly Platform Platform;
/// <summary>The Steam app ID for Stardew Valley.</summary>
private const string SteamAppId = "413150";
/********* /*********
** Public methods ** Public methods
@ -145,7 +149,7 @@ namespace StardewModdingAPI.Toolkit.Framework.GameScanning
#if SMAPI_FOR_WINDOWS #if SMAPI_FOR_WINDOWS
IDictionary<string, string> registryKeys = new Dictionary<string, string> IDictionary<string, string> registryKeys = new Dictionary<string, string>
{ {
[@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 413150"] = "InstallLocation", // Steam [@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App " + GameScanner.SteamAppId] = "InstallLocation", // Steam
[@"SOFTWARE\WOW6432Node\GOG.com\Games\1453375253"] = "PATH", // GOG on 64-bit Windows [@"SOFTWARE\WOW6432Node\GOG.com\Games\1453375253"] = "PATH", // GOG on 64-bit Windows
}; };
foreach (var pair in registryKeys) foreach (var pair in registryKeys)
@ -158,7 +162,15 @@ namespace StardewModdingAPI.Toolkit.Framework.GameScanning
// via Steam library path // via Steam library path
string? steamPath = this.GetCurrentUserRegistryValue(@"Software\Valve\Steam", "SteamPath"); string? steamPath = this.GetCurrentUserRegistryValue(@"Software\Valve\Steam", "SteamPath");
if (steamPath != null) if (steamPath != null)
{
// conventional path
yield return Path.Combine(steamPath.Replace('/', '\\'), @"steamapps\common\Stardew Valley"); yield return Path.Combine(steamPath.Replace('/', '\\'), @"steamapps\common\Stardew Valley");
// from Steam's .vdf file
string? path = this.GetPathFromSteamLibrary(steamPath);
if (!string.IsNullOrWhiteSpace(path))
yield return path;
}
#endif #endif
// default GOG/Steam paths // default GOG/Steam paths
@ -243,6 +255,42 @@ namespace StardewModdingAPI.Toolkit.Framework.GameScanning
using (openKey) using (openKey)
return (string?)openKey.GetValue(name); return (string?)openKey.GetValue(name);
} }
/// <summary>Get the game directory path from alternative Steam library locations.</summary>
/// <param name="steamPath">The full path to the directory containing steam.exe.</param>
/// <returns>The game directory, if found.</returns>
private string? GetPathFromSteamLibrary(string? steamPath)
{
if (steamPath == null)
return null;
// get raw .vdf data
string libraryFoldersPath = Path.Combine(steamPath.Replace('/', '\\'), "steamapps\\libraryfolders.vdf");
using FileStream fileStream = File.OpenRead(libraryFoldersPath);
VdfDeserializer deserializer = new();
dynamic libraries = deserializer.Deserialize(fileStream);
if (libraries?.libraryfolders is null)
return null;
// get path from Stardew Valley app (if any)
foreach (dynamic pair in libraries.libraryfolders)
{
dynamic library = pair.Value;
foreach (dynamic app in library.apps)
{
string key = app.Key;
if (key == GameScanner.SteamAppId)
{
string path = library.path;
return Path.Combine(path.Replace("\\\\", "\\"), "steamapps", "common", "Stardew Valley");
}
}
}
return null;
}
#endif #endif
} }
} }

View File

@ -14,6 +14,7 @@
<PackageReference Include="Pathoschild.Http.FluentClient" Version="4.2.0" /> <PackageReference Include="Pathoschild.Http.FluentClient" Version="4.2.0" />
<PackageReference Include="System.Management" Version="5.0.0" Condition="'$(OS)' == 'Windows_NT'" /> <PackageReference Include="System.Management" Version="5.0.0" Condition="'$(OS)' == 'Windows_NT'" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" Condition="'$(OS)' == 'Windows_NT'" /> <PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" Condition="'$(OS)' == 'Windows_NT'" />
<PackageReference Include="VdfConverter" Version="1.0.3" Condition="'$(OS)' == 'Windows_NT'" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>