-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathBattleNetGameFactory.cs
151 lines (127 loc) · 5.27 KB
/
BattleNetGameFactory.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
using Gamelib.Core.Util;
using GameLib.Core;
using GameLib.Plugin.BattleNet.Model;
using Newtonsoft.Json;
using System.Reflection;
namespace GameLib.Plugin.BattleNet;
public static class BattleNetGameFactory
{
public static IEnumerable<BattleNetGame> GetGames(ILauncher launcher, CancellationToken cancellationToken = default)
{
var catalog = GetCatalog();
return DeserializeProductInstalls()
.AsParallel()
.WithCancellation(cancellationToken)
.Select(product => BattleNetGameBuiler(launcher, product))
.Where(game => game is not null)
.Select(game => AddLauncherId(launcher, game))
.Select(game => AddCatalogData(launcher, game, catalog))
.Select(game => AddExecutables(launcher, game))
.ToList()!;
}
/// <summary>
/// Add launcher ID to Game
/// </summary>
private static BattleNetGame AddLauncherId(ILauncher launcher, BattleNetGame game)
{
game.LauncherId = launcher.Id;
return game;
}
/// <summary>
/// Find executables within the install directory
/// </summary>
private static BattleNetGame AddExecutables(ILauncher launcher, BattleNetGame game)
{
if (launcher.LauncherOptions.SearchExecutables)
{
var executables = PathUtil.GetExecutables(game.InstallDir);
executables.AddRange(game.Executables);
game.Executables = executables.Distinct(StringComparer.OrdinalIgnoreCase).ToList();
}
return game;
}
/// <summary>
/// Load local catalog data
/// </summary>
private static BNetGames? GetCatalog()
{
var path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? ".", "Resources", "BattleNetGames.json");
if (!File.Exists(path))
{
return null;
}
try
{
var json = File.ReadAllText(path);
var catalog = JsonConvert.DeserializeObject<BNetGames>(json);
if (catalog is null)
{
throw new ApplicationException("Cannot deserialize JSON stream");
}
return catalog;
}
catch { return null; }
}
/// <summary>
/// Deserialize the BattlNet product.db
/// </summary>
private static IEnumerable<ProductInstall> DeserializeProductInstalls()
{
var productInstalls = new List<ProductInstall>();
var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Battle.net", "Agent", "product.db");
if (!File.Exists(path))
{
throw new FileNotFoundException("Configuration file not found, probably Battle.net client hasn't been started at least once.", path);
}
using var file = File.OpenRead(path);
productInstalls = ProtoBuf.Serializer.Deserialize<List<ProductInstall>>(file);
return productInstalls.Where(p => p.Uid is not "agent" and not "battle.net");
}
/// <summary>
/// Convert entry from product.db into a BattleNetGame object
/// </summary>
private static BattleNetGame BattleNetGameBuiler(ILauncher launcher, ProductInstall productInstall)
{
return new BattleNetGame()
{
Id = productInstall.Uid,
Name = Path.GetFileName(PathUtil.Sanitize(productInstall.Settings.installPath)) ?? string.Empty,
InstallDir = PathUtil.Sanitize(productInstall.Settings.installPath) ?? string.Empty,
WorkingDir = PathUtil.Sanitize(productInstall.Settings.installPath) ?? string.Empty,
InstallDate = PathUtil.GetCreationTime(productInstall.Settings.installPath) ?? DateTime.MinValue,
LaunchString = $"\"{launcher.Executable}\" --game={productInstall.productCode.ToUpper()}",
ProductCode = productInstall.productCode ?? string.Empty,
PlayRegion = productInstall.Settings.playRegion ?? string.Empty,
SpeechLanguage = productInstall.Settings.selectedSpeechLanguage ?? string.Empty,
TextLanguage = productInstall.Settings.selectedTextLanguage ?? string.Empty,
Version = productInstall.cachedProductState.baseProductState.currentVersionStr ?? string.Empty
};
}
/// <summary>
/// Get the executable and game name from the catalog
/// </summary>
private static BattleNetGame AddCatalogData(ILauncher launcher, BattleNetGame game, BNetGames? catalog = null)
{
if (catalog?.Games
.Where(g => g.InternalId == game.Id)
.FirstOrDefault(defaultValue: null) is not BNetGame catalogItem)
{
return game;
}
if (!string.IsNullOrEmpty(catalogItem.Name))
{
game.Name = catalogItem.Name;
}
if (!string.IsNullOrEmpty(catalogItem.ProductId))
{
game.ProductCode = catalogItem.ProductId;
game.LaunchString = $"\"{launcher.Executable}\" --exec=\"launch {game.ProductCode}\"";
}
game.Executables = catalogItem.Executables
.Where(e => !string.IsNullOrEmpty(e))
.Select(e => Path.Combine(game.InstallDir, e))
.ToList();
game.Executable = game.Executables.FirstOrDefault(defaultValue: string.Empty);
return game;
}
}