Added BethNet StoreHandler

This commit is contained in:
erri120 2020-04-22 14:02:58 +02:00
parent 58d8d2ef20
commit 6ec0025245
No known key found for this signature in database
GPG Key ID: A8C0A18D8D4D3135
4 changed files with 235 additions and 1 deletions

View File

@ -12,6 +12,7 @@ namespace Wabbajack.Common
{
public enum Game
{
FalloutShelter,
//MO2 GAMES
Morrowind,
Oblivion,
@ -74,6 +75,9 @@ namespace Wabbajack.Common
public List<int>? SteamIDs { get; internal set; }
// to get gog ids: https://www.gogdb.org
public List<int>? GOGIDs { get; internal set; }
public int BethNetID { get; internal set; }
//for BethNet games only!
public string RegString { get; internal set; } = string.Empty;
// these are additional folders when a game installs mods outside the game folder
public List<string>? AdditionalFolders { get; internal set; }
// file to check if the game is present, useful when steamIds and gogIds dont help
@ -232,6 +236,8 @@ namespace Wabbajack.Common
NexusGameId = 100,
MO2Name = "Morrowind",
MO2ArchiveName = "morrowind",
BethNetID = 31,
RegString = @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\The Elder Scrolls III: Morrowind Game of the Year Edition",
RequiredFiles = new List<string>
{
"Morrowind.exe"

View File

@ -0,0 +1,210 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using Microsoft.Win32;
#nullable enable
namespace Wabbajack.Common.StoreHandlers
{
public class BethNetGame : AStoreGame
{
public override Game Game { get; internal set; }
public override StoreType Type { get; internal set; } = StoreType.BethNet;
}
public class BethNetHandler : AStoreHandler
{
public override StoreType Type { get; internal set; } = StoreType.BethNet;
private const string RegKey = @"SOFTWARE\WOW6432Node\bethesda softworks\Bethesda.net";
public AbsolutePath BethPath { get; set; }
private AbsolutePath Launcher => new RelativePath("BethesdaNetLauncher.exe").RelativeTo(BethPath);
private AbsolutePath GamesFolder => new RelativePath("games").RelativeTo(BethPath);
public override bool Init()
{
try
{
var key = Registry.LocalMachine.OpenSubKey(RegKey);
var pathKey = key?.GetValue("installLocation");
if (pathKey == null)
{
Utils.Error(new StoreException("Could not open the BethNetPath registry key!"));
return false;
}
var bethPath = pathKey.ToString() ?? string.Empty;
if (string.IsNullOrWhiteSpace(bethPath))
{
Utils.Error(new StoreException("Path to the BethNet Directory from registry is Null or Empty!"));
return false;
}
BethPath = (AbsolutePath)bethPath;
if (!BethPath.IsDirectory || !BethPath.Exists)
{
Utils.Error(new StoreException($"Path to the BethNet Directory from registry does not exists: {BethPath}"));
return false;
}
if (Launcher.Exists && Launcher.IsFile)
return true;
Utils.Error(new StoreException($"The BethNet Launcher could not be located: {Launcher}"));
return false;
}
catch (SecurityException se)
{
Utils.Error(se, "BethNetHandler could not read from registry!");
}
catch (UnauthorizedAccessException uae)
{
Utils.Error(uae, "BethNetHandler could not read from registry!");
}
return false;
}
public override bool LoadAllGames()
{
List<BethNetGame> possibleGames = new List<BethNetGame>();
// games folder
if (!GamesFolder.Exists)
{
Utils.Error(new StoreException($"The GamesFolder for BethNet at {GamesFolder} does not exist!"));
return false;
}
if (GamesFolder.Exists && GamesFolder.IsDirectory)
{
GamesFolder.EnumerateDirectories(false).Do(d =>
{
var files = d.EnumerateFiles();
var game = GameRegistry.Games.Values
.FirstOrDefault(g => g.RequiredFiles.All(f =>
{
var absPath = new RelativePath(f).RelativeTo(d);
return files.Contains(absPath);
}));
if (game != null)
{
possibleGames.Add(new BethNetGame
{
Game = game.Game,
ID = game.BethNetID,
Name = game.Game.ToString(),
Path = d,
Type = StoreType.BethNet
});
}
else
{
Utils.Log($"Game at {d} is not supported!");
}
});
}
possibleGames.Do(g =>
{
try
{
var regString = g.Game.MetaData().RegString;
var regKey = Registry.LocalMachine.OpenSubKey(regString);
regString = @"HKEY_LOCAL_MACHINE\" + regString;
if (regKey == null)
{
Utils.Error(new StoreException($@"Could not open registry key at {regString}"));
return;
}
var pathValue = regKey.GetValue("Path");
var uninstallStringValue = regKey.GetValue("UninstallString");
if (pathValue == null || uninstallStringValue == null)
{
Utils.Error(new StoreException($@"Could not get Value from either {regString}\Path or UninstallString"));
return;
}
var path = pathValue.ToString() ?? string.Empty;
var uninstallString = uninstallStringValue.ToString() ?? string.Empty;
if (string.IsNullOrWhiteSpace(path) || string.IsNullOrWhiteSpace(uninstallString))
{
Utils.Error(new StoreException($@"Path or UninstallString is null or empty for {regString}!"));
return;
}
path = FixRegistryValue(path);
if ((AbsolutePath)path != g.Path)
{
Utils.Error(new StoreException($"Path from registry does not equal game path: {path} != {g.Path} at {regString}"));
return;
}
var split = uninstallString.Split("\"");
if (split.Length != 3)
{
Utils.Error(new StoreException($"UninstallString at {regString} can not be split into 3 parts!"));
return;
}
var updaterPath = (AbsolutePath)split[1];
var args = split[2].Trim();
if (!updaterPath.Exists)
{
Utils.Error(new StoreException($"UpdaterPath from {regString} does not exist at {updaterPath}"));
return;
}
if (updaterPath.Parent != BethPath)
{
Utils.Error(new StoreException($"Parent of UpdatePath from {regString} is not BethPath: {updaterPath.Parent} != {BethPath}"));
return;
}
if (!args.Equals($"bethesdanet://uninstall/{g.ID}", StringComparison.InvariantCultureIgnoreCase))
{
Utils.Error(new StoreException($"Uninstall arguments from {regString} is not valid: {args}"));
return;
}
Utils.Log($"Found BethNet game \"{g.Game}\" ({g.ID}) at {g.Path}");
Games.Add(g);
}
catch (SecurityException se)
{
Utils.Error(se, "BethNetHandler could not read from registry!");
}
catch (UnauthorizedAccessException uae)
{
Utils.Error(uae, "BethNetHandler could not read from registry!");
}
});
Utils.Log($"Total number of BethNet Games found: {Games.Count}");
return Games.Count != 0;
}
private static string FixRegistryValue(string value)
{
var s = value;
if (s.StartsWith("\""))
s = s[1..];
if (s.EndsWith("\""))
s = s[..^1];
return s;
}
}
}

View File

@ -7,7 +7,8 @@ namespace Wabbajack.Common.StoreHandlers
public enum StoreType
{
STEAM,
GOG
GOG,
BethNet
}
public class StoreHandler
@ -21,6 +22,9 @@ namespace Wabbajack.Common.StoreHandlers
private static readonly Lazy<GOGHandler> _gogHandler = new Lazy<GOGHandler>(() => new GOGHandler());
public GOGHandler GOGHandler = _gogHandler.Value;
private static readonly Lazy<BethNetHandler> _bethNetHandler = new Lazy<BethNetHandler>(() => new BethNetHandler());
public BethNetHandler BethNetHandler = _bethNetHandler.Value;
public List<AStoreGame> StoreGames;
public StoreHandler()
@ -50,6 +54,18 @@ namespace Wabbajack.Common.StoreHandlers
{
Utils.Error(new StoreException("Could not Init the GOGHandler, check previous error messages!"));
}
if (BethNetHandler.Init())
{
if (BethNetHandler.LoadAllGames())
StoreGames.AddRange(BethNetHandler.Games);
else
Utils.Error(new StoreException("Could not load all Games from the BethNetHandler, check previous error messages!"));
}
else
{
Utils.Error(new StoreException("Could not Init the BethNetHandler, check previous error messages!"));
}
}
public AbsolutePath? TryGetGamePath(Game game)

View File

@ -8,6 +8,7 @@ using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using Wabbajack.Common;
using Wabbajack.Common.StoreHandlers;
using Wabbajack.Util;
namespace Wabbajack
@ -24,6 +25,7 @@ namespace Wabbajack
CLIOld.ParseOptions(Environment.GetCommandLineArgs());
if (CLIArguments.Help)
CLIOld.DisplayHelpText();
var storeHandler = new StoreHandler();
}
}
}