Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 48 additions & 53 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -1,54 +1,49 @@
<Project>
<ItemGroup>
<PackageVersion Include="BenchmarkDotNet" Version="0.13.12" />
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
<PackageVersion Include="FluentResults" Version="3.15.2" />
<PackageVersion Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageVersion Include="NexusMods.Paths" Version="0.9.0" />
<PackageVersion Include="NexusMods.Paths.TestingHelpers" Version="0.9.0" />
<PackageVersion Include="NLog" Version="5.2.8" />
<PackageVersion Include="NLog.Extensions.Logging" Version="5.3.8" />
<PackageVersion Include="OneOf" Version="3.0.263" />
<PackageVersion Include="SHA3.Net" Version="2.0.0" />
<PackageVersion Include="System.Management" Version="8.0.0" />
<PackageVersion Include="ValveKeyValue" Version="0.10.0.360" />
<PackageVersion Include="TransparentValueObjects" Version="1.0.1" />
</ItemGroup>

<ItemGroup>
<PackageVersion Include="Meziantou.Analyzer" Version="2.0.146"/>
<PackageVersion Include="JetBrains.Annotations" Version="2023.3.0"/>
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0"/>
</ItemGroup>

<ItemGroup>
<PackageVersion Include="AutoFixture" Version="4.18.1" />
<PackageVersion Include="AutoFixture.Xunit2" Version="4.18.1" />
<PackageVersion Include="FluentAssertions" Version="6.12.0" />
<PackageVersion Include="FluentAssertions.Analyzers" Version="0.31.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageVersion>
<PackageVersion Include="FluentResults.Extensions.FluentAssertions" Version="2.1.1" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageVersion Include="NSubstitute" Version="5.1.0" />
<PackageVersion Include="NSubstitute.Analyzers.CSharp" Version="1.0.17">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageVersion>
<PackageVersion Include="xunit" Version="2.7.0" />
<PackageVersion Include="Xunit.SkippableFact" Version="1.4.13" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.7">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageVersion>
<PackageVersion Include="coverlet.collector" Version="6.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageVersion>
<PackageVersion Include="GitHubActionsTestLogger" Version="2.3.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageVersion>
</ItemGroup>
</Project>
<ItemGroup>
<PackageVersion Include="BenchmarkDotNet" Version="0.13.12" />
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
<PackageVersion Include="FluentResults" Version="3.15.2" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" />
<PackageVersion Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageVersion Include="NexusMods.Paths" Version="0.9.0" />
<PackageVersion Include="NexusMods.Paths.TestingHelpers" Version="0.9.0" />
<PackageVersion Include="NLog" Version="5.2.8" />
<PackageVersion Include="NLog.Extensions.Logging" Version="5.3.8" />
<PackageVersion Include="OneOf" Version="3.0.263" />
<PackageVersion Include="SHA3.Net" Version="2.0.0" />
<PackageVersion Include="System.Management" Version="8.0.0" />
<PackageVersion Include="ValveKeyValue" Version="0.10.0.360" />
<PackageVersion Include="TransparentValueObjects" Version="1.0.1" />
<PackageVersion Include="Meziantou.Analyzer" Version="2.0.146" />
<PackageVersion Include="JetBrains.Annotations" Version="2023.3.0" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<PackageVersion Include="AutoFixture" Version="4.18.1" />
<PackageVersion Include="AutoFixture.Xunit2" Version="4.18.1" />
<PackageVersion Include="FluentAssertions" Version="6.12.0" />
<PackageVersion Include="FluentAssertions.Analyzers" Version="0.31.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageVersion>
<PackageVersion Include="FluentResults.Extensions.FluentAssertions" Version="2.1.1" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageVersion Include="NSubstitute" Version="5.1.0" />
<PackageVersion Include="NSubstitute.Analyzers.CSharp" Version="1.0.17">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageVersion>
<PackageVersion Include="xunit" Version="2.7.0" />
<PackageVersion Include="Xunit.SkippableFact" Version="1.4.13" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.7">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageVersion>
<PackageVersion Include="coverlet.collector" Version="6.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageVersion>
<PackageVersion Include="GitHubActionsTestLogger" Version="2.3.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageVersion>
</ItemGroup>
</Project>
1 change: 1 addition & 0 deletions GameFinder.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=appmanifest/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=appworkshop/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=libraryfolders/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mfst/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=patchnotes/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Preallocating/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Redistributables/@EntryIndexedValue">True</s:Boolean>
Expand Down
172 changes: 13 additions & 159 deletions other/GameFinder.Example/Program.cs
Original file line number Diff line number Diff line change
@@ -1,39 +1,26 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime.InteropServices;
using CommandLine;
using GameFinder.Common;
using GameFinder.RegistryUtils;
using GameFinder.StoreHandlers.EADesktop;
using GameFinder.StoreHandlers.EADesktop.Crypto;
using GameFinder.StoreHandlers.EADesktop.Crypto.Windows;
using GameFinder.StoreHandlers.EGS;
using GameFinder.StoreHandlers.GOG;
using GameFinder.StoreHandlers.Origin;
using GameFinder.StoreHandlers.Steam;
using GameFinder.StoreHandlers.Xbox;
using GameFinder.Wine;
using GameFinder.Wine.Bottles;
using Microsoft.Extensions.Logging;
using NexusMods.Paths;
using NLog;
using NLog.Config;
using NLog.Extensions.Logging;
using NLog.Targets;
using OneOf;
using FileSystem = NexusMods.Paths.FileSystem;
using IFileSystem = NexusMods.Paths.IFileSystem;
using ILogger = Microsoft.Extensions.Logging.ILogger;

