Merge pull request #1532 from erri120/update-gamefinder-161

Update GameFinder to 1.6.1
This commit is contained in:
Timothy Baldridge 2021-07-11 14:32:14 -07:00 committed by GitHub
commit 13a567e705
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 41 additions and 283 deletions

View File

@ -4,6 +4,9 @@
<TargetFramework>net5.0-windows</TargetFramework>
<Platforms>x64</Platforms>
<IsPackable>false</IsPackable>
<!-- temp fix for NETSDK1151 https://github.com/dotnet/sdk/issues/17579-->
<ValidateExecutableReferencesMatchSelfContained>false</ValidateExecutableReferencesMatchSelfContained>
</PropertyGroup>
<ItemGroup>

View File

@ -1,238 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using Microsoft.Win32;
namespace Wabbajack.Common.StoreHandlers
{
public class OriginHandler
{
private AbsolutePath OriginDataPath = (AbsolutePath)@"C:\ProgramData\Origin\LocalContent";
private Extension MFSTExtension = new Extension(".mfst");
private HashSet<string> KnownMFSTs = new();
public List<OriginGame> Games = new();
private static Regex SplitRegex = new Regex("(.*)([0-9]+)(@subscription)?", RegexOptions.RightToLeft);
public bool Init()
{
try
{
if (!OriginDataPath.Exists)
return false;
KnownMFSTs = OriginDataPath.EnumerateFiles()
.Where(f => f.Extension == MFSTExtension)
.Select(f => f.FileNameWithoutExtension.ToString())
.Select(f =>
{
var result = SplitRegex.Match(f);
if (result == null) return default;
var a = result.Groups[1];
var b = result.Groups[2];
return a + ":" + b;
})
.Where(t => t != default)
.Select(t => t!)
.Where(t => !t.Contains("."))
.ToHashSet();
foreach (var known in KnownMFSTs)
{
try
{
var resp = OriginGame.GetAndCacheManifestResponse(known)
.FromJsonString<OriginGame.GameLocalDataResponse>();
Utils.Log($"Found Origin Content {resp.localizableAttributes!.displayName} ({known})");
}
catch (Exception ex)
{
Utils.Log($"Origin got {ex.Message} when loading info for {known}");
continue;
}
}
Utils.Log($"Found MFSTs from Origin: {string.Join(", ", KnownMFSTs)}");
return true;
}
catch (Exception)
{
return false;
}
}
public bool LoadAllGames()
{
try
{
foreach (var game in GameRegistry.Games)
{
var mfst = game.Value.OriginIDs.FirstOrDefault(g => KnownMFSTs.Contains(g));
if (mfst == null)
continue;
var ogame = new OriginGame(mfst, game.Key, game.Value);
Games.Add(ogame);
}
return true;
}
catch (Exception ex)
{
Utils.Log(ex.ToString());
return false;
}
}
}
public sealed class OriginGame
{
private string _mfst;
private GameMetaData _metaData;
public OriginGame(string mfst, Game game, GameMetaData metaData)
{
_mfst = mfst;
Game = game;
_metaData = metaData;
}
public Game Game { get; internal set; }
public AbsolutePath Path
{
get
{
return GetGamePath();
}
internal set
{
throw new NotImplementedException();
}
}
private AbsolutePath GetGamePath()
{
var manifestData = GetAndCacheManifestResponse(this._mfst).FromJsonString<GameLocalDataResponse>();
var platform = manifestData!.publishing!.softwareList!.software!.FirstOrDefault(a => a.softwarePlatform == "PCWIN");
var installPath = GetPathFromPlatformPath(platform!.fulfillmentAttributes!.installCheckOverride!);
return installPath;
}
internal AbsolutePath GetPathFromPlatformPath(string path, RegistryView platformView)
{
if (!path.StartsWith("["))
{
return (AbsolutePath)path;
}
var matchPath = Regex.Match(path, @"\[(.*?)\\(.*)\\(.*)\](.*)");
if (!matchPath.Success)
{
Utils.Log("Unknown path format " + path);
return default;
}
var root = matchPath.Groups[1].Value;
RegistryKey rootKey = root switch
{
"HKEY_LOCAL_MACHINE" => RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, platformView),
"HKEY_CURRENT_USER" => RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, platformView),
_ => throw new Exception("Unknown registry root entry " + root)
};
var subPath = matchPath.Groups[2].Value.Trim('\\');
var key = matchPath.Groups[3].Value;
var executable = matchPath.Groups[4].Value.Trim('\\');
var subKey = rootKey.OpenSubKey(subPath);
if (subKey == null)
{
return default;
}
var keyValue = rootKey!.OpenSubKey(subPath)!.GetValue(key);
if (keyValue == null)
{
return default;
}
return (AbsolutePath)keyValue!.ToString()!;
}
internal AbsolutePath GetPathFromPlatformPath(string path)
{
var resultPath = GetPathFromPlatformPath(path, RegistryView.Registry64);
if (resultPath == default)
{
resultPath = GetPathFromPlatformPath(path, RegistryView.Registry32);
}
return resultPath;
}
private static AbsolutePath ManifestCacheLocation(string mfst) =>
Consts.LocalAppDataPath.Combine("OriginManifestCache", mfst.Replace(":", ""));
internal static string GetAndCacheManifestResponse(string mfst)
{
var location = ManifestCacheLocation(mfst);
if (location.Exists)
{
return location.ReadAllText();
}
Utils.Log($"Getting Origin Manifest info for {mfst}");
var client = new HttpClient();
var data = client.GetStringAsync($"https://api1.origin.com/ecommerce2/public/{mfst}/en_US").Result;
location.Parent.CreateDirectory();
location.WriteAllTextAsync(data).Wait();
return data;
}
public class GameLocalDataResponse
{
public class LocalizableAttributes
{
public string? longDescription;
public string? displayName;
}
public class Publishing
{
public class Software
{
public class FulfillmentAttributes
{
public string? executePathOverride;
public string? installationDirectory;
public string? installCheckOverride;
}
public string? softwareId;
public string? softwarePlatform;
public FulfillmentAttributes? fulfillmentAttributes;
}
public class SoftwareList
{
public List<Software>? software;
}
public SoftwareList? softwareList;
}
public string? offerId;
public string? offerType;
public Publishing? publishing;
public LocalizableAttributes? localizableAttributes;
}
}
}

