Skip to content

Commit 17ef26a

Browse files
authored
Merge pull request #161 from halgari/master
More information for Epic Games
2 parents 35bb5c9 + e3f0fbd commit 17ef26a

File tree

4 files changed

+39
-17
lines changed

4 files changed

+39
-17
lines changed

src/GameFinder.StoreHandlers.EGS/EGSGame.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Collections.Generic;
12
using GameFinder.Common;
23
using JetBrains.Annotations;
34
using NexusMods.Paths;
@@ -11,4 +12,4 @@ namespace GameFinder.StoreHandlers.EGS;
1112
/// <param name="DisplayName"></param>
1213
/// <param name="InstallLocation"></param>
1314
[PublicAPI]
14-
public record EGSGame(EGSGameId CatalogItemId, string DisplayName, AbsolutePath InstallLocation) : IGame;
15+
public record EGSGame(EGSGameId CatalogItemId, string DisplayName, AbsolutePath InstallLocation, IReadOnlyList<string> ManifestHash) : IGame;

src/GameFinder.StoreHandlers.EGS/EGSHandler.cs

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
namespace GameFinder.StoreHandlers.EGS;
1212

1313
[UsedImplicitly]
14-
internal record ManifestFile(string CatalogItemId, string DisplayName, string InstallLocation);
14+
internal record ManifestFile(string CatalogItemId, string DisplayName, string InstallLocation, string ManifestHash, string MainGameCatalogItemId);
1515

1616
/// <summary>
1717
/// Handler for finding games installed with the Epic Games Store.
@@ -73,13 +73,38 @@ public override IEnumerable<OneOf<EGSGame, ErrorMessage>> FindAllGames()
7373
yield break;
7474
}
7575

76-
foreach (var itemFile in itemFiles)
76+
// Parse all the files
77+
var allItems = itemFiles.Select(DeserializeItem).ToList();
78+
79+
// Group by the MainGameCatalogItemId, and collect all the manifest hashes
80+
// for each game. If a game has multiple DLCs, all the DLCs will reference the
81+
// same MainGameCatalogItemId.
82+
var itemsGrouped = allItems
83+
.Where(f => f.Match(f0: static _ => true, f1: static _ => false))
84+
.Select(f => f.AsT0)
85+
.GroupBy(c => c.MainGameCatalogItemId, StringComparer.OrdinalIgnoreCase)
86+
.Select(group =>
87+
{
88+
return new EGSGame(
89+
EGSGameId.From(group.Key),
90+
group.First().DisplayName,
91+
_fileSystem.FromUnsanitizedFullPath(group.First().InstallLocation),
92+
group.Select(g => g.ManifestHash).ToArray());
93+
});
94+
95+
foreach (var game in itemsGrouped)
7796
{
78-
yield return DeserializeGame(itemFile);
97+
yield return game;
98+
}
99+
100+
foreach (var errorMessage in allItems
101+
.Where(f => f.Match(f0: static _ => false, f1: static _ => true)))
102+
{
103+
yield return errorMessage.AsT1;
79104
}
80105
}
81106

82-
private OneOf<EGSGame, ErrorMessage> DeserializeGame(AbsolutePath itemFile)
107+
private OneOf<ManifestFile, ErrorMessage> DeserializeItem(AbsolutePath itemFile)
83108
{
84109
using var stream = _fileSystem.ReadFile(itemFile);
85110

@@ -109,13 +134,7 @@ private OneOf<EGSGame, ErrorMessage> DeserializeGame(AbsolutePath itemFile)
109134
return new ErrorMessage($"Manifest {itemFile.GetFullPath()} does not have a value \"InstallLocation\"");
110135
}
111136

112-
var game = new EGSGame(
113-
EGSGameId.From(manifest.CatalogItemId),
114-
manifest.DisplayName,
115-
_fileSystem.FromUnsanitizedFullPath(manifest.InstallLocation)
116-
);
117-
118-
return game;
137+
return manifest;
119138
}
120139
catch (Exception e)
121140
{

tests/GameFinder.StoreHandlers.EGS.Tests/ArrangeHelpers.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,15 @@ private static IEnumerable<EGSGame> SetupGames(InMemoryFileSystem fs, AbsolutePa
3838
var mockData = $@"{{
3939
""CatalogItemId"": ""{catalogItemId}"",
4040
""DisplayName"": ""{displayName}"",
41-
""InstallLocation"": ""{installLocation.GetFullPath().ToEscapedString()}""
41+
""InstallLocation"": ""{installLocation.GetFullPath().ToEscapedString()}"",
42+
""MainGameCatalogItemId"": ""{catalogItemId}"",
43+
""ManifestHash"": ""{catalogItemId}_manifest""
4244
}}";
4345

4446
fs.AddDirectory(installLocation);
4547
fs.AddFile(manifestItem, mockData);
4648

47-
return new EGSGame(EGSGameId.From(catalogItemId), displayName, installLocation);
49+
return new EGSGame(EGSGameId.From(catalogItemId), displayName, installLocation, new [] { catalogItemId + "_manifest" });
4850
})
4951
.OmitAutoProperties());
5052

tests/TestUtils/AssertionHelpers.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public static void ShouldFindAllGames<TGame, TId>(
4848
var results = handler.FindAllGames().ToArray();
4949
var games = results.ShouldOnlyBeGames();
5050

51-
games.Should().Equal(expectedGames);
51+
games.Should().BeEquivalentTo(expectedGames);
5252
}
5353

5454
public static void ShouldFindAllGamesById<TGame, TId>(
@@ -62,7 +62,7 @@ public static void ShouldFindAllGamesById<TGame, TId>(
6262
errors.Should().BeEmpty();
6363

6464
results.Should().ContainKeys(expectedGames.Select(keySelector));
65-
results.Should().ContainValues(expectedGames);
65+
results.Values.Should().BeEquivalentTo(expectedGames);
6666
}
6767

6868
public static void ShouldFindAllInterfacesGames<TGame, TId>(
@@ -74,6 +74,6 @@ public static void ShouldFindAllInterfacesGames<TGame, TId>(
7474
var results = handler.FindAllInterfaceGames().ToArray();
7575
var games = results.ShouldOnlyBeGames();
7676

77-
games.Should().AllBeOfType<TGame>().Which.Should().Equal(expectedGames);
77+
games.Should().AllBeOfType<TGame>().Which.Should().BeEquivalentTo(expectedGames);
7878
}
7979
}

0 commit comments

Comments
 (0)