Skip to content

Commit

Permalink
Provide wine prefix for heroic
Browse files Browse the repository at this point in the history
  • Loading branch information
erri120 committed Oct 1, 2024
1 parent 504d7c7 commit 2fce4fb
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 10 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com) and this p

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

## [4.3.1](https://github.com/erri120/GameFinder/compare/v4.3.0...v4.3.1) - 2024-10-01

- Heroic: pass along the wine prefix

## [4.3.0](https://github.com/erri120/GameFinder/compare/v4.2.4...v4.3.0) - 2024-09-28

Adds support for Heroic.
Expand Down
29 changes: 29 additions & 0 deletions src/GameFinder.Launcher.Heroic/DTOs/Json.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,34 @@ internal record Root(
[property: JsonPropertyName("installed")] IReadOnlyList<Installed> Installed
);

internal record GameConfig(
[property: JsonPropertyName("autoInstallDxvk")] bool AutoInstallDxvk,
[property: JsonPropertyName("autoInstallDxvkNvapi")] bool AutoInstallDxvkNvapi,
[property: JsonPropertyName("autoInstallVkd3d")] bool AutoInstallVkd3d,
[property: JsonPropertyName("preferSystemLibs")] bool PreferSystemLibs,
[property: JsonPropertyName("enableEsync")] bool EnableEsync,
[property: JsonPropertyName("enableMsync")] bool EnableMsync,
[property: JsonPropertyName("enableFsync")] bool EnableFsync,
[property: JsonPropertyName("nvidiaPrime")] bool NvidiaPrime,
[property: JsonPropertyName("enviromentOptions")] IReadOnlyList<object> EnviromentOptions,
[property: JsonPropertyName("wrapperOptions")] IReadOnlyList<object> WrapperOptions,
[property: JsonPropertyName("showFps")] bool ShowFps,
[property: JsonPropertyName("useGameMode")] bool UseGameMode,
[property: JsonPropertyName("battlEyeRuntime")] bool BattlEyeRuntime,
[property: JsonPropertyName("eacRuntime")] bool EacRuntime,
[property: JsonPropertyName("language")] string Language,
[property: JsonPropertyName("beforeLaunchScriptPath")] string BeforeLaunchScriptPath,
[property: JsonPropertyName("afterLaunchScriptPath")] string AfterLaunchScriptPath,
[property: JsonPropertyName("wineVersion")] WineVersion WineVersion,
[property: JsonPropertyName("winePrefix")] string WinePrefix,
[property: JsonPropertyName("wineCrossoverBottle")] string WineCrossoverBottle
);

public record WineVersion(
[property: JsonPropertyName("bin")] string Bin,
[property: JsonPropertyName("name")] string Name,
[property: JsonPropertyName("type")] string Type
);



Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@

<ItemGroup>
<ProjectReference Include="..\GameFinder.StoreHandlers.GOG\GameFinder.StoreHandlers.GOG.csproj" />
<ProjectReference Include="..\GameFinder.Wine\GameFinder.Wine.csproj" />
</ItemGroup>
</Project>
22 changes: 22 additions & 0 deletions src/GameFinder.Launcher.Heroic/HeroicGOGGame.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using GameFinder.StoreHandlers.GOG;
using GameFinder.Wine;
using NexusMods.Paths;

namespace GameFinder.Launcher.Heroic;

public record HeroicGOGGame(
GOGGameId Id,
string Name,
AbsolutePath Path,
AbsolutePath WinePrefixPath,
DTOs.WineVersion WineVersion) : GOGGame(Id, Name, Path)
{
public WinePrefix GetWinePrefix()
{
return new WinePrefix
{
ConfigurationDirectory = WinePrefixPath.Combine("pfx"),
UserName = "steamuser",
};
}
}
46 changes: 37 additions & 9 deletions src/GameFinder.Launcher.Heroic/HeroicGOGHandler.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
Expand All @@ -20,6 +21,7 @@ public class HeroicGOGHandler : AHandler<GOGGame, GOGGameId>
private static readonly JsonSerializerOptions JsonSerializerOptions = new()
{
AllowTrailingCommas = true,
ReadCommentHandling = JsonCommentHandling.Skip,
};