[assembly: ExcludeFromCodeCoverage]
namespace GameFinder.Example;

public static class Program
{
private static NLogLoggerProvider _provider = null!;

public static void Main(string[] args)
{
var config = new LoggingConfiguration();
Expand All @@ -51,6 +38,7 @@ public static void Main(string[] args)
CompileRegex = true,
ForegroundColor = ConsoleOutputColor.Gray,
},
new ConsoleWordHighlightingRule("TRACE", ConsoleOutputColor.Gray, ConsoleOutputColor.NoChange),
new ConsoleWordHighlightingRule("DEBUG", ConsoleOutputColor.Gray, ConsoleOutputColor.NoChange),
new ConsoleWordHighlightingRule("INFO", ConsoleOutputColor.Cyan, ConsoleOutputColor.NoChange),
new ConsoleWordHighlightingRule("ERROR", ConsoleOutputColor.Red, ConsoleOutputColor.NoChange),
Expand All @@ -68,166 +56,32 @@ public static void Main(string[] args)
config.AddRuleForAllLevels(fileTarget);

LogManager.Configuration = config;
_provider = new NLogLoggerProvider();

var logger = _provider.CreateLogger(nameof(Program));
ILoggerFactory loggerFactory = new NLogLoggerFactory();

Parser.Default
.ParseArguments<Options>(args)
.WithParsed(x => Run(x, logger));
.WithParsed(x => Run(x, loggerFactory));
}

private static void Run(Options options, ILogger logger)
private static void Run(Options options, ILoggerFactory loggerFactory)
{
var realFileSystem = FileSystem.Shared;

var logFile = realFileSystem.GetKnownPath(KnownPath.CurrentDirectory).Combine("log.log");
if (realFileSystem.FileExists(logFile)) realFileSystem.DeleteFile(logFile);

var logger = loggerFactory.CreateLogger(nameof(Program));
logger.LogInformation("Operating System: {OSDescription}", RuntimeInformation.OSDescription);

if (OperatingSystem.IsWindows())
{
var windowsRegistry = WindowsRegistry.Shared;
if (options.Steam) RunSteamHandler(realFileSystem, windowsRegistry);
if (options.GOG) RunGOGHandler(windowsRegistry, realFileSystem);
if (options.EGS) RunEGSHandler(windowsRegistry, realFileSystem);
if (options.Origin) RunOriginHandler(realFileSystem);
if (options.Xbox) RunXboxHandler(realFileSystem);
if (options.EADesktop)
{
var hardwareInfoProvider = new HardwareInfoProvider();
var decryptionKey = Decryption.CreateDecryptionKey(new HardwareInfoProvider());
var sDecryptionKey = Convert.ToHexString(decryptionKey).ToLower(CultureInfo.InvariantCulture);
logger.LogDebug("EA Decryption Key: {DecryptionKey}", sDecryptionKey);

RunEADesktopHandler(realFileSystem, hardwareInfoProvider);
}
}

if (OperatingSystem.IsLinux())
{
if (options.Steam) RunSteamHandler(realFileSystem, registry: null);
var winePrefixes = new List<AWinePrefix>();

if (options.Wine)
{
var prefixManager = new DefaultWinePrefixManager(realFileSystem);
winePrefixes.AddRange(LogWinePrefixes(prefixManager, _provider.CreateLogger("Wine")));
}

if (options.Bottles)
{
var prefixManager = new BottlesWinePrefixManager(realFileSystem);
winePrefixes.AddRange(LogWinePrefixes(prefixManager, _provider.CreateLogger("Bottles")));
}

foreach (var winePrefix in winePrefixes)
{
var wineFileSystem = winePrefix.CreateOverlayFileSystem(realFileSystem);
var wineRegistry = winePrefix.CreateRegistry(realFileSystem);

if (options.GOG) RunGOGHandler(wineRegistry, wineFileSystem);
if (options.EGS) RunEGSHandler(wineRegistry, wineFileSystem);
if (options.Origin) RunOriginHandler(wineFileSystem);
if (options.Xbox) RunXboxHandler(wineFileSystem);
}
}

if (OperatingSystem.IsMacOS())
{
if (options.Steam)
RunSteamHandler(realFileSystem, null);
}
}

