Files

148 lines
4.5 KiB
C#

using System.Text.RegularExpressions;
namespace gregExtractor;
public static class SteamLocator
{
public static string TryFindDataCenterDirectory()
{
return TryFindGameDirectory("Data Center");
}
public static string TryFindGameDirectory(string gameFolderName)
{
if (string.IsNullOrWhiteSpace(gameFolderName))
return string.Empty;
foreach (string library in EnumerateSteamLibraryRoots())
{
string candidate = Path.Combine(library, "steamapps", "common", gameFolderName);
if (!Directory.Exists(candidate))
continue;
if (File.Exists(Path.Combine(candidate, "GameAssembly.dll"))
|| Directory.Exists(Path.Combine(candidate, "MelonLoader")))
{
return candidate;
}
}
return string.Empty;
}
public static string TryFindIl2CppAssembliesDirectory(string gameFolderName = "Data Center")
{
string gameDir = TryFindGameDirectory(gameFolderName);
if (string.IsNullOrWhiteSpace(gameDir))
return string.Empty;
string[] candidates =
{
Path.Combine(gameDir, "MelonLoader", "Il2CppAssemblies"),
Path.Combine(gameDir, "Il2CppAssemblies"),
};
foreach (string candidate in candidates)
{
if (Directory.Exists(candidate) && File.Exists(Path.Combine(candidate, "Assembly-CSharp.dll")))
return candidate;
}
return string.Empty;
}
private static IEnumerable<string> EnumerateSteamLibraryRoots()
{
var roots = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
string pf86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
string pf = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
string[] defaults =
{
Path.Combine(pf86, "Steam"),
Path.Combine(pf, "Steam"),
};
foreach (string root in defaults)
{
if (Directory.Exists(root))
roots.Add(root);
}
foreach (string installPath in ReadSteamInstallPathsFromRegistry())
{
if (Directory.Exists(installPath))
roots.Add(installPath);
}
var libraries = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (string steamRoot in roots)
{
libraries.Add(steamRoot);
string vdfPath = Path.Combine(steamRoot, "steamapps", "libraryfolders.vdf");
if (!File.Exists(vdfPath))
continue;
string vdf = File.ReadAllText(vdfPath);
foreach (string parsedLibrary in ParseLibraryFolders(vdf))
{
if (Directory.Exists(parsedLibrary))
libraries.Add(parsedLibrary);
}
}
return libraries;
}
private static IEnumerable<string> ParseLibraryFolders(string vdfContent)
{
if (string.IsNullOrWhiteSpace(vdfContent))
yield break;
foreach (Match match in Regex.Matches(vdfContent, "\"path\"\\s*\"(?<path>[^\"]+)\"", RegexOptions.IgnoreCase))
{
string value = match.Groups["path"].Value.Replace("\\\\", "\\");
if (!string.IsNullOrWhiteSpace(value))
yield return value;
}
foreach (Match match in Regex.Matches(vdfContent, "\"\\d+\"\\s*\"(?<path>[A-Za-z]:\\\\[^\"]+)\"", RegexOptions.IgnoreCase))
{
string value = match.Groups["path"].Value.Replace("\\\\", "\\");
if (!string.IsNullOrWhiteSpace(value))
yield return value;
}
}
private static IEnumerable<string> ReadSteamInstallPathsFromRegistry()
{
if (!OperatingSystem.IsWindows())
return Array.Empty<string>();
const string keyPath = @"SOFTWARE\WOW6432Node\Valve\Steam";
const string keyPath64 = @"SOFTWARE\Valve\Steam";
return ReadRegistryPath(keyPath).Concat(ReadRegistryPath(keyPath64));
}
private static IEnumerable<string> ReadRegistryPath(string keyPath)
{
if (!OperatingSystem.IsWindows())
return Array.Empty<string>();
try
{
using var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(keyPath);
if (key?.GetValue("InstallPath") is string installPath && !string.IsNullOrWhiteSpace(installPath))
return new[] { installPath };
}
catch
{
}
return Array.Empty<string>();
}
}