mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
239 lines
7.6 KiB
C#
239 lines
7.6 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|