6694be9848
A two-part Punktfunk plugin that syncs the Playnite library into the host
game library as the `playnite` provider:
- exporter/ — a minimal C# Playnite GenericPlugin ("Punktfunk Sync") that
writes punktfunk-library.json on every library change. Reading Playnite's
live-locked LiteDB from outside isn't robust, so this adapter runs inside
Playnite. Builds net462 via reference assemblies; packaged as a .pext.
- src/ — the TS plugin (on @punktfunk/host, rom-manager shape): watches the
export, embeds covers as data URLs, reconciles via
PUT /library/provider/playnite, with a console-hosted web UI + standalone
fallback + CLI. Launch = playnite://playnite/start/<id>, run by the host
in the interactive session so Playnite performs the real launch.
Verified locally: backend tsc + 23 tests + biome clean, SPA build, C#
exporter build + .pext pack.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
70 lines
2.5 KiB
Markdown
70 lines
2.5 KiB
Markdown
# Punktfunk Sync — Playnite exporter
|
|
|
|
The Playnite side of [`@punktfunk/plugin-playnite`](../README.md): a minimal
|
|
[GenericPlugin](https://api.playnite.link/docs/tutorials/extensions/genericPlugins.html) that writes
|
|
your library to `punktfunk-library.json` whenever it changes. The Punktfunk plugin on the host reads
|
|
that file and reconciles it into the streaming library.
|
|
|
|
It exists because Playnite keeps its library database (LiteDB) open and locked while running, so the
|
|
only robust way to read the library — with correct install state, art paths and metadata — is from
|
|
*inside* Playnite. This plugin does exactly that and nothing else: no network, no settings, no UI.
|
|
|
|
## What it writes
|
|
|
|
On startup, on every `OnLibraryUpdated`, and (debounced) on any per-game add/update/remove, it writes:
|
|
|
|
```
|
|
%APPDATA%\Playnite\ExtensionsData\<plugin-guid>\punktfunk-library.json
|
|
```
|
|
|
|
Shape (kept in lockstep with `../src/export-schema.ts`):
|
|
|
|
```jsonc
|
|
{
|
|
"schema": 1,
|
|
"generatedAt": "2026-07-18T21:00:00Z",
|
|
"playnite": { "version": "10.x", "mode": "Desktop" },
|
|
"games": [
|
|
{
|
|
"id": "e3b0c442-98fc-1c14-9afb-4c8996fb9242", // Playnite Guid = reconcile external_id
|
|
"name": "Hollow Knight",
|
|
"installed": true,
|
|
"hidden": false,
|
|
"source": "Steam",
|
|
"platforms": ["PC (Windows)"],
|
|
"cover": "C:\\Users\\me\\AppData\\Roaming\\Playnite\\library\\files\\ab\\cover.jpg",
|
|
"background": null,
|
|
"icon": null
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
Art paths are **absolute** (resolved via `IPlayniteAPI.Database.GetFullFilePath`). Filtering
|
|
(installed-only, hidden, per-source) happens on the Punktfunk side, so the export is the full library.
|
|
|
|
You can also trigger a write by hand: Playnite **main menu → Punktfunk Sync → Export library to
|
|
Punktfunk now**.
|
|
|
|
## Install (for users)
|
|
|
|
Double-click `punktfunk-sync.pext` — Playnite installs it like any add-on — and restart Playnite.
|
|
Grab the `.pext` from the repo's [CI artifacts](https://git.unom.io/unom/punktfunk-plugin-playnite/actions).
|
|
|
|
## Build
|
|
|
|
Targets .NET Framework 4.6.2 (Playnite's runtime). Thanks to
|
|
`Microsoft.NETFramework.ReferenceAssemblies` it builds with the plain .NET SDK on any OS — no Windows
|
|
or MSBuild needed:
|
|
|
|
```sh
|
|
dotnet build PunktfunkSync.csproj -c Release
|
|
# output: bin/Release/PunktfunkSync.dll + extension.yaml (PlayniteSDK.dll is provided by Playnite)
|
|
```
|
|
|
|
Package the `.pext` (a zip of the two files):
|
|
|
|
```sh
|
|
( cd bin/Release && zip -j ../../punktfunk-sync.pext extension.yaml PunktfunkSync.dll )
|
|
```
|