wabbajack/Wabbajack.Downloaders.GameFile/GameLocator.cs

193 lines
5.1 KiB
C#
Raw Normal View History

2022-10-21 20:13:49 +00:00
using System.Runtime.InteropServices;
using GameFinder.Common;
using GameFinder.RegistryUtils;
2021-09-27 12:42:46 +00:00
using GameFinder.StoreHandlers.EGS;
using GameFinder.StoreHandlers.GOG;
using GameFinder.StoreHandlers.Origin;
using GameFinder.StoreHandlers.Steam;
using Microsoft.Extensions.Logging;
using Wabbajack.DTOs;
using Wabbajack.Paths;
2022-10-21 20:13:49 +00:00
using Wabbajack.Paths.IO;
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
namespace Wabbajack.Downloaders.GameFile;
public class GameLocator : IGameLocator
2021-09-27 12:42:46 +00:00
{
2022-10-21 20:13:49 +00:00
private readonly SteamHandler _steam;
2022-10-19 22:17:25 +00:00
private readonly GOGHandler? _gog;
2022-10-21 20:13:49 +00:00
private readonly EGSHandler? _egs;
private readonly OriginHandler? _origin;
private readonly Dictionary<int, AbsolutePath> _steamGames = new();
private readonly Dictionary<long, AbsolutePath> _gogGames = new();
private readonly Dictionary<string, AbsolutePath> _egsGames = new(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<string, AbsolutePath> _originGames = new(StringComparer.OrdinalIgnoreCase);
2021-10-23 16:51:17 +00:00
private readonly Dictionary<Game, AbsolutePath> _locationCache;
private readonly ILogger<GameLocator> _logger;
public GameLocator(ILogger<GameLocator> logger)
2021-09-27 12:42:46 +00:00
{
2021-10-23 16:51:17 +00:00
_logger = logger;
2022-10-21 20:13:49 +00:00
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
2021-09-27 12:42:46 +00:00
{
2022-10-21 20:13:49 +00:00
var windowsRegistry = new WindowsRegistry();
2022-10-19 22:17:25 +00:00
2022-10-21 20:13:49 +00:00
_steam = new SteamHandler(windowsRegistry);
_gog = new GOGHandler(windowsRegistry);
_egs = new EGSHandler(windowsRegistry);
_origin = new OriginHandler();
}
else
{
_steam = new SteamHandler(null);
2022-10-15 17:18:22 +00:00
}
2022-10-19 22:17:25 +00:00
_locationCache = new Dictionary<Game, AbsolutePath>();
2022-10-21 20:13:49 +00:00
FindAllGames();
}
private void FindAllGames()
{
2022-10-19 22:17:25 +00:00
try
2022-10-15 17:18:22 +00:00
{
2022-10-21 20:13:49 +00:00
FindStoreGames(_steam, _steamGames, game => game.Path);
2022-10-19 22:17:25 +00:00
}
2022-10-21 20:13:49 +00:00
catch (Exception e)
2022-10-19 22:17:25 +00:00
{
2022-10-21 20:13:49 +00:00
_logger.LogError(e, "While finding games installed with Steam");
2021-10-23 16:51:17 +00:00
}
2021-09-27 12:42:46 +00:00
2022-10-19 22:17:25 +00:00
try
2022-10-15 17:18:22 +00:00
{
2022-10-21 20:13:49 +00:00
FindStoreGames(_gog, _gogGames, game => game.Path);
2022-10-19 22:17:25 +00:00
}
2022-10-21 20:13:49 +00:00
catch (Exception e)
2022-10-19 22:17:25 +00:00
{
2022-10-21 20:13:49 +00:00
_logger.LogError(e, "While finding games installed with GOG Galaxy");
2022-10-15 17:18:22 +00:00
}
2021-09-27 12:42:46 +00:00
2022-10-19 22:17:25 +00:00
try
2022-10-15 17:18:22 +00:00
{
2022-10-21 20:13:49 +00:00
FindStoreGames(_egs, _egsGames, game => game.InstallLocation);
2022-10-19 22:17:25 +00:00
}
2022-10-21 20:13:49 +00:00
catch (Exception e)
2022-10-19 22:17:25 +00:00
{
2022-10-21 20:13:49 +00:00
_logger.LogError(e, "While finding games installed with the Epic Games Store");
2022-10-15 17:18:22 +00:00
}
2022-10-19 22:17:25 +00:00
try
2022-10-15 17:18:22 +00:00
{
2022-10-21 20:13:49 +00:00
FindStoreGames(_origin, _originGames, game => game.InstallPath);
}
catch (Exception e)
{
_logger.LogError(e, "While finding games installed with Origin");
}
}
private void FindStoreGames<TGame, TId>(
AHandler<TGame, TId>? handler,
Dictionary<TId, AbsolutePath> paths,
Func<TGame, string> getPath)
where TGame : class
{
if (handler is null) return;
var games = handler.FindAllGamesById(out var errors);
foreach (var (id, game) in games)
{
try
{
var path = getPath(game).ToAbsolutePath();
if (!path.DirectoryExists())
{
_logger.LogError("Game does not exist: {Game}", game);
continue;
}
paths[id] = path;
_logger.LogDebug("Found {Game}", game);
}
catch (Exception e)
{
_logger.LogError(e, "While locating {Game}", game);
}
2022-10-19 22:17:25 +00:00
}
2022-10-21 20:13:49 +00:00
foreach (var error in errors)
2022-10-19 22:17:25 +00:00
{
2022-10-21 20:13:49 +00:00
_logger.LogError("{Error}", error);
2022-10-15 17:18:22 +00:00
}
2021-10-23 16:51:17 +00:00
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public AbsolutePath GameLocation(Game game)
{
if (TryFindLocation(game, out var path))
return path;
throw new Exception($"Can't find game {game}");
}
public bool IsInstalled(Game game)
{
return TryFindLocation(game, out _);
}
public bool TryFindLocation(Game game, out AbsolutePath path)
{
lock (_locationCache)
2021-09-27 12:42:46 +00:00
{
2021-10-23 16:51:17 +00:00
if (_locationCache.TryGetValue(game, out path))
return true;
if (TryFindLocationInner(game, out path))
{
_locationCache.Add(game, path);
return true;
}
2021-09-27 12:42:46 +00:00
}
2021-10-23 16:51:17 +00:00
return false;
}
private bool TryFindLocationInner(Game game, out AbsolutePath path)
{
var metaData = game.MetaData();
2022-10-15 17:18:22 +00:00
2022-10-21 20:13:49 +00:00
foreach (var id in metaData.SteamIDs)
2021-09-27 12:42:46 +00:00
{
2022-10-21 20:13:49 +00:00
if (!_steamGames.TryGetValue(id, out var found)) continue;
path = found;
return true;
2021-09-27 12:42:46 +00:00
}
2022-10-21 20:13:49 +00:00
foreach (var id in metaData.GOGIDs)
2022-10-19 17:28:07 +00:00
{
2022-10-21 20:13:49 +00:00
if (!_gogGames.TryGetValue(id, out var found)) continue;
path = found;
return true;
2021-10-23 16:51:17 +00:00
}
2022-10-21 20:13:49 +00:00
foreach (var id in metaData.EpicGameStoreIDs)
2021-10-24 04:39:57 +00:00
{
2022-10-21 20:13:49 +00:00
if (!_egsGames.TryGetValue(id, out var found)) continue;
path = found;
return true;
2021-10-24 04:39:57 +00:00
}
2022-10-19 17:28:07 +00:00
2022-10-21 20:13:49 +00:00
foreach (var id in metaData.OriginIDs)
2022-10-19 17:28:07 +00:00
{
2022-10-21 20:13:49 +00:00
if (!_originGames.TryGetValue(id, out var found)) continue;
path = found;
return true;
2022-10-19 17:28:07 +00:00
}
2021-10-23 16:51:17 +00:00
path = default;
return false;
2021-09-27 12:42:46 +00:00
}
2022-10-21 20:13:49 +00:00
}