diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs | 36 | ||||
-rw-r--r-- | src/SMAPI.Toolkit/Framework/GameScanning/SteamLibraryCollection.cs | 47 | ||||
-rw-r--r-- | src/SMAPI.Toolkit/SMAPI.Toolkit.csproj | 1 |
3 files changed, 84 insertions, 0 deletions
diff --git a/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs b/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs index 8e1538a5..8e24dcdf 100644 --- a/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs +++ b/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs @@ -9,6 +9,7 @@ using StardewModdingAPI.Toolkit.Utilities; using System.Reflection; #if SMAPI_FOR_WINDOWS using Microsoft.Win32; +using VdfParser; #endif namespace StardewModdingAPI.Toolkit.Framework.GameScanning @@ -158,7 +159,14 @@ namespace StardewModdingAPI.Toolkit.Framework.GameScanning // via Steam library path string? steamPath = this.GetCurrentUserRegistryValue(@"Software\Valve\Steam", "SteamPath"); if (steamPath != null) + { yield return Path.Combine(steamPath.Replace('/', '\\'), @"steamapps\common\Stardew Valley"); + + // Check for Steam libraries in other locations + string? path = this.GetPathFromSteamLibrary(steamPath); + if (!string.IsNullOrWhiteSpace(path)) + yield return path; + } #endif // default GOG/Steam paths @@ -243,6 +251,34 @@ namespace StardewModdingAPI.Toolkit.Framework.GameScanning using (openKey) 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) + { + string stardewAppId = "413150"; + if (steamPath != null) + { + string? libraryFoldersPath = Path.Combine(steamPath.Replace('/', '\\'), "steamapps\\libraryfolders.vdf"); + using FileStream fs = File.OpenRead(libraryFoldersPath); + VdfDeserializer deserializer = new VdfDeserializer(); + SteamLibraryCollection libraries = deserializer.Deserialize<SteamLibraryCollection>(fs); + if (libraries.libraryfolders != null) + { + var stardewLibrary = libraries.libraryfolders.FirstOrDefault(f => + { + var apps = f.Value?.apps; + return apps != null && apps.Any(a => a.Key.Equals(stardewAppId)); + }); + if (stardewLibrary.Value?.path != null) + { + return Path.Combine(stardewLibrary.Value.path.Replace("\\\\", "\\"), @"steamapps\common\Stardew Valley"); + } + } + } + return null; + } #endif } } diff --git a/src/SMAPI.Toolkit/Framework/GameScanning/SteamLibraryCollection.cs b/src/SMAPI.Toolkit/Framework/GameScanning/SteamLibraryCollection.cs new file mode 100644 index 00000000..7a186f69 --- /dev/null +++ b/src/SMAPI.Toolkit/Framework/GameScanning/SteamLibraryCollection.cs @@ -0,0 +1,47 @@ +#if SMAPI_FOR_WINDOWS +using System.Collections.Generic; + +namespace StardewModdingAPI.Toolkit.Framework.GameScanning +{ +#pragma warning disable IDE1006 // Model requires lowercase naming. +#pragma warning disable CS8618 // Required for model. + /// <summary>Model for Steam's libraryfolders.vdf.</summary> + public class SteamLibraryCollection + { + /// <summary>Each entry identifies a different location that part of the Steam games library is installed to.</summary> + public LibraryFolders<int, LibraryFolder> libraryfolders { get; set; } + } + + /// <summary>A collection of LibraryFolders. Like a dictionary, but has contentstatsid used as an index also.</summary> + /// <typeparam name="TKey"></typeparam> + /// <typeparam name="TValue"></typeparam> +#pragma warning disable CS8714 // Required for model. + public class LibraryFolders<TKey, TValue> : Dictionary<TKey, TValue> +#pragma warning restore CS8714 + { + /// <summary>Index of the library, starting from "0".</summary> + public string contentstatsid { get; set; } + } + + /// <summary>A Steam library folder, containing information on the location and size of games installed there.</summary> + public class LibraryFolder + { + /// <summary>The escaped path to this Steam library folder. There will be a steam.exe here, but this may not be the one the player generally launches.</summary> + public string path { get; set; } + /// <summary>Label for the library, or ""</summary> + public string label { get; set; } + /// <summary>~19-digit identifier.</summary> + public string contentid { get; set; } + /// <summary>Size of the library in bytes. May show 0 when size is non-zero.</summary> + public string totalsize { get; set; } + /// <summary>Used for downloads.</summary> + public string update_clean_bytes_tally { get; set; } + /// <summary>Normally "0".</summary> + public string time_last_update_corruption { get; set; } + /// <summary>List of Steam app IDs, and their current size in bytes.</summary> + public Dictionary<string, string> apps { get; set; } + } +#pragma warning restore IDE1006 +#pragma warning restore CS8618 +} +#endif diff --git a/src/SMAPI.Toolkit/SMAPI.Toolkit.csproj b/src/SMAPI.Toolkit/SMAPI.Toolkit.csproj index 7b79105f..411fd469 100644 --- a/src/SMAPI.Toolkit/SMAPI.Toolkit.csproj +++ b/src/SMAPI.Toolkit/SMAPI.Toolkit.csproj @@ -14,6 +14,7 @@ <PackageReference Include="Pathoschild.Http.FluentClient" Version="4.1.1" /> <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="VdfConverter" Version="1.0.3" /> </ItemGroup> <ItemGroup> |