using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.Win32;
namespace Wabbajack.Common
{
[DebuggerDisplay("{Name}")]
public class SteamGame
{
public int AppId;
public string Name;
public string InstallDir;
public Game? Game;
}
///
/// Class for all Steam operations
///
public class SteamHandler
{
private static readonly Lazy instance = new Lazy(
() => new SteamHandler(true),
isThreadSafe: true);
public static SteamHandler Instance => instance.Value;
private const string SteamRegKey = @"Software\Valve\Steam";
///
/// Path to the Steam folder
///
public string SteamPath { get; internal set; }
///
/// HashSet of all known Steam Libraries
///
public HashSet InstallFolders { get; internal set; }
///
/// HashSet of all known SteamGames
///
public HashSet Games { get; internal set; }
private string SteamConfig => Path.Combine(SteamPath, "config", "config.vdf");
public SteamHandler(bool init)
{
var steamKey = Registry.CurrentUser.OpenSubKey(SteamRegKey);
SteamPath = steamKey?.GetValue("SteamPath").ToString();
if(!init) return;
LoadInstallFolders();
LoadAllSteamGames();
}
///
/// Finds the installation path of a Steam game by ID
///
/// ID of the Steam game
///
public string GetGamePathById(int id)
{
return Games.FirstOrDefault(f => f.AppId == id)?.InstallDir;
}
///
/// Reads the config file and adds all found installation folders to the HashSet
///
public void LoadInstallFolders()
{
var paths = new HashSet();
File.ReadLines(SteamConfig, Encoding.UTF8).Do(l =>
{
if (!l.Contains("BaseInstallFolder_")) return;
var s = GetVdfValue(l);
s = Path.Combine(s, "steamapps");
paths.Add(s);
});
InstallFolders = paths;
}
///
/// Enumerates through all Steam Libraries to find and read all .afc files, adding the found game
/// to the HashSet
///
public void LoadAllSteamGames()
{
var games = new HashSet();
InstallFolders.Do(p =>
{
Directory.EnumerateFiles(p, "*.acf", SearchOption.TopDirectoryOnly).Do(f =>
{
var steamGame = new SteamGame();
File.ReadAllLines(f, Encoding.UTF8).Do(l =>
{
if(l.Contains("\"appid\""))
steamGame.AppId = int.Parse(GetVdfValue(l));
if (l.Contains("\"name\""))
steamGame.Name = GetVdfValue(l);
if (l.Contains("\"installdir\""))
steamGame.InstallDir = Path.Combine(p, "common", GetVdfValue(l));
});
steamGame.Game = GameRegistry.Games.Values
.FirstOrDefault(g =>
g.SteamIDs.Contains(steamGame.AppId)
&&
g.RequiredFiles.TrueForAll(s => File.Exists(Path.Combine(steamGame.InstallDir, s)))
)?.Game;
games.Add(steamGame);
});
});
Games = games;
}
private static string GetVdfValue(string line)
{
var trim = line.Trim('\t').Replace("\t", "");
string[] s = trim.Split('\"');
return s[3].Replace("\\\\", "\\");
}
}
}