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
8 changes: 5 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ Though upstream [GameFinder](https://github.com/erri120/GameFinder) adheres to [
- Add [PkgHandlers](https://github.com/Nutzzz/GameCollector/pull/40) to find installed software, and to download free games
- Add [DataHandlers](https://github.com/Nutzzz/GameCollector/pull/13) to download metadata and images from online sources

## [Released](https://github.com/Nutzzz/GameCollector/releases)
## [4.2.4-2](https://github.com/Nutzzz/GameCollector/compare/v4.2.4.1...v4.2.4.2) - UNRELEASED

### Added

## [4.3.2-1](https://github.com/Nutzzz/GameCollector/compare/v4.3.1.1...v4.3.2.1) - 2024-10-09
- Add Winget package handler to detect both installed apps and show free game packages

- Upstream: Heroic: validate that file exists before parsing
## [Released](https://github.com/Nutzzz/GameCollector/releases)

## [4.3.1-1](https://github.com/Nutzzz/GameCollector/compare/v4.2.4.1...v4.3.1.1) - 2024-10-01

Expand Down
23 changes: 16 additions & 7 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,25 @@
<PackageVersion Include="TransparentValueObjects" Version="1.0.1" />
</ItemGroup>
<ItemGroup>
<PackageVersion Include="HtmlAgilityPack" Version="1.11.61" />
<PackageVersion Include="HtmlAgilityPack" Version="1.11.70" />
<PackageVersion Include="Microsoft.AspNet.WebApi.Client" Version="5.2.9" />
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
<PackageVersion Include="protobuf-net" Version="3.2.30" />
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.1" />
<PackageVersion Include="Microsoft.Management.Deployment" Version="8.0.0" />
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.1.3" />
<!-- Version="2.0.4" /> -->
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.3.106" />
<!-- Version="0.3.49-beta" /> -->
<PackageVersion Include="Microsoft.WindowsPackageManager.ComInterop" Version="1.8.1911" GeneratePathProperty="true" IncludeAssets="none" />
<PackageVersion Include="Microsoft.WindowsPackageManager.InProcCom" Version="1.8.1911" GeneratePathProperty="true" IncludeAssets="none" />
<!-- Version="1.7.10091-preview" /> -->
<!-- Version="1.5.1572" /> -->
<PackageVersion Include="protobuf-net" Version="3.2.45" />
<PackageVersion Include="SteamWebAPI2" Version="4.4.1" />
<PackageVersion Include="System.Data.SQLite" Version="1.0.117" />
<PackageVersion Include="System.Data.SQLite.Core" Version="1.0.117" />
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="8.0.0" />
<PackageVersion Include="System.Data.SQLite" Version="1.0.119" />
<PackageVersion Include="System.Data.SQLite.Core" Version="1.0.119" />
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="8.0.1" />
<PackageVersion Include="System.Text.Json" Version="7.0.0" />
<PackageVersion Include="YamlDotNet" Version="15.3.0" />
<PackageVersion Include="YamlDotNet" Version="16.1.3" />
</ItemGroup>
<ItemGroup>
<PackageVersion Include="Meziantou.Analyzer" Version="2.0.159" />
Expand Down
10 changes: 10 additions & 0 deletions GameCollector.sln
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameCollector.EmuHandlers.D
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameCollector.EmuHandlers.MAME", "src\GameCollector.EmuHandlers.MAME\GameCollector.EmuHandlers.MAME.csproj", "{EA0A79A3-639B-4983-A28F-1D07EC1113C7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PkgHandlers", "PkgHandlers", "{55345886-D1F6-4733-9943-1283AF39CEA5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameCollector.PkgHandlers.Winget", "src\GameCollector.PkgHandlers.Winget\GameCollector.PkgHandlers.Winget.csproj", "{7C74842C-69FE-4908-BA71-210652A15744}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DataHandlers", "DataHandlers", "{82816E34-196A-4304-8A28-BF22FA937DF0}"
EndProject
Global
Expand Down Expand Up @@ -324,6 +328,10 @@ Global
{EA0A79A3-639B-4983-A28F-1D07EC1113C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EA0A79A3-639B-4983-A28F-1D07EC1113C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EA0A79A3-639B-4983-A28F-1D07EC1113C7}.Release|Any CPU.Build.0 = Release|Any CPU
{7C74842C-69FE-4908-BA71-210652A15744}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7C74842C-69FE-4908-BA71-210652A15744}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7C74842C-69FE-4908-BA71-210652A15744}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7C74842C-69FE-4908-BA71-210652A15744}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -378,6 +386,8 @@ Global
{1F5F230D-146C-4794-A2E6-F9C13279D721} = {EFB4E7DB-DE24-4BDE-B660-DAF1394ECC21}
{6173D1F4-48C2-4B14-B907-C7A746CF081D} = {1F5F230D-146C-4794-A2E6-F9C13279D721}
{EA0A79A3-639B-4983-A28F-1D07EC1113C7} = {1F5F230D-146C-4794-A2E6-F9C13279D721}
{55345886-D1F6-4733-9943-1283AF39CEA5} = {EFB4E7DB-DE24-4BDE-B660-DAF1394ECC21}
{7C74842C-69FE-4908-BA71-210652A15744} = {55345886-D1F6-4733-9943-1283AF39CEA5}
{82816E34-196A-4304-8A28-BF22FA937DF0} = {EFB4E7DB-DE24-4BDE-B660-DAF1394ECC21}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
Expand Down
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

.NET library for finding games. GameCollector expands on upstream GameFinder (which is primarily designed to support modding tools), by adding additional supported store launchers, emulators, and data sources, and includes additional information about each game (sufficient for a multi-store game launcher such as [GLC](https://github.com/Solaire/GLC)). This fork is indebted to erri120's hard work, but as [he is reticent](https://github.com/erri120/GameFinder/issues/49) to expand the scope of GameFinder, GameCollector continues with a different philosophy.

The following launchers and emulators are supported:
The following launchers, emulators, and package managers are supported:

| handler | package |
| -- | -- |
Expand Down Expand Up @@ -36,6 +36,7 @@ The following launchers and emulators are supported:
| [Steam](#steam) | [![Nuget](https://img.shields.io/nuget/v/GameCollector.StoreHandlers.Steam)](https://www.nuget.org/packages/GameCollector.StoreHandlers.Steam) [![Nuget](https://img.shields.io/nuget/v/GameFinder.StoreHandlers.Steam?color=red&label=upstream)](https://www.nuget.org/packages/GameFinder.StoreHandlers.Steam) |
| Ubisoft Connect | [![Nuget](https://img.shields.io/nuget/v/GameCollector.StoreHandlers.Ubisoft)](https://www.nuget.org/packages/GameCollector.StoreHandlers.Ubisoft) |
| Wargaming.net Game Center | [![Nuget](https://img.shields.io/nuget/v/GameCollector.StoreHandlers.WargamingNet)](https://www.nuget.org/packages/GameCollector.StoreHandlers.WargamingNet) |
| Windows Package Manager | [![Nuget](https://img.shields.io/nuget/v/GameCollector.PkgHandlers.Winget)](https://www.nuget.org/packages/GameCollector.PkgHandlers.Winget) |
| [Xbox Game Pass](#xbox-game-pass) | [![Nuget](https://img.shields.io/nuget/v/GameCollector.StoreHandlers.Xbox)](https://www.nuget.org/packages/GameCollector.StoreHandlers.Xbox) [![Nuget](https://img.shields.io/nuget/v/GameFinder.StoreHandlers.Xbox?color=red&label=upstream)](https://www.nuget.org/packages/GameFinder.StoreHandlers.Xbox) |

If you are interested in understanding _how_ GameCollector/GameFinder finds these games, check [the upstream wiki](https://github.com/erri120/GameFinder/wiki) for more information (descriptions of the added handlers should eventually be added to a wiki here).
Expand Down Expand Up @@ -98,6 +99,12 @@ The TGame implementations of GameCollector's handlers inherit a generic GameData

The Metadata dictionary may include (depending on available information): "ReleaseDate", "Description", "Developers", "Publishers", "Genres", "ImageUrl", etc.

### Supported Package Managers

This is a new category of handler for GameCollector. It is Windows-only for now.

- Winget

### Supported Emulators

This is a new category of handler for GameCollector. They are Windows-only for now.
Expand Down Expand Up @@ -418,7 +425,7 @@ Self-contained deployments and executables can be [trimmed](https://learn.micros

**NOT Trimmable**:

- `GameCollector.StoreHandlers.EADesktop`: This package references `System.Management`, which is **not trimmable** due to COM interop issues. See [dotnet/runtime#78038](https://github.com/dotnet/runtime/issues/78038), [dotnet/runtime#75176](https://github.com/dotnet/runtime/pull/75176) and [dotnet/runtime#61960](https://github.com/dotnet/runtime/issues/61960) for more details.
- `GameCollector.StoreHandlers.EADesktop` and `GameCollector.PkgHandlers.Winget`: These packages reference `System.Management`, which is **not trimmable** due to COM interop issues. See [dotnet/runtime#78038](https://github.com/dotnet/runtime/issues/78038), [dotnet/runtime#75176](https://github.com/dotnet/runtime/pull/75176) and [dotnet/runtime#61960](https://github.com/dotnet/runtime/issues/61960) for more details.

I recommend looking at the [project file](./other/GameFinder.Example/GameFinder.Example.csproj) of the example project, if you run into warnings or errors with trimming.

Expand Down
4 changes: 4 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ component_management:
name: Wargaming.net Game Center
paths:
- "src/GameCollector.StoreHandlers.WargamingNet/**"
- component_id: pkg_handler_winget
name: Windows Package Manager
paths:
- "src/GameCollector.PkgHandlers.Winget/**"
- component_id: emu_handler_dolphin
name: Dolphin Emulator
paths:
Expand Down
4 changes: 4 additions & 0 deletions other/GameFinder.Example/GameFinder.Example.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
<ProjectReference Include="..\..\src\GameCollector.EmuHandlers.MAME\GameCollector.EmuHandlers.MAME.csproj" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\GameCollector.PkgHandlers.Winget\GameCollector.PkgHandlers.Winget.csproj" />
</ItemGroup>

<ItemGroup>
<!--<ProjectReference Include="..\..\src\GameCollector.DataHandlers.TheGamesDb\GameCollector.DataHandlers.TheGamesDb.csproj" />-->
</ItemGroup>
Expand Down
3 changes: 3 additions & 0 deletions other/GameFinder.Example/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ public class Options
[Option("wargaming", HelpText = "Search for Wargaming.Net Game Center games", Hidden = true, Group = "Handlers")]
public bool Wargaming { get; set; } = false;

[Option("winget", HelpText = "Search for Windows Package Manager packages", Hidden = true, Group = "Handlers")]
public bool Winget { get; set; } = false;

[Option("xbox", HelpText = "Search for Xbox Games Pass games", Hidden = true, Group = "Handlers")]
public bool Xbox { get; set; } = false;

Expand Down
18 changes: 14 additions & 4 deletions other/GameFinder.Example/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
using GameCollector.StoreHandlers.Rockstar;
using GameCollector.StoreHandlers.Ubisoft;
using GameCollector.StoreHandlers.WargamingNet;
using GameCollector.PkgHandlers.Winget;
using GameCollector.EmuHandlers.Dolphin;
using GameCollector.EmuHandlers.MAME;
//using GameCollector.DataHandlers.TheGamesDb;
Expand Down Expand Up @@ -115,13 +116,13 @@ private async static void Run(Options options, ILogger logger)

var settings = new Settings(options.Installed, options.Parent || options.Base, options.Owned, options.Games);

if (options.All) // Enable all emulator and handlers
if (options.All) // Enable all handlers
{
options.Amazon = true;
options.Arc = true;
options.BattleNet = true;
options.BigFish = true;
//options.Dolphin ??= "";
//options.Dolphin ??= ""; // needs path
options.EA = true;
options.Epic = true;
options.GameJolt = true;
Expand All @@ -131,7 +132,7 @@ private async static void Run(Options options, ILogger logger)
options.IG = true;
options.Itch = true;
options.Legacy = true;
//options.MAME ??= "";
//options.MAME ??= ""; // needs path
options.Oculus = true;
options.Origin = true;
options.Paradox = true;
Expand All @@ -140,9 +141,10 @@ private async static void Run(Options options, ILogger logger)
options.RobotCache = true;
options.Rockstar = true;
options.Steam = true;
//options.TheGamesDB = true;
//options.TheGamesDB = true; // WIP
options.Ubisoft = true;
options.Wargaming = true;
options.Winget = true;
options.Xbox = true;
}

Expand Down Expand Up @@ -187,6 +189,8 @@ private async static void Run(Options options, ILogger logger)
if (options.Ubisoft || options.Uplay) tasks.Add(Task.Run(() => RunUbisoftHandler(settings, windowsRegistry, realFileSystem), cancelToken));
if (options.Wargaming || options.WargamingNet) tasks.Add(Task.Run(() => RunWargamingNetHandler(settings, windowsRegistry, realFileSystem), cancelToken));

if (options.Winget) tasks.Add(Task.Run(() => RunWingetHandler(settings, windowsRegistry, realFileSystem), cancelToken));

if (options.Dolphin is not null)
{
tasks.Add(Task.Run(() =>
Expand Down Expand Up @@ -455,6 +459,12 @@ private static void RunWargamingNetHandler(Settings settings, IRegistry registry
var handler = new WargamingNetHandler(registry, fileSystem);
LogGamesAndErrors(handler.FindAllGames(settings), logger);
}
private static void RunWingetHandler(Settings settings, IRegistry registry, IFileSystem fileSystem)
{
var logger = _provider.CreateLogger(nameof(WingetHandler));
var handler = new WingetHandler(registry, fileSystem, logger); //, logger);
LogGamesAndErrors(handler.FindAllGames(settings), logger);
}

private static void RunDolphinHandler(Settings settings, IRegistry registry, IFileSystem fileSystem, AbsolutePath path)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />

<PropertyGroup>
<PackageVersion>4.3.2.1</PackageVersion>
<PackageVersion>4.3.2.2</PackageVersion>
<Authors>Nutzzz, erri120</Authors>

<PackageReadmeFile>docs\README.md</PackageReadmeFile>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Library for finding installed apps and available game packages via Windows Package Manager.</Description>
<PackageTags>winget windows-package-manager games</PackageTags>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\GameFinder.Common\GameFinder.Common.csproj" />
<ProjectReference Include="..\GameFinder.RegistryUtils\GameFinder.RegistryUtils.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="TransparentValueObjects" PrivateAssets="all" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="GameCollector.PkgHandlers.Winget.Tests" />
</ItemGroup>
</Project>
86 changes: 86 additions & 0 deletions src/GameCollector.PkgHandlers.Winget/WingetGame.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using GameFinder.Common;
using JetBrains.Annotations;
using NexusMods.Paths;

namespace GameCollector.PkgHandlers.Winget;

/// <summary>
/// Represents an installed app or available package via Windows Package Manager.
/// </summary>
/// <param name="Id"></param>
/// <param name="Name"></param>
/// <param name="InstallDirectory"></param>
/// <param name="Launch"></param>
/// <param name="InstallerUrl"></param>
/// <param name="Uninstall"></param>
/// <param name="IsInstalled"></param>
/// <param name="IsOwned"></param>
/// <param name="InstallDate"></param>
/// <param name="Description"></param>
/// <param name="Publisher"></param>
/// <param name="PackageTags"></param>
/// <param name="PublisherUrl"></param>
/// <param name="SupportUrl"></param>
/// <param name="Homepage"></param>
/// <param name="Author"></param>
/// <param name="PackageName"></param>
/// <param name="Moniker"></param>
/// <param name="Source"></param>
/// <param name="LicenseType"></param>
/// <param name="InstalledVersion"></param>
/// <param name="DefaultVersion"></param>
/// <param name="AgeRating"></param>

[PublicAPI]
public record WingetGame(WingetGameId Id,
string? Name,
AbsolutePath InstallDirectory,
AbsolutePath Launch = new(),
string? InstallerUrl = "",
AbsolutePath Uninstall = new(),
bool IsInstalled = true,
bool IsOwned = true,
DateTime? InstallDate = null,
string? Description = "",
string? Publisher = "",
List<string>? PackageTags = default,
string? PublisherUrl = "",
string? SupportUrl = "",
string? Homepage = "",
string? Author = "",
string? PackageName = "",
string? Moniker = "",
string? Source = "",
string? LicenseType = "",
string? InstalledVersion = "",
string? DefaultVersion = "",
string? AgeRating = "") :
GameData(Handler: Handler.PkgHandler_Winget,
GameId: Id.ToString(),
GameName: Name ?? "",
GamePath: InstallDirectory,
Launch: Launch,
LaunchUrl: InstallerUrl ?? "",
Icon: Launch,
Uninstall: Uninstall,
IsInstalled: IsInstalled,
IsOwned: IsOwned,
InstallDate: InstallDate,
Metadata: new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase)
{
["Description"] = new() { Description ?? "", },
["Developers"] = new() { Author ?? "", },
["Publishers"] = new() { Publisher ?? "", },
["Genres"] = PackageTags ?? new(),
["WebInfo"] = new() { Homepage ?? PublisherUrl ?? "" },
["WebSupport"] = new() { SupportUrl ?? "" },
["PackageName"] = new() { PackageName ?? "" },
["Moniker"] = new() { Moniker ?? "", },
["Source"] = new() { Source ?? "", },
["License"] = new() { LicenseType ?? "", },
["InstalledVersion"] = new() { InstalledVersion ?? "", },
["DefaultVersion"] = new() { DefaultVersion ?? "", },
["AgeRating"] = new() { AgeRating ?? "", },
});
50 changes: 50 additions & 0 deletions src/GameCollector.PkgHandlers.Winget/WingetGameId.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using TransparentValueObjects;

namespace GameCollector.PkgHandlers.Winget;

/// <summary>
/// Represents an id for installed apps and available packages via Windows Package Manager.
/// </summary>
[ValueObject<string>]
public readonly partial struct WingetGameId : IAugmentWith<DefaultEqualityComparerAugment>
{
/// <inheritdoc/>
public static IEqualityComparer<string> InnerValueDefaultEqualityComparer { get; } = StringComparer.OrdinalIgnoreCase;
}

/// <inheritdoc/>
[PublicAPI]
public class WingetGameIdComparer : IEqualityComparer<WingetGameId>
{
private static WingetGameIdComparer? _default;

/// <summary>
/// Default equality comparer that uses <see cref="StringComparison.OrdinalIgnoreCase"/>.
/// </summary>
public static WingetGameIdComparer Default => _default ??= new();

private readonly StringComparison _stringComparison;

/// <summary>
/// Default constructor that uses <see cref="StringComparison.OrdinalIgnoreCase"/>.
/// </summary>
public WingetGameIdComparer() : this(StringComparison.OrdinalIgnoreCase) { }

/// <summary>
/// Constructor.
/// </summary>
/// <param name="stringComparison"></param>
public WingetGameIdComparer(StringComparison stringComparison)
{
_stringComparison = stringComparison;
}

/// <inheritdoc/>
public bool Equals(WingetGameId x, WingetGameId y) => string.Equals(x.Value, y.Value, _stringComparison);

/// <inheritdoc/>
public int GetHashCode(WingetGameId obj) => obj.Value.GetHashCode(_stringComparison);
}
Loading