wabbajack/Wabbajack.Common/GameMetaData.cs

383 lines
14 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
2020-04-12 19:47:28 +00:00
using System.Diagnostics.CodeAnalysis;
2019-09-29 00:22:25 +00:00
using System.Linq;
using Wabbajack.Common.StoreHandlers;
2019-09-29 00:22:25 +00:00
namespace Wabbajack.Common
{
public enum Game
{
//MO2 GAMES
2019-11-18 19:31:55 +00:00
Morrowind,
2019-09-29 00:22:25 +00:00
Oblivion,
[Description("Fallout 3")]
2019-09-29 00:22:25 +00:00
Fallout3,
[Description("Fallout New Vegas")]
2019-09-29 00:22:25 +00:00
FalloutNewVegas,
[Description("Skyrim Legendary Edition")]
2019-09-29 00:22:25 +00:00
Skyrim,
2020-04-13 17:58:08 +00:00
Enderal,
[Description("Skyrim Special Edition")]
2019-09-29 00:22:25 +00:00
SkyrimSpecialEdition,
[Description("Fallout 4")]
Fallout4,
[Description("Skyrim VR")]
SkyrimVR,
2019-09-29 00:22:25 +00:00
}
2020-04-22 12:33:07 +00:00
public static class GameExtensions
{
public static GameMetaData MetaData(this Game game)
{
return GameRegistry.Games[game];
}
}
2019-09-29 00:22:25 +00:00
public class GameMetaData
{
2020-04-22 12:33:07 +00:00
public Game Game { get; internal set; }
public ModManager SupportedModManager { get; internal set; }
2020-04-22 12:33:07 +00:00
public string? MO2ArchiveName { get; internal set; }
public string? NexusName { get; internal set; }
2020-02-06 05:30:31 +00:00
// Nexus DB id for the game, used in some specific situations
public long NexusGameId { get; internal set; }
public string? MO2Name { get; internal set; }
// to get steam ids: https://steamdb.info
public List<int>? SteamIDs { get; internal set; }
2020-04-22 12:33:07 +00:00
// to get gog ids: https://www.gogdb.org
public List<int>? GOGIDs { get; internal set; }
2020-04-22 12:33:07 +00:00
// to get BethNet IDs: check the registry
2020-04-22 12:02:58 +00:00
public int BethNetID { get; internal set; }
//for BethNet games only!
public string RegString { get; internal set; } = string.Empty;
2020-04-22 12:33:07 +00:00
// file to check if the game is present, useful when steamIds and gogIds dont help
public List<string>? RequiredFiles { get; internal set; }
2020-04-22 12:33:07 +00:00
public string? MainExecutable { get; internal set; }
// Games that this game are commonly confused with, for example Skyrim SE vs Skyrim LE
public Game[] CommonlyConfusedWith { get; set; } = Array.Empty<Game>();
2020-04-22 12:33:07 +00:00
public string HumanFriendlyGameName => Game.GetDescription();
public string InstalledVersion
{
get
{
2020-04-12 19:47:28 +00:00
if (!TryGetGameLocation(out var gameLoc))
throw new GameNotInstalledException(this);
if (MainExecutable == null)
throw new NotImplementedException();
2020-04-12 19:47:28 +00:00
return FileVersionInfo.GetVersionInfo((string)gameLoc.Combine(MainExecutable)).ProductVersion;
}
}
public bool IsInstalled => TryGetGameLocation() != null;
public AbsolutePath? TryGetGameLocation()
{
return StoreHandler.Instance.TryGetGamePath(Game);
}
2020-04-12 19:47:28 +00:00
public bool TryGetGameLocation(out AbsolutePath path)
{
var ret = TryGetGameLocation();
if (ret != null)
{
path = ret.Value;
return true;
}
2020-04-22 12:33:07 +00:00
path = default;
return false;
2020-04-12 19:47:28 +00:00
}
public AbsolutePath GameLocation()
{
var ret = TryGetGameLocation();
if (ret == null) throw new ArgumentNullException();
return ret.Value;
}
2019-09-29 00:22:25 +00:00
}
public class GameNotInstalledException : Exception
{
public GameNotInstalledException(GameMetaData gameMetaData) : base($"Game {gameMetaData.Game} does not appear to be installed.")
{
}
}
public static class EnumExtensions
{
public static string GetDescription<T>(this T enumerationValue)
where T : Enum
{
var type = enumerationValue.GetType();
if(!type.IsEnum)
{
throw new ArgumentException($"{nameof(enumerationValue)} must be of Enum type", nameof(enumerationValue));
}
var memberInfo = type.GetMember(enumerationValue.ToString()!);
2020-04-22 12:33:07 +00:00
if (memberInfo.Length <= 0)
return enumerationValue.ToString()!;
2020-04-22 12:33:07 +00:00
var attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
return attrs.Length > 0 ? ((DescriptionAttribute)attrs[0]).Description : enumerationValue.ToString();
}
public static IEnumerable<T> GetAllItems<T>() where T : struct
{
return Enum.GetValues(typeof(T)).Cast<T>();
}
}
2019-09-29 00:22:25 +00:00
public class GameRegistry
{
public static GameMetaData GetByMO2ArchiveName(string gameName)
{
2020-04-22 12:33:07 +00:00
gameName = gameName.ToLower();
return Games.Values.FirstOrDefault(g => g.MO2ArchiveName?.ToLower() == gameName);
2019-09-29 00:22:25 +00:00
}
public static GameMetaData GetByNexusName(string gameName)
{
return Games.Values.FirstOrDefault(g => g.NexusName == gameName.ToLower());
}
public static GameMetaData GetBySteamID(int id)
{
return Games.Values
.FirstOrDefault(g => g.SteamIDs != null && g.SteamIDs.Count > 0 && g.SteamIDs.Any(i => i == id));
}
2020-02-11 00:30:38 +00:00
/// <summary>
/// Parse game data from an arbitrary string. Tries first via parsing as a game Enum, then by Nexus name.
/// <param nambe="someName">Name to query</param>
/// <returns>GameMetaData found</returns>
/// <exception cref="ArgumentNullException">If string could not be translated to a game</exception>
2020-04-22 12:33:07 +00:00
/// </summary>
public static GameMetaData GetByFuzzyName(string someName)
2020-02-11 00:30:38 +00:00
{
return TryGetByFuzzyName(someName) ?? throw new ArgumentNullException($"{someName} could not be translated to a game");
}
2020-02-11 00:30:38 +00:00
/// <summary>
/// Tries to parse game data from an arbitrary string. Tries first via parsing as a game Enum, then by Nexus name.
/// <param nambe="someName">Name to query</param>
/// <returns>GameMetaData if found, otherwise null</returns>
2020-04-22 12:33:07 +00:00
/// </summary>
public static GameMetaData? TryGetByFuzzyName(string someName)
{
if (Enum.TryParse(typeof(Game), someName, true, out var metadata)) return ((Game)metadata!).MetaData();
2020-02-11 00:30:38 +00:00
GameMetaData? result = GetByNexusName(someName);
2020-02-11 00:30:38 +00:00
if (result != null) return result;
result = GetByMO2ArchiveName(someName);
if (result != null) return result;
2020-05-04 12:11:53 +00:00
result = GetByMO2Name(someName);
if (result != null) return result;
2020-02-11 00:30:38 +00:00
return int.TryParse(someName, out int id) ? GetBySteamID(id) : null;
}
2020-05-04 12:11:53 +00:00
private static GameMetaData? GetByMO2Name(string gameName)
{
gameName = gameName.ToLower();
return Games.Values.FirstOrDefault(g => g.MO2Name?.ToLower() == gameName);
}
2020-04-12 19:47:28 +00:00
public static bool TryGetByFuzzyName(string someName, [MaybeNullWhen(false)] out GameMetaData gameMetaData)
{
2020-04-15 12:05:05 +00:00
var result = TryGetByFuzzyName(someName);
if (result == null)
{
gameMetaData = Games.Values.First();
return false;
}
gameMetaData = result;
return true;
2020-04-12 19:47:28 +00:00
}
public static IReadOnlyDictionary<Game, GameMetaData> Games = new Dictionary<Game, GameMetaData>
2019-09-29 00:22:25 +00:00
{
2019-11-18 19:31:55 +00:00
{
Game.Morrowind, new GameMetaData
{
SupportedModManager = ModManager.MO2,
Game = Game.Morrowind,
SteamIDs = new List<int>{22320},
2020-03-25 13:22:55 +00:00
GOGIDs = new List<int>{1440163901, 1435828767},
2019-11-18 19:31:55 +00:00
NexusName = "morrowind",
2020-02-06 21:43:30 +00:00
NexusGameId = 100,
2019-11-18 19:31:55 +00:00
MO2Name = "Morrowind",
MO2ArchiveName = "morrowind",
2020-04-22 12:02:58 +00:00
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"
},
MainExecutable = "Morrowind.exe"
2019-11-18 19:31:55 +00:00
}
},
2019-09-29 00:22:25 +00:00
{
Game.Oblivion, new GameMetaData
{
SupportedModManager = ModManager.MO2,
2019-09-29 00:22:25 +00:00
Game = Game.Oblivion,
NexusName = "oblivion",
2020-02-06 21:43:30 +00:00
NexusGameId = 101,
MO2Name = "Oblivion",
MO2ArchiveName = "oblivion",
SteamIDs = new List<int> {22330},
2020-01-08 16:25:19 +00:00
GOGIDs = new List<int>{1458058109},
RequiredFiles = new List<string>
{
"oblivion.exe"
},
MainExecutable = "Oblivion.exe"
2019-09-29 00:22:25 +00:00
}
},
{
Game.Fallout3, new GameMetaData
{
SupportedModManager = ModManager.MO2,
2019-09-29 00:22:25 +00:00
Game = Game.Fallout3,
NexusName = "fallout3",
2020-02-06 21:43:30 +00:00
NexusGameId = 120,
2020-05-09 18:02:49 +00:00
MO2Name = "Fallout 3",
2019-09-29 00:22:25 +00:00
MO2ArchiveName = "fallout3",
SteamIDs = new List<int> {22300, 22370}, // base game and GotY
GOGIDs = new List<int>{1454315831}, // GotY edition
RequiredFiles = new List<string>
{
2020-05-09 18:02:49 +00:00
"Fallout3.exe"
},
MainExecutable = "Fallout3.exe"
2019-09-29 00:22:25 +00:00
}
},
{
Game.FalloutNewVegas, new GameMetaData
{
SupportedModManager = ModManager.MO2,
2019-09-29 00:22:25 +00:00
Game = Game.FalloutNewVegas,
NexusName = "newvegas",
2020-02-06 21:43:30 +00:00
NexusGameId = 130,
2019-09-29 00:22:25 +00:00
MO2Name = "New Vegas",
MO2ArchiveName = "falloutnv",
2020-01-07 10:20:34 +00:00
SteamIDs = new List<int> {22380, 22490}, // normal and RU version
2020-01-08 16:25:19 +00:00
GOGIDs = new List<int>{1454587428},
RequiredFiles = new List<string>
{
"FalloutNV.exe"
},
MainExecutable = "FalloutNV.exe"
2019-09-29 00:22:25 +00:00
}
},
{
Game.Skyrim, new GameMetaData
{
SupportedModManager = ModManager.MO2,
2019-09-29 00:22:25 +00:00
Game = Game.Skyrim,
NexusName = "skyrim",
2020-02-06 21:43:30 +00:00
NexusGameId = 110,
2019-09-29 00:22:25 +00:00
MO2Name = "Skyrim",
MO2ArchiveName = "skyrim",
SteamIDs = new List<int> {72850},
RequiredFiles = new List<string>
{
"tesv.exe"
},
MainExecutable = "TESV.exe",
CommonlyConfusedWith = new [] {Game.SkyrimSpecialEdition, Game.SkyrimVR}
2019-09-29 00:22:25 +00:00
}
},
{
Game.SkyrimSpecialEdition, new GameMetaData
{
SupportedModManager = ModManager.MO2,
2019-09-29 00:22:25 +00:00
Game = Game.SkyrimSpecialEdition,
NexusName = "skyrimspecialedition",
2020-02-06 05:30:31 +00:00
NexusGameId = 1704,
2019-09-29 00:22:25 +00:00
MO2Name = "Skyrim Special Edition",
MO2ArchiveName = "skyrimse",
SteamIDs = new List<int> {489830},
RequiredFiles = new List<string>
{
"SkyrimSE.exe"
},
MainExecutable = "SkyrimSE.exe",
CommonlyConfusedWith = new []{Game.Skyrim, Game.SkyrimVR}
2019-09-29 00:22:25 +00:00
}
},
{
Game.Fallout4, new GameMetaData
{
SupportedModManager = ModManager.MO2,
2019-09-29 00:22:25 +00:00
Game = Game.Fallout4,
NexusName = "fallout4",
2020-02-06 21:43:30 +00:00
NexusGameId = 1151,
2019-09-29 00:22:25 +00:00
MO2Name = "Fallout 4",
MO2ArchiveName = "fallout4",
SteamIDs = new List<int> {377160},
RequiredFiles = new List<string>
{
"Fallout4.exe"
},
MainExecutable = "Fallout4.exe"
2019-09-29 00:22:25 +00:00
}
},
{
Game.SkyrimVR, new GameMetaData
{
SupportedModManager = ModManager.MO2,
Game = Game.SkyrimVR,
NexusName = "skyrimspecialedition",
2020-02-06 21:43:30 +00:00
NexusGameId = 1704,
MO2Name = "Skyrim VR",
MO2ArchiveName = "skyrimse",
SteamIDs = new List<int> {611670},
RequiredFiles = new List<string>
{
"SkyrimVR.exe"
},
MainExecutable = "SkyrimVR.exe",
CommonlyConfusedWith = new []{Game.Skyrim, Game.SkyrimSpecialEdition}
}
},
2020-04-15 12:05:05 +00:00
{
Game.Enderal, new GameMetaData
{
SupportedModManager = ModManager.MO2,
Game = Game.Enderal,
NexusName = "enderal",
MO2Name = "Enderal",
MO2ArchiveName = "enderal",
SteamIDs = new List<int>{1027920, 933480},
2020-04-15 12:05:05 +00:00
RequiredFiles = new List<string>
{
"TESV.exe"
},
MainExecutable = "TESV.exe"
}
2019-09-29 00:22:25 +00:00
}
};
2020-02-11 00:30:38 +00:00
2019-09-29 00:22:25 +00:00
}
}