All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog and this project adheres to Semantic Versioning.
4.3.3 - 2024-10-31
- Wine:
users
instead ofUsers
4.3.2 - 2024-10-07
- Heroic: validate that file exists before parsing (#155). Thanks @MistaOmega!
4.3.1 - 2024-10-01
- Heroic: pass along the wine prefix
4.3.0 - 2024-09-28
Adds support for Heroic.
4.2.4 - 2024-07-04
- Steam: find Flatpak installation
4.2.3 - 2024-06-25
- Steam: find snap installation
4.2.2 - 2024-06-06
- EA App: fixed exception (#132)
4.2.1 - 2024-06-05
- Steam: fixed exception (#133).
- Upgrade deps
4.2.0 - 2024-01-28
- Added support for OSX version of Steam (#122)
4.1.0 - 2024-01-08
- Upgraded to .NET 8.
- Upgraded all dependencies.
- Replaced Vogen with TransparentValueObjects.
- Steam: fixed
AppManifestParser
breaking when encountering an absolute path instead of a relative path in theinstalldir
field (#118). - Bottles: fixed a
DirectoryNotFoundException
when trying to enumerate a directory that doesn't exist (#119).
4.0.0 - 2023-09-03
This is a major release because I've had to change the license from MIT to GPLv3. See https://github.com/erri120/GameFinder/commit/53130f2d39fcb061366f4da9fcc695b8e0d8dd61 for details.
Additionally, all builds will now be packaged in release mode and dependencies have been upgraded.
3.2.2 - 2023-08-11
- Steam: fixed
StateFlag
parser throwing an exception (#93). - Updated dependencies.
- Replaced Moq with NSubstitute (#92).
3.2.1 - 2023-07-25
- Xbox: parsed relative path is now sanitized
3.2.0 - 2023-07-25
This is the first in a series of major updates that rework one of the store handlers. In this update, I focused on Steam and completely reworked the handler and data models. The SteamGame
record now contains a reference to the parsed AppManifest
, which itself is now fully fleshed out and has everything you need. Furthermore, you can now also parse the workshop manifest file, if it exists, to get a list of all installed Steam workshop items:
AppManifest
: forappmanifest_*.acf
files.LibraryFoldersManifest
: for the singlelibraryfolders.vdf
file inside theSteam/config
folder.WorkshopManifest
: forappworkshop_*.acf
files.LocalUserConfig
for the singlelocalconfig.vdf
file inside theuserdata/{steamId}/config
folder.
Finally, I've been thinking a lot about result types. Over the years, I've updated GameFinder to use various different approaches for dealing with errors. This update is the beginning of me phasing out my hacky OneOf<TResult, ErrorMessage>
solution, and replacing it with FluentResults.
Changes:
- Steam: complete rework
- Updated
NexusMods.Paths
to0.1.1
3.1.0 - 2023-05-23
Changes:
- Steam: added
CloudSavesDirectory
toSteamGame
. - Fixed
AWinePrefix.CreateRegistry
throwing an exception when the file doesn't exist. It will now do a check and early exist with an empty registry, if the registry file doesn't exist. - Fixed
WMIHelper
throwing an exception when WMI returns more than one element. - Marked
GameFinder.StoreHandlers.EADesktop
as non-trimmable. It uses the WMI, which itself requires COM, which is disabled when trimming is enabled.
3.0.2 - 2023-05-10
Changes:
- Converted
AWinePrefix
and all inheritors into record types. - Added
DebuggerDisplay
toErrorMessage
.
3.0.1 - 2023-05-10
First small release after the major 3.0.0 release.
Changes:
- Added
AHandler
. This is a non-generic abstract base class, inherited byAHandler<TGame, TId>
and should alleviate some of the issues with generics hell. This class only has one methodIEnumerable<OneOf<IGame, ErrorMessage>> FindAllInterfaceGames()
which makes use of the newIGame
interface added in 3.0.0.
3.0.0 - 2023-05-09
This is a major release with big changes featuring Wine, Bottles and Proton support for GOG, EGS and Origin. This release also replaces System.IO.Abstraction
with NexusMods.Paths
from the new Nexus Mods App, changes how results are handled and re-adds Xbox Game Pass support.
Breaking Changes:
- Reworked the constructors of all handlers and removed most overloads. All handlers now have a single constructor with no default values.
- Updated
FindAllGames
to returnOneOf<TGame, ErrorMessage>
instead ofResult<TGame>
(using the OneOf library). - Replaced
System.IO.Abstraction
withNexusMods.Path.IFileSystem
.- Paths are now of type
AbsolutePath
instead ofstring
.
- Paths are now of type
- Changed
AHandler<TGame, TId>
to requireTId : notnull
. - Added
IGame
interface and changedAHandler<TGame, TId>
to requireTGame : IGame
. - Removed the extension functions
OnlyGame
andOnlyError
. - Changed all game Ids to be value objects using Vogen.
- Changed
FindAllGamesById
to returnIReadOnlyDictionary<TGame, TId>
instead ofIDictionary<TGame, TId>
.
(Hopefully) non-breaking changes:
- Re-added Xbox Game Pass.
- Added
Func<TGame, TId> IdSelector
andIEqualityComparer<TId>? IdEqualityComparer
toAHandler<TGame, TId>
. These can be used to construct key-value types like a dictionary. - Added
WindowsRegistry.Shared
for a shared instance ofIRegistry
. - Wine: added
GetUserName
,ProtonWinePrefix
will now usesteamuser
. - Enabled Trimming.
How to upgrade:
The transition from Result<TGame>
to OneOf<TGame, ErrorMessage>
should be straight forward. You can use the provided helper methods for matching like result.Match(game => { }, error => { })
or result.Switch(game => { }, error => { })
depending on your needs. I've also added some extension methods to make the transition easier:
bool IsGame()
bool IsError()
TGame AsGame()
ErrorMessage AsError
bool TryGetGame(out TGame)
bool TryGetError(out ErrorMessage)
Store handlers, like GOGHandler
, now require an implementation of NexusMods.Paths.IFileSystem
, instead of System.IO.Abstraction.IFileSystem
. You can use the shared instance at NexusMods.Path.FileSystem.Shared
, if you want to use the real file system.
For testing, you can either mock NexusMods.Paths.IFileSystem
, or use NexusMods.Paths.InMemoryFileSystem
. If you need to do more in-depth testing, you can also use the NexusMods.Paths.TestingHelpers
package.
Since AHandler<TGame, TId>
has changed, you might need to update the constraints for TId
, if you use generics. Simply add where TId : notnull
to the constraints. All Ids have been replaced to using value objects. For example: instead of having long id
for GOGGame
, it's now GOGGameId id
. You can still get the value using id.Value
, which is still a long
.
How to use with Wine on Linux:
See the updated README.
2.6.0 - 2023-03-07
- removed support for
net6.0
- add support for finding Wine prefixes (check the README)
- Steam: added new default installation directories:
~/.steam/debian-installation
(apparently used on Debian/Ubuntu systems)~/.var/app/com.valvesoftware.Steam/data/Steam
(used by the flatpak installation)~/.steam/steam
(legacy installation, links to another installation)
2.5.0 - 2023-01-17
Added support for EA Desktop. Read the wiki entry before using.
2.4.0 - 2023-01-13
Although this release contains some API changes and a lot of internal changes, consumers will likely not be affected.
- Core:
AHandler.FindAllGamesById
now returnsIDictionary<>
instead ofDictionary<>
- Core: changed
Result<TGame>
from a record struct to a custom readonly struct - Steam: added
SteamGame.GetManifestPath
that returns the absolute path to the parsed manifest. This is useful if you need to extract more information from the manifest, after the game has been found. - Internal: restructured the project and reworked all tests
2.3.0 - 2022-12-16
- Steam: added
~/.steam
and~/.local/.steam
as possible default Steam directories on Linux - Steam: added constructor that accepts a custom Steam path in case the library can't find it
- upgrade to C# 11
- upgrade
System.IO.Abstractions
to v19.1.1
2.2.2 - 2022-11-11
FindAllGamesById
will no longer throw an exception for duplicate IDs
2.2.1 - 2022-10-21
Small update that changes the equality comparer of the dictionary returned by EGSHandler.FindAllGamesById
and OriginHandler.FindAllGamesById
to StringComparer.OrdinalIgnoreCase
.
2.2.0 - 2022-10-21
This update adds some utility functions you can use. I've also created a new package GameFinder.Common
where all those new utility functions live:
- added
AHandler
an abstract class that all store handlers inherit:AHandler.FindAllGames
: same function as beforeAHandler.FindAllGamesById
: wrapsFindAllGames
and returns aDictionary<TId, TGame>
AHandler.FindOneGameById
: if you just need to find 1 game
- added some extension methods that work with
IEnumerable<Result<TGame>> results
:IEnumerable<TGame> OnlyGames
: returns only non-null games and discards the restIEnumerable<string> OnlyErrors
: returns only non-null errors and discards the rest(TGame[] games, string[] errors) SplitResults
: splits the results into two arrays
2.1.0 - 2022-10-21
Minor update after the major rework:
- everything was made safer and less functions will throw (you should still wrap the
FindAllGames
function call) - API changed a bit:
FindAllGames
will now return a readonly record struct instead of a named tuple - lots of internal changes and more tests
2.0.1 - 2022-10-19
- Origin: fix parsing manifests with duplicate key-value entries
2.0.0 - 2022-10-15
Major rework of all packages:
- removed
netstandard2.1
target - added
net7.0
target - added
IRegistry
interface withWindowsRegistry
andInMemoryRegistry
implementations - added runtime platform check in all packages
- deprecated the Bethesda.net and Xbox packages (see README for more information)
- removed logging from all packages
- removed the
GameFinder
package (it's not needed anymore) - simplified the public APIs
1.8.0 - 2022-06-27
- Fix SteamHandler not finding any Libraries when there are no external libs
- Remove .NET 5 target
- Upgrade dependencies
1.7.3 - 2022-05-14
- Steam: parsing is now more relaxed, only required values are
appid
,installdir
andname
1.7.2 - 2021-11-10
- GOG: most stuff is no longer required from the registry, the only values that actually matter are
gameID
,gameName
,path
- Xbox: updated Windows SDK to 10.0.20348.0
1.7.1 - 2021-08-19
- GOG:
productID
from registry is no longer required
1.7.0 - 2021-08-09
- Added support for .NET 6
1.6.4 - 2021-08-03
- Steam: Added support for Unix systems
1.6.3 - 2021-07-30
- Improved Regex performance by making it
static readonly
and usingRegexOptions.Compiled
- Steam: Removed parsing the
mounted
value inlibraryfolders.vdf
files
1.6.2 - 2021-07-17
- Steam: Fixed Regex for parsing old
libraryfolders.vdf
files - Origin: Fixed returning invalid Paths
- Origin: Fixed looking for Games with an empty ID
- Origin: Fixed registry lookup with 64bit view
1.6.1 - 2021-07-10
- Origin Handler Documentation
- Release Workflow because NuGet doesn't like it when a new project suddenly exists
1.6.0 - 2021-07-10
This update reverted the change from v1.5.0 because it did not perform very well, made the code worse and harder to read and felt like a quick and dirty fix. The reason why I even added Result<T>
was to let the consumer of this library, which should be an application, know what went wrong by returning something akin to Rust's error propagation. Instead of having an exception whenever something went wrong, it would just add another error as a string
to a List<string>
inside the Result<T>
which the consumer can access and print out. I have removed all of this code and replaced it with simple logging using ILogger
from Microsoft.Extensions.Logging
. This way you can simply pass a ILogger
to the constructor of a Store Handler and it will log to it. Since the consumer of this library is an application which likely has some form of logging going on, this should be very easy to implement.
Additionally I finally went ahead and added Origin Support, see the README for more information.
- Using
ILogger
fromMicrosoft.Extensions.Logging
instead of customResult<T>
to let the user know what went wrong
- Added Origin Support, see README for more information
1.5.3 - 2021-06-13
- Steam: Fixed double slashes in Paths (#8)
- Steam: Improved parsing of
config.vdf
,libraryfolders.vdf
and*.acf
files
1.5.2 - 2021-06-09
- Steam, GOG and EGS Handlers will not also include init errors in the final result
- Steam: Added support for new
libraryfolders.vdf
format introduced in update 1623193086 (2021-06-08). See README for more information.
1.5.1 - 2021-06-06
- Steam:
libraryfolders.vdf
will now also get parsed (#7)
1.5.0 - 2021-05-29
All functions are now no-throw and return Return<T>
for better error handling and error aggregation. Checkout the example on how to use this: Link.
1.4.1 - 2021-03-26
- Include snupkg in output
- Skip broken EGS manifest files
- Fixed
exe
andexeFile
values not being optional for GOGHandler. DLCs don't have this set.
1.4.0 - 2021-03-26
- All StoreHandlers are less strict about missing directories
- Update Newtonsoft.Json to 13.0.1
- Update Windows SDK to 10.0.19041.0
1.3.1 - 2021-03-14
- Added helper DTOs to XboxHandler
- GameFinder.Example will also log to file
- Replaced Placeholder Exceptions in EGSHandler with EGSExceptions
- Fixed AccessDeniedException in XboxHandler when trying to access Package properties
1.3.0 - 2021-03-13
- XboxHandler for finding games installed via Xbox Game Pass App (or all UWP apps, see README for more information)
- Example application using all game handlers
1.2.0 - 2021-03-13
- Updated project structure: each StoreHandler now has it's own package.
1.1.0 - 2021-02-21
- Added support for
netstandard2.1
1.0.0 - 2021-02-21
- Everything. This is the first release.