mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Merge pull request #1532 from erri120/update-gamefinder-161
Update GameFinder to 1.6.1
This commit is contained in:
commit
13a567e705
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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" />
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user