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>
69 lines
2.2 KiB
C#
69 lines
2.2 KiB
C#
using System.Collections.Generic;
|
|
using Playnite.SDK.Data;
|
|
|
|
namespace PunktfunkSync
|
|
{
|
|
// The on-disk contract with the Punktfunk `playnite` plugin. Keep these property names in lockstep
|
|
// with `src/export-schema.ts` (ExportedGame / LibraryExport). Serialized via the Playnite SDK's
|
|
// `Serialization.ToJson`, so `[SerializationPropertyName]` pins the JSON keys regardless of the
|
|
// serializer's default casing.
|
|
|
|
public class ExportedGame
|
|
{
|
|
// Playnite's stable game Guid ("d"-format, lowercase with dashes) — the reconcile external_id.
|
|
[SerializationPropertyName("id")]
|
|
public string Id { get; set; }
|
|
|
|
[SerializationPropertyName("name")]
|
|
public string Name { get; set; }
|
|
|
|
[SerializationPropertyName("installed")]
|
|
public bool Installed { get; set; }
|
|
|
|
[SerializationPropertyName("hidden")]
|
|
public bool Hidden { get; set; }
|
|
|
|
// Library source name ("Steam", "GOG", "Epic", emulator name…) or null.
|
|
[SerializationPropertyName("source")]
|
|
public string Source { get; set; }
|
|
|
|
[SerializationPropertyName("platforms")]
|
|
public List<string> Platforms { get; set; }
|
|
|
|
// ABSOLUTE paths on the host box (already resolved from Playnite's database-relative form), or
|
|
// null. A remote (http) art URL is passed through verbatim.
|
|
[SerializationPropertyName("cover")]
|
|
public string Cover { get; set; }
|
|
|
|
[SerializationPropertyName("background")]
|
|
public string Background { get; set; }
|
|
|
|
[SerializationPropertyName("icon")]
|
|
public string Icon { get; set; }
|
|
}
|
|
|
|
public class PlayniteInfo
|
|
{
|
|
[SerializationPropertyName("version")]
|
|
public string Version { get; set; }
|
|
|
|
[SerializationPropertyName("mode")]
|
|
public string Mode { get; set; }
|
|
}
|
|
|
|
public class LibraryExport
|
|
{
|
|
[SerializationPropertyName("schema")]
|
|
public int Schema { get; set; }
|
|
|
|
[SerializationPropertyName("generatedAt")]
|
|
public string GeneratedAt { get; set; }
|
|
|
|
[SerializationPropertyName("playnite")]
|
|
public PlayniteInfo Playnite { get; set; }
|
|
|
|
[SerializationPropertyName("games")]
|
|
public List<ExportedGame> Games { get; set; }
|
|
}
|
|
}
|