View File

@ -6,32 +6,26 @@ 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<StoreHandler> _instance = new(() => new StoreHandler(), isThreadSafe: true);
public static StoreHandler Instance => _instance.Value;
private static readonly Lazy<SteamHandler> _steamHandler = new(() => new SteamHandler());
public SteamHandler SteamHandler = _steamHandler.Value;
private static readonly Lazy<GOGHandler> _gogHandler = new(() => new GOGHandler());
public GOGHandler GOGHandler = _gogHandler.Value;
private static readonly Lazy<BethNetHandler> _bethNetHandler = new(() => new BethNetHandler());
public BethNetHandler BethNetHandler = _bethNetHandler.Value;
private static readonly Lazy<EGSHandler> _epicGameStoreHandler = new(() => new EGSHandler());
public EGSHandler EpicGameStoreHandler = _epicGameStoreHandler.Value;
private static readonly Lazy<OriginHandler> _originHandler = new(() => new OriginHandler());
public OriginHandler OriginHandler = _originHandler.Value;
private List<AStoreGame> _storeGames;
private static readonly Lazy<SteamHandler> SteamHandler = new(() => new SteamHandler(Logger));
private static readonly Lazy<GOGHandler> GogHandler = new(() => new GOGHandler(Logger));
private static readonly Lazy<BethNetHandler> BethNetHandler = new(() => new BethNetHandler(Logger));
private static readonly Lazy<EGSHandler> EpicGameStoreHandler = new(() => new EGSHandler(Logger));
private static readonly Lazy<OriginHandler> OriginHandler = new(() => new OriginHandler(true, true, Logger));
private readonly List<AStoreGame> _storeGames;
public Dictionary<Game, AStoreGame> Games = new();
private void FindGames<THandler, TGame>(Lazy<THandler> lazyHandler, string name)
@ -42,11 +36,7 @@ namespace Wabbajack.Common.StoreHandlers
{
var handler = lazyHandler.Value;
var res = handler.FindAllGames();
if (res.HasErrors)
{
Utils.Error($"Errors while finding Games from {name}\n{res.ErrorsToString()}");
}
if (!res) return;
foreach (var game in handler.Games)
{
@ -64,20 +54,11 @@ namespace Wabbajack.Common.StoreHandlers
{
_storeGames = new List<AStoreGame>();
FindGames<SteamHandler, SteamGame>(_steamHandler, "SteamHandler");
FindGames<GOGHandler, GOGGame>(_gogHandler, "GOGHandler");
FindGames<BethNetHandler, BethNetGame>(_bethNetHandler, "BethNetHandler");
FindGames<EGSHandler, EGSGame>(_epicGameStoreHandler, "EGSHandler");
if (OriginHandler.Init())
{
if (!OriginHandler.LoadAllGames())
Utils.Error(new StoreException("Could not load all Games from the OriginHandler, check previous error messages!"));
}
else
{
Utils.Error(new StoreException("Could not Init the OriginHandler, check previous error messages!"));
}
FindGames<SteamHandler, SteamGame>(SteamHandler, "SteamHandler");
FindGames<GOGHandler, GOGGame>(GogHandler, "GOGHandler");
FindGames<BethNetHandler, BethNetGame>(BethNetHandler, "BethNetHandler");
FindGames<EGSHandler, EGSGame>(EpicGameStoreHandler, "EGSHandler");
FindGames<OriginHandler, OriginGame>(OriginHandler, "OriginHandler");
foreach (var storeGame in _storeGames)
{
@ -87,6 +68,7 @@ namespace Wabbajack.Common.StoreHandlers
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
};
@ -106,7 +88,7 @@ namespace Wabbajack.Common.StoreHandlers
{
if (Games.TryGetValue(game, out var storeGame))
return (AbsolutePath) storeGame.Path;
return OriginHandler.Games.FirstOrDefault(x => x.Game == game)?.Path;
return null;
}
public static void Warmup()
@ -114,12 +96,19 @@ namespace Wabbajack.Common.StoreHandlers
Task.Run(() => _instance.Value).FireAndForget();
}
}
public class StoreException : Exception
{
public StoreException(string msg) : base(msg)
{
internal class StoreHandlerLogger : ILogger
{
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
Utils.Log(formatter(state, exception));
}
public bool IsEnabled(LogLevel logLevel) => true;
public IDisposable BeginScope<TState>(TState state)
{
throw new NotImplementedException();
}
}
}

View File

@ -48,10 +48,11 @@
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="GameFinder.StoreHandlers.BethNet" Version="1.5.3" />
<PackageReference Include="GameFinder.StoreHandlers.EGS" Version="1.5.3" />
<PackageReference Include="GameFinder.StoreHandlers.GOG" Version="1.5.3" />
<PackageReference Include="GameFinder.StoreHandlers.Steam" Version="1.5.3" />
<PackageReference Include="GameFinder.StoreHandlers.BethNet" Version="1.6.1" />
<PackageReference Include="GameFinder.StoreHandlers.EGS" Version="1.6.1" />
<PackageReference Include="GameFinder.StoreHandlers.GOG" Version="1.6.1" />
<PackageReference Include="GameFinder.StoreHandlers.Steam" Version="1.6.1" />
<PackageReference Include="GameFinder.StoreHandlers.Origin" Version="1.6.1" />
<PackageReference Include="Genbox.AlphaFS" Version="2.2.2.1" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.34" />
<PackageReference Include="ini-parser-netstandard" Version="2.5.2" />

View File

@ -4,6 +4,9 @@
<TargetFramework>net5.0-windows</TargetFramework>
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
<IsPackable>false</IsPackable>
<!-- temp fix for NETSDK1151 https://github.com/dotnet/sdk/issues/17579-->
<ValidateExecutableReferencesMatchSelfContained>false</ValidateExecutableReferencesMatchSelfContained>
</PropertyGroup>
<ItemGroup>