-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #151 from erri120/heroic
Add heroic support
- Loading branch information
Showing
13 changed files
with
194 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using System.Collections.Generic; | ||
using System.Text.Json.Serialization; | ||
|
||
namespace GameFinder.Launcher.Heroic.DTOs; | ||
|
||
internal record Installed( | ||
[property: JsonPropertyName("platform")] string Platform, | ||
[property: JsonPropertyName("executable")] string Executable, | ||
[property: JsonPropertyName("install_path")] string InstallPath, | ||
[property: JsonPropertyName("install_size")] string InstallSize, | ||
[property: JsonPropertyName("is_dlc")] bool IsDlc, | ||
[property: JsonPropertyName("version")] string Version, | ||
[property: JsonPropertyName("appName")] string AppName, | ||
[property: JsonPropertyName("installedDLCs")] IReadOnlyList<object> InstalledDLCs, | ||
[property: JsonPropertyName("language")] string Language, | ||
[property: JsonPropertyName("versionEtag")] string VersionEtag, | ||
[property: JsonPropertyName("buildId")] string BuildId, | ||
[property: JsonPropertyName("pinnedVersion")] bool PinnedVersion | ||
); | ||
|
||
internal record Root( | ||
[property: JsonPropertyName("installed")] IReadOnlyList<Installed> Installed | ||
); | ||
|
||
|
||
|
9 changes: 9 additions & 0 deletions
9
src/GameFinder.Launcher.Heroic/GameFinder.Launcher.Heroic.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<IsTrimmable>false</IsTrimmable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\GameFinder.StoreHandlers.GOG\GameFinder.StoreHandlers.GOG.csproj" /> | ||
</ItemGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Globalization; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Text.Json; | ||
using GameFinder.Common; | ||
using GameFinder.StoreHandlers.GOG; | ||
using JetBrains.Annotations; | ||
using NexusMods.Paths; | ||
using OneOf; | ||
|
||
namespace GameFinder.Launcher.Heroic; | ||
|
||
[PublicAPI] | ||
public class HeroicGOGHandler : AHandler<GOGGame, GOGGameId> | ||
{ | ||
private readonly IFileSystem _fileSystem; | ||
|
||
private static readonly JsonSerializerOptions JsonSerializerOptions = new() | ||
{ | ||
AllowTrailingCommas = true, | ||
}; | ||
|
||
/// <summary> | ||
/// Constructor. | ||
/// </summary> | ||
public HeroicGOGHandler(IFileSystem fileSystem) | ||
{ | ||
_fileSystem = fileSystem; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override Func<GOGGame, GOGGameId> IdSelector { get; } = static game => game.Id; | ||
|
||
/// <inheritdoc/> | ||
public override IEqualityComparer<GOGGameId>? IdEqualityComparer => null; | ||
|
||
/// <inheritdoc/> | ||
public override IEnumerable<OneOf<GOGGame, ErrorMessage>> FindAllGames() | ||
{ | ||
var installedJsonFile = FindConfigDirectory(_fileSystem) | ||
.Select(GetInstalledJsonFilePath) | ||
.FirstOrDefault(path => path.FileExists); | ||
|
||
if (installedJsonFile == default) | ||
{ | ||
yield return new ErrorMessage("Didn't find any heroic files, this can be ignored if heroic isn't installed"); | ||
yield break; | ||
} | ||
|
||
var games = ParseInstalledJsonFile(installedJsonFile); | ||
foreach (var x in games) | ||
{ | ||
yield return x; | ||
} | ||
} | ||
|
||
internal static IEnumerable<OneOf<GOGGame, ErrorMessage>> ParseInstalledJsonFile(AbsolutePath path) | ||
{ | ||
using var stream = path.Open(FileMode.Open, FileAccess.Read, FileShare.Read); | ||
var root = JsonSerializer.Deserialize<DTOs.Root>(stream, JsonSerializerOptions); | ||
if (root is null) | ||
{ | ||
yield return new ErrorMessage($"Unable to deserialize `{path}`"); | ||
yield break; | ||
} | ||
|
||
foreach (var installed in root.Installed) | ||
{ | ||
OneOf<GOGGame, ErrorMessage> res; | ||
try | ||
{ | ||
res = Parse(installed, path.FileSystem); | ||
} | ||
catch (Exception e) | ||
{ | ||
res = new ErrorMessage(e, $"Unable to parse in {path}: `{installed}`"); | ||
} | ||
|
||
yield return res; | ||
} | ||
} | ||
|
||
internal static OneOf<GOGGame, ErrorMessage> Parse(DTOs.Installed installed, IFileSystem fileSystem) | ||
{ | ||
if (!long.TryParse(installed.AppName, NumberStyles.Integer, CultureInfo.InvariantCulture, out var id)) | ||
{ | ||
return new ErrorMessage($"The value \"appName\" is not a number: \"{installed.AppName}\""); | ||
} | ||
|
||
var path = fileSystem.FromUnsanitizedFullPath(installed.InstallPath); | ||
return new GOGGame(GOGGameId.From(id), installed.AppName, path); | ||
} | ||
|
||
internal static AbsolutePath GetInstalledJsonFilePath(AbsolutePath configPath) | ||
{ | ||
return configPath.Combine("gog_store").Combine("installed.json"); | ||
} | ||
|
||
internal static IEnumerable<AbsolutePath> FindConfigDirectory(IFileSystem fileSystem) | ||
{ | ||
yield return fileSystem.GetKnownPath(KnownPath.XDG_CONFIG_HOME).Combine("heroic"); | ||
|
||
// Flatpak installation | ||
yield return fileSystem.GetKnownPath(KnownPath.HomeDirectory) | ||
.Combine(".var") | ||
.Combine("app") | ||
.Combine("com.heroicgameslauncher.hgl") | ||
.Combine("config") | ||
.Combine("heroic"); | ||
} | ||
} |