/// <summary>
Expand All @@ -39,24 +41,25 @@ public HeroicGOGHandler(IFileSystem fileSystem)
/// <inheritdoc/>
public override IEnumerable<OneOf<GOGGame, ErrorMessage>> FindAllGames()
{
var installedJsonFile = FindConfigDirectory(_fileSystem)
.Select(GetInstalledJsonFilePath)
.FirstOrDefault(path => path.FileExists);
var configDirectory = FindConfigDirectory(_fileSystem)
.FirstOrDefault(path => path.DirectoryExists());

if (installedJsonFile == default)
if (configDirectory == 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);
var installedJsonFile = GetInstalledJsonFilePath(configDirectory);

var games = ParseInstalledJsonFile(installedJsonFile, configDirectory);
foreach (var x in games)
{
yield return x;
}
}

internal static IEnumerable<OneOf<GOGGame, ErrorMessage>> ParseInstalledJsonFile(AbsolutePath path)
internal static IEnumerable<OneOf<GOGGame, ErrorMessage>> ParseInstalledJsonFile(AbsolutePath path, AbsolutePath configPath)
{
using var stream = path.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
var root = JsonSerializer.Deserialize<DTOs.Root>(stream, JsonSerializerOptions);
Expand All @@ -71,7 +74,7 @@ internal static IEnumerable<OneOf<GOGGame, ErrorMessage>> ParseInstalledJsonFile
OneOf<GOGGame, ErrorMessage> res;
try
{
res = Parse(installed, path.FileSystem);
res = Parse(installed, configPath, path.FileSystem);
}
catch (Exception e)
{
Expand All @@ -82,15 +85,40 @@ internal static IEnumerable<OneOf<GOGGame, ErrorMessage>> ParseInstalledJsonFile
}
}

internal static OneOf<GOGGame, ErrorMessage> Parse(DTOs.Installed installed, IFileSystem fileSystem)
[RequiresUnreferencedCode("Calls System.Text.Json.JsonSerializer.Deserialize<TValue>(JsonSerializerOptions)")]
internal static OneOf<GOGGame, ErrorMessage> Parse(
DTOs.Installed installed,
AbsolutePath configPath,
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 gamesConfigFile = GetGamesConfigJsonFile(configPath, id.ToString(CultureInfo.InvariantCulture));
if (!gamesConfigFile.FileExists) return new ErrorMessage($"File `{gamesConfigFile}` doesn't exist!");

using var stream = gamesConfigFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
using var doc = JsonDocument.Parse(stream, new JsonDocumentOptions
{
AllowTrailingCommas = true,
CommentHandling = JsonCommentHandling.Skip,
});

var element = doc.RootElement.GetProperty(id.ToString(CultureInfo.InvariantCulture));
var gameConfig = element.Deserialize<DTOs.GameConfig>();
if (gameConfig is null) return new ErrorMessage($"Unable to deserialize `{gamesConfigFile}`");

var path = fileSystem.FromUnsanitizedFullPath(installed.InstallPath);
return new GOGGame(GOGGameId.From(id), installed.AppName, path);
var winePrefixPath = fileSystem.FromUnsanitizedFullPath(gameConfig.WinePrefix);

return new HeroicGOGGame(GOGGameId.From(id), installed.AppName, path, winePrefixPath, gameConfig.WineVersion);
}

internal static AbsolutePath GetGamesConfigJsonFile(AbsolutePath configPath, string name)
{
return configPath.Combine("GamesConfig").Combine($"{name}.json");
}

internal static AbsolutePath GetInstalledJsonFilePath(AbsolutePath configPath)
Expand Down
10 changes: 9 additions & 1 deletion src/GameFinder.Wine/WinePrefix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,12 @@ namespace GameFinder.Wine;
/// Represents a wine prefix.
/// </summary>
[PublicAPI]
public record WinePrefix : AWinePrefix;
public record WinePrefix : AWinePrefix
{
public string? UserName { get; init; }

protected override string GetUserName()
{
return UserName ?? base.GetUserName();
}
}
1 change: 1 addition & 0 deletions src/GameFinder/GameFinder.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<ProjectReference Include="..\GameFinder.StoreHandlers.Steam\GameFinder.StoreHandlers.Steam.csproj" />
<ProjectReference Include="..\GameFinder.StoreHandlers.Xbox\GameFinder.StoreHandlers.Xbox.csproj" />
<ProjectReference Include="..\GameFinder.Wine\GameFinder.Wine.csproj" />
<ProjectReference Include="..\GameFinder.Launcher.Heroic\GameFinder.Launcher.Heroic.csproj" />
</ItemGroup>

</Project>

0 comments on commit 2fce4fb

Please sign in to comment.