private static void RunGOGHandler(IRegistry registry, IFileSystem fileSystem)
{
var logger = _provider.CreateLogger(nameof(GOGHandler));
var handler = new GOGHandler(registry, fileSystem);
LogGamesAndErrors(handler.FindAllGames(), logger);
}
// TODO: Linux and macOS
if (!OperatingSystem.IsWindows()) return;

private static void RunEGSHandler(IRegistry registry, IFileSystem fileSystem)
{
var logger = _provider.CreateLogger(nameof(EGSHandler));
var handler = new EGSHandler(registry, fileSystem);
LogGamesAndErrors(handler.FindAllGames(), logger);
}
var gameFinder = GameFinderBuilder.Create(
loggerFactory,
new OriginHandler(loggerFactory, realFileSystem),
new GOGHandler(loggerFactory, realFileSystem, new WindowsRegistry())
);

private static void RunOriginHandler(IFileSystem fileSystem)
{
var logger = _provider.CreateLogger(nameof(OriginHandler));
var handler = new OriginHandler(fileSystem);
LogGamesAndErrors(handler.FindAllGames(), logger);
}

private static void RunEADesktopHandler(
IFileSystem fileSystem,
IHardwareInfoProvider hardwareInfoProvider)
{
var logger = _provider.CreateLogger(nameof(EADesktopHandler));
var handler = new EADesktopHandler(fileSystem, hardwareInfoProvider);
LogGamesAndErrors(handler.FindAllGames(), logger);
}

[UnconditionalSuppressMessage(
"Trimming",
"IL2026:RequiresUnreferencedCodeAttribute",
Justification = "Required types are preserved using TrimmerRootDescriptor file.")]
private static void RunXboxHandler(IFileSystem fileSystem)
{
var logger = _provider.CreateLogger(nameof(XboxHandler));
var handler = new XboxHandler(fileSystem);
LogGamesAndErrors(handler.FindAllGames(), logger);
}

private static void RunSteamHandler(IFileSystem fileSystem, IRegistry? registry)
{
var logger = _provider.CreateLogger(nameof(SteamHandler));
var handler = new SteamHandler(fileSystem, registry);
LogGamesAndErrors(handler.FindAllGames(), logger, game =>
{
if (!OperatingSystem.IsLinux()) return;
var protonPrefix = game.GetProtonPrefix();
if (protonPrefix is null) return;
logger.LogInformation("Proton Directory for this game: {}", protonPrefix.ProtonDirectory.GetFullPath());
});
}

private static List<AWinePrefix> LogWinePrefixes<TWinePrefix>(IWinePrefixManager<TWinePrefix> prefixManager, ILogger logger)
where TWinePrefix : AWinePrefix
{
var res = new List<AWinePrefix>();

foreach (var result in prefixManager.FindPrefixes())
{
result.Switch(prefix =>
{
logger.LogInformation("Found wine prefix at {PrefixConfigurationDirectory}", prefix.ConfigurationDirectory);
res.Add(prefix);
}, error =>
{
logger.LogError("{Error}", error);
});
}

return res;
}

private static void LogGamesAndErrors<TGame>(IEnumerable<OneOf<TGame, ErrorMessage>> results, ILogger logger, Action<TGame>? action = null)
where TGame : class
{
foreach (var result in results)
{
result.Switch(game =>
{
logger.LogInformation("Found {Game}", game);
action?.Invoke(game);
}, error =>
{
logger.LogError("{Error}", error);
});
}
var foundGames = gameFinder.FindAllGames();
}
}
Loading