148 lines
4.5 KiB
C#
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>();
|
|
}
|
|
}
|