using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using GameFinder; using GameFinder.StoreHandlers.BethNet; using GameFinder.StoreHandlers.EGS; using GameFinder.StoreHandlers.GOG; using GameFinder.StoreHandlers.Origin; using GameFinder.StoreHandlers.Steam; using Microsoft.Extensions.Logging; namespace Wabbajack.Common.StoreHandlers { public class StoreHandler { private static readonly StoreHandlerLogger Logger = new(); private static readonly Lazy _instance = new(() => new StoreHandler(), isThreadSafe: true); public static StoreHandler Instance => _instance.Value; private static readonly Lazy SteamHandler = new(() => new SteamHandler(Logger)); private static readonly Lazy GogHandler = new(() => new GOGHandler(Logger)); private static readonly Lazy BethNetHandler = new(() => new BethNetHandler(Logger)); private static readonly Lazy EpicGameStoreHandler = new(() => new EGSHandler(Logger)); private static readonly Lazy OriginHandler = new(() => new OriginHandler(true, true, Logger)); private readonly List _storeGames; public Dictionary Games = new(); private void FindGames(Lazy lazyHandler, string name) where THandler : AStoreHandler where TGame : AStoreGame { try { var handler = lazyHandler.Value; var res = handler.FindAllGames(); if (!res) return; foreach (var game in handler.Games) { Utils.Log($"{handler.StoreType}: Found game {game} at \"{game.Path}\""); _storeGames.Add(game); } } catch (Exception e) { Utils.Error(e, $"Could not load all Games from {name}"); } } public StoreHandler() { _storeGames = new List(); FindGames(SteamHandler, "SteamHandler"); FindGames(GogHandler, "GOGHandler"); FindGames(BethNetHandler, "BethNetHandler"); FindGames(EpicGameStoreHandler, "EGSHandler"); FindGames(OriginHandler, "OriginHandler"); foreach (var storeGame in _storeGames) { IEnumerable>? enumerable = storeGame switch { SteamGame steamGame => GameRegistry.Games.Where(y => y.Value.SteamIDs?.Contains(steamGame.ID) ?? false), GOGGame gogGame => GameRegistry.Games.Where(y => y.Value.GOGIDs?.Contains(gogGame.GameID) ?? false), BethNetGame bethNetGame => GameRegistry.Games.Where(y => y.Value.BethNetID.Equals((int)bethNetGame.ID)), EGSGame egsGame => GameRegistry.Games.Where(y => y.Value.EpicGameStoreIDs.Contains(egsGame.CatalogItemId ?? string.Empty)), OriginGame originGame => GameRegistry.Games.Where(y => y.Value.OriginIDs.Contains(originGame.Id ?? string.Empty)), _ => null }; if (enumerable == null) continue; var list = enumerable.ToList(); if (list.Count == 0) continue; var game = list.First().Key; if (Games.ContainsKey(game)) continue; Games.Add(game, storeGame); } } public AbsolutePath? TryGetGamePath(Game game) { if (!Games.TryGetValue(game, out var storeGame)) return null; return (AbsolutePath)storeGame.Path; } public static void Warmup() { Task.Run(() => _instance.Value).FireAndForget(); } } internal class StoreHandlerLogger : ILogger { public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) { Utils.Log(formatter(state, exception)); } public bool IsEnabled(LogLevel logLevel) => true; public IDisposable BeginScope(TState state) { throw new NotImplementedException(); } } }