This commit is contained in:
2026-08-08 18:00:34 +02:00
commit 41e307b5c1
28 changed files with 4728 additions and 0 deletions
+167
View File
@@ -0,0 +1,167 @@
# Cyberpunk 2077 Vortex extension for Linux (Proton / SteamTinkerLaunch)
![Tile artwork](assets/gameart.png)
A Vortex game extension for Cyberpunk 2077 that works when Vortex itself runs
inside a Wine/Proton prefix, e.g. launched through SteamTinkerLaunch on Linux
Mint.
## Why the community extension crashes here
The official/community extension discovers the game with Vortex's
`GameStoreHelper.findByAppId(...)`. Inside a Proton prefix that helper reads the
Windows Steam client's config:
```
ENOENT: no such file or directory, open 'C:\Program Files (x86)\Steam\config\libraryfolders.vdf'
```
SteamTinkerLaunch puts `steamclient.dll` and friends into
`C:\Program Files (x86)\Steam` inside the prefix, but never writes
`config\libraryfolders.vdf` — the real Steam libraries are native Linux
directories such as `/home/<user>/.steam/steam` and `/mnt/<disk>/SteamLibrary`.
The read throws, nothing catches it, and Vortex reports it as
`unrecoverable error` in the renderer, taking the whole UI down.
This extension fixes both halves of that:
1. **Own discovery.** It never calls `GameStoreHelper`. It reads the real Linux
Steam configuration through Wine's `Z:` drive (which maps `/`), parses
`libraryfolders.vdf` and `appmanifest_1091500.acf`, and verifies
`bin/x64/Cyberpunk2077.exe` before reporting a game path.
2. **Prefix repair.** It recreates the missing
`C:\Program Files (x86)\Steam\config\libraryfolders.vdf` inside the prefix,
pointing at the real libraries as `Z:\...` paths. That stops Vortex core's own
Steam scan from crashing, which also unbreaks other extensions. An existing
file is never overwritten unless you ask for it.
## Requirements
- Vortex running in a Wine/Proton prefix (tested with the SteamTinkerLaunch
Vortex prefix at `~/.config/steamtinkerlaunch/vortex/compatdata/pfx`)
- Node.js 22+ on the Linux side, to build and install
- Cyberpunk 2077 installed through Steam
## Install
```bash
npm install
tools/install-extension.sh
```
The script builds `dist/`, copies it to
`<prefix>/drive_c/users/steamuser/AppData/Roaming/Vortex/plugins/game-cyberpunk2077-linux/`,
and repairs the prefix's `libraryfolders.vdf`. Restart Vortex afterwards and
manage **Cyberpunk 2077 (Linux/Proton)**.
Options:
| Flag | Effect |
| --- | --- |
| `--prefix <path>` | Use a different Wine prefix (default: the SteamTinkerLaunch Vortex prefix) |
| `--force-shim` | Rewrite `libraryfolders.vdf` even if one already exists |
| `--disable-bundled` | Rename Vortex's bundled `game-cyberpunk2077` stub to `.disabled`, so only this extension offers Cyberpunk |
Repairing the prefix alone, without installing the extension:
```bash
node scripts/repair-prefix.mjs --dry-run # show what would be written
node scripts/repair-prefix.mjs # write it
```
Run the repair *before* starting Vortex if Vortex currently dies on launch.
## Uninstall
```bash
rm -rf "$HOME/.config/steamtinkerlaunch/vortex/compatdata/pfx/drive_c/users/steamuser/AppData/Roaming/Vortex/plugins/game-cyberpunk2077-linux"
```
The `libraryfolders.vdf` shim can stay — Vortex core needs it. Delete it with:
```bash
rm "$HOME/.config/steamtinkerlaunch/vortex/compatdata/pfx/drive_c/Program Files (x86)/Steam/config/libraryfolders.vdf"
```
## Configuration
Set `CYBERPUNK2077_PATH` to a Linux path to skip Steam discovery entirely, for
example a GOG copy:
```
CYBERPUNK2077_PATH=/mnt/games/GOG/Cyberpunk 2077
```
The variable has to be visible to the Vortex process inside the prefix, so set it
in the SteamTinkerLaunch launch options for Vortex, not just in your shell.
## Game id and Nexus downloads
The extension registers the game id `cyberpunk2077linux`, deliberately different
from the bundled `cyberpunk2077` stub so the two can coexist. `nexusPageId` is
still `cyberpunk2077`, so mod pages and `nxm://` downloads from the Cyberpunk
Nexus section resolve normally.
## Mod layouts handled
The installer routes archive contents to the right place and strips wrapper
folders such as `Cool Mod v1.2/`:
| Archive contains | Installed to |
| --- | --- |
| a game-root tree (`archive/`, `bin/`, `r6/`, `red4ext/`, `mods/`, `engine/`) | the game directory, wrapper folder stripped |
| loose `.archive` / `.archive.xl` files | `archive\pc\mod\` |
| `init.lua` plus its folder | `bin\x64\plugins\cyber_engine_tweaks\mods\<folder>\` |
| loose `.reds` files | `r6\scripts\<mod name>\` |
| `info.json` plus `archives/` (REDmod) | `mods\<folder>\` |
| a bare `.dll` | `red4ext\plugins\<mod name>\` |
| anything else | copied verbatim, so nothing is silently dropped |
Files that sit beside a detected game-root tree (readmes, screenshots) are left
out of the deployment.
## Launching the game
Start Cyberpunk 2077 from Steam as usual. Vortex runs in its own prefix, so its
"launch game" button would start the executable in the wrong prefix; the
extension registers the executable for detection only.
## Development
```bash
npm test # unit tests (vitest)
npm run typecheck # tsc --noEmit
npm run build # bundle to dist/
node scripts/smoke-load.cjs # load the built bundle with a stubbed vortex-api
```
The logic is split so it can be tested without Vortex or Wine:
| File | Responsibility |
| --- | --- |
| `src/vdf.ts` | Valve KeyValues parser/serialiser |
| `src/winePath.ts` | Linux ⇄ `Z:` path translation, separator-aware joins |
| `src/discovery.ts` | Steam roots, library folders, app install dir, game verification |
| `src/steamShim.ts` | Builds and writes the `libraryfolders.vdf` shim |
| `src/installer.ts` | Maps a mod archive's file list to install instructions |
| `src/gameart.ts` | Generates the tile artwork and encodes it as a PNG |
| `src/index.ts` | Vortex registration glue (the only file that touches `vortex-api`) |
Regenerating the artwork after editing `src/gameart.ts`:
```bash
npm run gameart # rewrites assets/gameart.png
```
`npm run build` renders the same image straight into `dist/`, so the two never
drift; the render is deterministic, so rebuilds produce byte-identical output.
## Licence and trademarks
Public domain, released under the [Unlicense](https://unlicense.org/) - see
`LICENSE`. Copy it, change it, ship it, sell it, no attribution needed.
Cyberpunk 2077 is a trademark of CD PROJEKT S.A.; this is an unofficial modding
tool with no affiliation to CD PROJEKT S.A. or Nexus Mods. No game or Nexus
assets are redistributed here - the tile artwork is generated by
`src/gameart.ts` and is covered by the same public domain dedication.