Skip to content

Commit efa23bd

Browse files
committed
Include DLC information for GOG and Heroic
1 parent 1d176a8 commit efa23bd

File tree

7 files changed

+41
-13
lines changed

7 files changed

+41
-13
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com) and this p
88

99
## [Released](https://github.com/erri120/GameFinder/releases)
1010

11+
## [4.9.0](https://github.com/erri120/GameFinder/compare/v4.8.0...v4.9.0) - 2025-07-20
12+
13+
- GOG: parse parent game ID for DLCs.
14+
- Heroic: parse installed DLCs.
15+
1116
## [4.8.0](https://github.com/erri120/GameFinder/compare/v4.7.3...v4.8.0) - 2025-06-23
1217

1318
- EGS: [#161](https://github.com/erri120/GameFinder/pull/161) by @[halgari](https://github.com/halgari)

src/GameFinder.Launcher.Heroic/DTOs/Json.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ internal record Installed(
1111
[property: JsonPropertyName("is_dlc")] bool IsDlc,
1212
[property: JsonPropertyName("version")] string? Version,
1313
[property: JsonPropertyName("appName")] string AppName,
14-
[property: JsonPropertyName("installedDLCs")] IReadOnlyList<object> InstalledDLCs,
14+
[property: JsonPropertyName("installedDLCs")] IReadOnlyList<string> InstalledDLCs,
1515
[property: JsonPropertyName("language")] string Language,
1616
[property: JsonPropertyName("versionEtag")] string VersionEtag,
1717
[property: JsonPropertyName("buildId")] string BuildId,

src/GameFinder.Launcher.Heroic/HeroicGOGGame.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Collections.Generic;
22
using System.Runtime.InteropServices;
3+
using GameFinder.Common;
34
using GameFinder.StoreHandlers.GOG;
45
using GameFinder.Wine;
56
using JetBrains.Annotations;
@@ -17,7 +18,8 @@ public record HeroicGOGGame(
1718
AbsolutePath Path,
1819
ulong BuildId,
1920
WineData? WineData,
20-
OSPlatform Platform) : GOGGame(Id, Name, Path, BuildId)
21+
OSPlatform Platform,
22+
IReadOnlyList<GOGGameId> InstalledDLCs) : IGame
2123
{
2224
/// <summary>
2325
/// Gets the wine prefix, if any.

src/GameFinder.Launcher.Heroic/HeroicGOGHandler.cs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
namespace GameFinder.Launcher.Heroic;
1818

1919
[PublicAPI]
20-
public class HeroicGOGHandler : AHandler<GOGGame, GOGGameId>
20+
public class HeroicGOGHandler : AHandler<HeroicGOGGame, GOGGameId>
2121
{
2222
private readonly IFileSystem _fileSystem;
2323
private readonly ILogger _logger;
@@ -39,13 +39,13 @@ public HeroicGOGHandler(IFileSystem fileSystem, ILogger logger)
3939
}
4040

4141
/// <inheritdoc/>
42-
public override Func<GOGGame, GOGGameId> IdSelector { get; } = static game => game.Id;
42+
public override Func<HeroicGOGGame, GOGGameId> IdSelector { get; } = static game => game.Id;
4343

4444
/// <inheritdoc/>
4545
public override IEqualityComparer<GOGGameId>? IdEqualityComparer => null;
4646

4747
/// <inheritdoc/>
48-
public override IEnumerable<OneOf<GOGGame, ErrorMessage>> FindAllGames()
48+
public override IEnumerable<OneOf<HeroicGOGGame, ErrorMessage>> FindAllGames()
4949
{
5050
var configDirectory = FindConfigDirectory(_fileSystem)
5151
.FirstOrDefault(path => path.DirectoryExists());
@@ -72,7 +72,7 @@ public override IEnumerable<OneOf<GOGGame, ErrorMessage>> FindAllGames()
7272
}
7373

7474
[RequiresUnreferencedCode("Calls System.Text.Json.JsonSerializer.Deserialize<TValue>(Stream, JsonSerializerOptions)")]
75-
internal IEnumerable<OneOf<GOGGame, ErrorMessage>> ParseInstalledJsonFile(AbsolutePath path, AbsolutePath configPath)
75+
internal IEnumerable<OneOf<HeroicGOGGame, ErrorMessage>> ParseInstalledJsonFile(AbsolutePath path, AbsolutePath configPath)
7676
{
7777
using var stream = path.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
7878
var root = JsonSerializer.Deserialize<DTOs.Root>(stream, JsonSerializerOptions);
@@ -84,7 +84,7 @@ internal IEnumerable<OneOf<GOGGame, ErrorMessage>> ParseInstalledJsonFile(Absolu
8484

8585
foreach (var installed in root.Installed)
8686
{
87-
OneOf<GOGGame, ErrorMessage> res;
87+
OneOf<HeroicGOGGame, ErrorMessage> res;
8888
try
8989
{
9090
res = Parse(installed, configPath, path.FileSystem);
@@ -99,7 +99,7 @@ internal IEnumerable<OneOf<GOGGame, ErrorMessage>> ParseInstalledJsonFile(Absolu
9999
}
100100

101101
[RequiresUnreferencedCode("Calls GameFinder.Launcher.Heroic.HeroicGOGHandler.GetWineData(Installed, AbsolutePath, Int64)")]
102-
internal OneOf<GOGGame, ErrorMessage> Parse(
102+
internal OneOf<HeroicGOGGame, ErrorMessage> Parse(
103103
DTOs.Installed installed,
104104
AbsolutePath configPath,
105105
IFileSystem fileSystem)
@@ -136,8 +136,17 @@ internal OneOf<GOGGame, ErrorMessage> Parse(
136136
}
137137
}
138138

139+
var installedDLCs = new List<GOGGameId>();
140+
foreach (var sRawId in installed.InstalledDLCs)
141+
{
142+
if (long.TryParse(sRawId, NumberStyles.Integer, CultureInfo.InvariantCulture, out var rawId))
143+
{
144+
installedDLCs.Add(GOGGameId.From(rawId));
145+
}
146+
}
147+
139148
var path = fileSystem.FromUnsanitizedFullPath(installed.InstallPath);
140-
return new HeroicGOGGame(GOGGameId.From(id), installed.AppName, path, buildId, wineData, installedPlatform);
149+
return new HeroicGOGGame(GOGGameId.From(id), installed.AppName, path, buildId, wineData, installedPlatform, installedDLCs);
141150
}
142151

143152
[RequiresUnreferencedCode("Calls System.Text.Json.JsonSerializer.Deserialize<TValue>(JsonSerializerOptions)")]

src/GameFinder.StoreHandlers.GOG/GOGGame.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using GameFinder.Common;
23
using JetBrains.Annotations;
34
using NexusMods.Paths;
@@ -8,4 +9,4 @@ namespace GameFinder.StoreHandlers.GOG;
89
/// Represents a game installed with GOG Galaxy.
910
/// </summary>
1011
[PublicAPI]
11-
public record GOGGame(GOGGameId Id, string Name, AbsolutePath Path, ulong BuildId) : IGame;
12+
public record GOGGame(GOGGameId Id, string Name, AbsolutePath Path, ulong BuildId, Nullable<GOGGameId> ParentGameId = null) : IGame;

src/GameFinder.StoreHandlers.GOG/GOGHandler.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,21 @@ private OneOf<GOGGame, ErrorMessage> ParseSubKey(IRegistryKey gogKey, string sub
120120
return new ErrorMessage($"The value \"buildId\" of {subKey.GetName()} is not a number: \"{sBuildId}\"");
121121
}
122122

123+
Nullable<GOGGameId> parentGameId = null;
124+
if (subKey.TryGetString("dependsOn", out var dependsOn))
125+
{
126+
if (long.TryParse(dependsOn, NumberStyles.Integer, CultureInfo.InvariantCulture, out var rawParentGameId))
127+
{
128+
parentGameId = GOGGameId.From(rawParentGameId);
129+
}
130+
}
131+
123132
var game = new GOGGame(
124133
GOGGameId.From(idResult.AsT0),
125134
name,
126135
_fileSystem.FromUnsanitizedFullPath(path),
127-
buildId
136+
buildId,
137+
parentGameId
128138
);
129139

130140
return game;

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public static IEnumerable<GOGGame> SetupGames(IFileSystem fileSystem, InMemoryRe
1818
var fixture = new Fixture();
1919

2020
fixture.Customize<GOGGame>(composer => composer
21-
.FromFactory<long, string, ulong>((id, name, buildId) =>
21+
.FromFactory<long, string, ulong, long>((id, name, buildId, parentId) =>
2222
{
2323
var path = fileSystem
2424
.GetKnownPath(KnownPath.TempDirectory)
@@ -29,8 +29,9 @@ public static IEnumerable<GOGGame> SetupGames(IFileSystem fileSystem, InMemoryRe
2929
gameKey.AddValue("gameName", name);
3030
gameKey.AddValue("path", path.GetFullPath());
3131
gameKey.AddValue("buildId", $"{buildId}");
32+
gameKey.AddValue("dependsOn", parentId.ToString(CultureInfo.InvariantCulture));
3233

33-
return new GOGGame(GOGGameId.From(id), name, path, buildId);
34+
return new GOGGame(GOGGameId.From(id), name, path, buildId, GOGGameId.From(parentId));
3435
})
3536
.OmitAutoProperties());
3637

0 commit comments

Comments
 (0)