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 Lazy _instance = new(() => new StoreHandler(), isThreadSafe: true); public static StoreHandler Instance => _instance.Value; private static readonly Lazy SteamHandler = new(() => new SteamHandler(new StoreHandlerLogger("Steam"))); private static readonly Lazy GogHandler = new(() => new GOGHandler(new StoreHandlerLogger("GOG"))); private static readonly Lazy BethNetHandler = new(() => new BethNetHandler(new StoreHandlerLogger("BethNet"))); private static readonly Lazy EpicGameStoreHandler = new(() => new EGSHandler(new StoreHandlerLogger("EGS"))); private static readonly Lazy OriginHandler = new(() => new OriginHandler(true, true, new StoreHandlerLogger("Origin"))); 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 { private readonly string _name; public StoreHandlerLogger(string name) { _name = name; } public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) { Utils.Log($"{_name}: {formatter(state, exception)}"); } public bool IsEnabled(LogLevel logLevel) => true; public IDisposable BeginScope(TState state) { throw new NotImplementedException(); } } }