Comments (2)
Thanks for taking the time to write this up. Let's break this down and start with the big design decisions:
GameFinder history and design
I originally made this library for Wabbajack, but since then, it has been used in various other projects. However, almost all the dependents are modding related. Most of the time, the only thing they are interested in is the installation location. Once they have that, they start doing their own thing. This is why the *Game
records only have 3 properties: an identifier, a name, and the installation path.
I did recently add some utility functions like SteamGame.GetManifestPath
and EADesktopGame.GetInstallerDataFile
which can be helpful for library consumers that need a bit more data.
The development of this library has been heavily influenced by the library consumers. So far, they only require the installation path, which is why GameFinder only returns the bare minimum. I know that a launcher requires more information. I've previously been involved with Playnite and know how much additional information it grabs from the various supported libraries.
More data
The core issue is that GameFinder doesn't know what data the consumer wants. Currently, GameFinder returns the absolute minimum. If you go back in time enough, you will actually find that previous versions of the library extracted almost everything. For Steam, it extracted all values from the .acf
file, for EGS it deserialized the entire .json
with all values into a class and for GOG it parsed all registry values.
I stopped doing that because it was hell to maintain. The GOG implementation would regularly break, because some registry keys wouldn't exist for some users, and Steam changed their format like three times within a month. Grabbing only the bare essentials makes the library easier to test and maintain.
That being said, what can be done? I would look into adding more utility functions. Provide the bare essentials and have some method that you can use to request more data.
However, it seems rather odd to force the library's client to reinvent the wheel of often re-parsing a file/regkey to get data that could easily have been collected the first time through in this library.
This is true for SteamGame.GetManifestPath
which returns the path to the manifest that got parsed beforehand. However, how else should this API be designed? For Steam, it might be possible to deserialize the .acf
file and put the deserialized object into the SteamGame
object, however this might not work with everything. Take the EA Desktop implementation as an example. The decrypted file is just a JSON file, however I'm deserializing it into an object. If a consumer were to request more data, would the EADesktopGame
have the entire JSON contents as a private field or something, that can be used to extract more information?
Also, something I forgot to write down in the docs: all the Store handler functions are pure functions. None of the store handlers have an internal mutable state. They are only classes because it makes configuring stuff easier using constructors. I'm very reluctant on adding state that can be mutated and accessed, if none of the library consumers are using it.
Access APIs or perform web scrapes to collect additional data.
I want to keep the library from accessing the web if possible. Furthermore, I'm considering adding the Origin API as a static helper method, but this won't be the default.
Ensure compatibility for existing clients of this library.
This isn't the Windows API or C++, we don't need a FindGames
and FindGamesEx
method to not break compatibility or the ABI. Following SemVar and providing good Changelogs with information on how to upgrade is sufficient.
Adding more store handlers
As pointed out before, GameFinder mostly followed the requests of library consumers, which were all modding tools. None of the additional stores, you have listed, have games supported by these tools. I recently marked the Xbox Game Pass implementation as deprecated, because no one was using it and maintaining it had become a chore.
This is another issue: I don't even use all of these stores. If something breaks, or someone requests a new store implementation, I have to install it and start researching. I hate the Epic Games Store and uninstalled it the moment I was done with it. I'm glad the implementation is still working, because I won't be installed the EGS any time soon.
If you want to add more store handlers to GameFinder, I suggest creating individual issues, where we can discuss the store in detail. Just note that I won't allow 20 new implementations any time soon. The current code base is rather small and most implementations are straight forward. Adding more store handlers and more complexity requires more tests and makes the library harder to maintain.
Individual store handler stuff
EA Desktop
Remove or revise the "Use the registry" alternative from the EA Desktop wiki. It seems backwards: are you suggesting to search all the user's disks for "installerdata.xml" files just to find the registry entries?
Maybe you don't want to find every single game, or you only need a known amount of games. In this case, you can just use the registry key from the
installerdata.xml
file. Every EA game has a folder called__Installer
which contains aninstallerdata.xml
file which can give you the correct registry key [...]
This alternative is for tools that only need to find one or a handful of known games. As an example: let's assume you make a tool for Titanfall 2, and you need to find the installation path programmatically. My method of breaking the encryption might be a bit overkill. Instead, you can, as the tool programmer, open the installerdata.xml
file on your machine and extract the registry key. This key can be hardcoded into the tool for a simple registry lookup to find the game installation location.
I'm not suggesting that the tool searches the entire disk for installerdata.xml
, but rather the programmer just extracts the required information from their file. This registry key doesn't change.
GOG
Instead of the registry, use the SQLite database (%ProgramData%\GOG.com\Galaxy\storage\galaxy-2.0.db).
I didn't know this file existed, when I created my implementation. However, this an embedded application database, meaning the schema can change with every update. I'm also not so keen on bundling an SQLite client with the store handler. I might consider this, if this were the only method of accessing the required data, but at the moment, I don't see the benefit over using the registry. You can create a separate issue for this, but this would be very low priority.
Other stuff
Add GLC to the Other Implementation sections.
Will do. Also, a quick reminder: GameFinder uses the MIT license, which is very permissive but still requires preservation of copyright and license notices, meaning you have to include the copyright notice and the permission notice in all copies or substantial portions of the Software.
from gamefinder.
Thanks very much for the in-depth response. I thought you might feel that way to one extent or another, and I totally understand that point of view. I'll close this issue. Take care!
from gamefinder.
Related Issues (20)
- Support Heroic Games Launcher
- Change 'Can't find Manifest Folder / Directory' Errors to warnings HOT 1
- WMIHelper can't handle multiple result objects HOT 4
- Unknown hard error when parsing some Steam manifests HOT 3
- UbiConnect Support HOT 1
- Battle.net (Activision/blizzard) Launcher needs support HOT 1
- Fix Steam `AppManifestParser`
- Fix `BottlesWinePrefixManager`
- GameFinder fails to parse Steam Manifest if there is a quotation mark used in a drive label HOT 1
- GameFinder stops looking for Steam games if any Steam library isn't available HOT 2
- EGS: consider using different ID type HOT 6
- Mark every project as trimmable
- Add meta package
- EA Desktop: add Wine support HOT 4
- Wine: `/z/*` should point to `/*`
- Decrypt IS file failed HOT 11
- GPL Licensed component HOT 4
- Allow multiple log message types (besides ErrorMessage) HOT 1
- Replace Moq with NSubstitute
- Game Discovery Issue on Steam HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from gamefinder.