-
Notifications
You must be signed in to change notification settings - Fork 168
Add GameFinder integration and YAML game definitions extension #19335
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Integrate GameFinder as an internal extension that detects games across
multiple store fronts (Steam, GOG, Epic, Xbox). Game extensions can now
opt-in to automatic detection by specifying store IDs in their registration.
Changes:
- Add IGameFinderIds interface and gameFinder property to IGame
- Create src/extensions/gamefinder/ with store handlers for Steam, GOG,
Epic, and Xbox
- Add GameFinderCache for indexed lookup by store IDs
- Hook into quickDiscovery() to check gameFinder before queryPath/queryArgs
- Add yarn detect-games CLI script for testing
- Add neverthrow and fast-xml-parser dependencies
Game extensions can now use:
gameFinder: { steam: '1086940', gog: '1456460669' }
instead of or in addition to queryPath/queryArgs.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Introduces a new extension that allows game definitions to be expressed in YAML format, reducing boilerplate code duplication. Store IDs are defined once and auto-populated to queryArgs, gameFinder, details, environment, and requiresLauncher. Includes JSON Schema validation, transformer logic, and a sample Skyrim SE YAML definition for demonstration. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change to subfolder structure: games/<game-id>/game.yaml with assets - Remove redundant requiredFiles from tools (defaults to [executable]) - Update schema to document default behavior for requiredFiles - extensionPath now points to game subfolder for logo resolution Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy logos and game art from existing game-skyrimse extension. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Renamed CK.png -> ck.png and SKSE.png -> skse.png to avoid case-sensitivity issues on Linux filesystems. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Schema now accepts integers for steam/gog IDs (YAML parses unquoted numbers as integers) - Transformer normalizes store IDs to strings before use - Updated sample YAML to remove all unnecessary quotes - Registry paths no longer need escaped backslashes without quotes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Configure InstallAssets.json to copy YAML files, JSON schema, and image assets from src/extensions/game-definitions/ to output. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Reduces total image size from ~79KB to ~39KB (~50% reduction). Electron/Chromium has native WebP support. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add info.json at extension root (required by registerGame) - Update transformer to prefix logo paths with relative game directory - Replace Ajv validation with manual validation to avoid version conflicts - Add game-definitions to staticExtensions for proper loading - Remove unused ajv dependency from package.json The registerGame function overwrites game.extensionPath with the extension's directory, so logo paths must be relative to that root (e.g., "games/skyrimse-yaml/gameart.webp" instead of "gameart.webp"). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Doesn't this remove a lot of the utility game extensions have to include additional options and parameters? The only thing I would change with the current model personally is move things like INI and plugins txt path resolution into the JS file rather than keeping it duplicated in the 7-8 gamebyro extensions. It also seems to remove the ability to register all the other features you might want with a game. New pages, tests, notifications, steps to prepare the game for modding, toolbar buttons, etc. I have to be honest, I don't really see the problem this is solving? What's wrong with JSON or JS? Switching to a static Yaml file removes conditional logic. Like if you need to resolve a different EXE file based on game store, locale, etc. Same with launch arguments. I don't want to be too critical as I'm sure there's something I've missed but it seems like a heavily simplified version of something that has been working well for years. "If it ain't broke" and all that... Please take this with a bit of a pinch of salt as I'm not a professional developer but this is just my thoughts as a third party consumer of the Vortex API |
erri120
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
High level feedback to discuss:
The PR should be split into two separate PRs to reduce review overhead. One to add the gamefinder extension and one for the game-definitions extension. While they might depend on each other, they don't need to be merges as one.
For the gamefinder extension specifically, I don't think it should exist in this form. It's currently a slimmed down AI-assisted TypeScript port of my GameFinder C# library. As the author of that library, I can tell you that the GameFinder code is not worth porting over. The only worthwhile code and information from my library that could be used here are all of the edge-cases that have accumulated over the years on where to find files and how to parse them. Different default paths for Steam on various Linux installations or information like manifest version changes that require different handling.
The only "special sauce" that my library has over other game detection systems is the tight integration with the NexusMods.Paths library, which I also authored. Various abstractions over the file system and the registry allowed the GameFinder library to be used seamlessly on Linux for Windows games, something that hasn't been carried over to this new extension because we don't have that paths library for Vortex.
I have many regrets for the code I've written for my GameFinder library. There are many things I'd do differently if I were to rework it, which I've tried to do a couple times with no progress. What pains me to see is that my arguably bad decisions have now propagated into this new extension with the port.
With Vortex being the tech-debt ridden mess it is, and with the new found intent to focus development on Vortex and bring the codebase up to stuff, I don't believe we should be porting my bad decisions from three years ago to Vortex, especially since Vortex already has game stores.
Steam, EGS, GOG, Xbox, Origin, UPlay are already supported by Vortex. Code for those game stores exists in src/util for Steam and EGS, and in extensions/gamestore-* for the others. There is no point in having the same functionality twice, especially since the old code is already used and battle-tested by all Vortex users.
I believe we should merge the existing game store extensions into one core extension and get the old code updated and modernized with maybe some new APIs.
IDCs
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm glad that I'm not the only reviewer to highlight this - why are we re-writing core functionality that has been functioning correctly for a decade?
Surely if we want to add new functionality such as the YAML integration, or fix linux issues, we can do so within the confines of GameStoreHelper without creating an entirely new plugin/extension. Alternatively if we want a single extension to cater for all stores, we can flatten the existing gamestore extensions into a single plugin/extension.
Re-writing the whole thing is bound to raise issues we have solved years ago in the previous system.
|
Specifically on Skyrim SE, I noticed this method does not seem to include the stopPatterns. Those are absolutely essential for properly installing many mods. An author simply including a "Data" folder would break the mod install entirely. This is one example of critical functionality for games that's not available in this YAML format. I like the idea behind this new method. But typically "stub" extensions are not sufficient to support most games. Bethesda games are built with modding in mind, so they are actually quite simple extensions (just for the actual game, not LOOT, etc). This method wouldn't work for a Unity or Unreal Engine game, for example. Too many modTypes in different paths. Most games need multiple installers with careful indexing to fix packaging issues. |
The original code doesn't include Stop Patterns either, those are in a different extension 🤦 |
This is a good question, my main idea is this: the original Skyrim SE plugin for this behavior is Javascript, not TS, not even well defined Javascript. So the idea here, is instead of writing TS code for every bit of functionality, for every game, we implement it as data, then we can re-interpret the pattern as we rework parts of Vortex. For the most part this work is a prototype to discuss how we could implement this behavior. I'd love in the future to implement stop patterns (which are also mostly data) as YAML. Code rots over time, and Vortex has a lot of rotted code. Data doesn't rot, or when it does we can simply write a data transformer to translate it to a new format. |
|
Correct. Stop patterns are in a different file. My mistake. But the point is that most games are not as simple as skyrimse. You're not wrong about Vortex having some suboptimal code, but I think using hyperbolic words like "rotted" isn't really helpful. The basic boilerplate code on game extensions is certainly not "rotted", so I'm not sure that characterization applies to the goals of this PR. |
Rationale
Most of the games included with Vortex are pretty simple, just metadata, ids and registry keys. Many of these extensions are in JS not TS, and use bluebird and other outdated programming libraries. In addition these extensions don't properly detect Linux installs. This PR fixes this by creating a new YAML based game definition. This definition includes automatic game location, works with Steam on Linux, and provides a schema for the YAML (so VS Code type checks the data).
For now this creates a new game called "Skyrim YAML Demo". After this PR is reviewed and approved, I'll remove the old SkyrimSE instance, and rename this definition. We can then go through and clean out all the other games that follow these same patterns.
Summary
GameFinder Integration
A new internal extension that detects installed games across multiple storefronts:
libraryfolders.vdfandappmanifest_*.acffilesappxmanifest.xmlGame extensions can now opt-in to automatic detection by specifying store IDs:
This is checked during quickDiscovery() before falling back to queryPath/queryArgs.
YAML Game Definitions
A new extension that allows game definitions to be expressed in YAML instead of JavaScript, dramatically reducing boilerplate. Store IDs are defined once and auto-populated to queryArgs, gameFinder, details, environment, and requiresLauncher.
Example (games/skyrimse-yaml/game.yaml):
The extension transforms this into a full IGame registration with all the repetitive fields auto-generated.
Other Changes
Test plan