itchio-opengamepadui-plugin/README.md

90 lines
4.3 KiB
Markdown
Raw Normal View History

2026-08-05 17:27:43 -03:00
# OpenGamepadUI-itch
An itch.io library plugin for [OpenGamepadUI](https://github.com/ShadowBlip/OpenGamepadUI),
built against itch's official [butlerd](https://itch.io/docs/butler/launcher-integration.html)
JSON-RPC launcher daemon (the same integration path the official itch.io app
uses under the hood) rather than screen-scraping the itch desktop app.
Owned games, install state, install/update/uninstall, and launching are all
driven through butlerd. This plugin spawns `butler daemon --json ...` itself,
so the itch.io desktop app doesn't need to be installed at all — only a
`butler` binary, which this plugin downloads automatically on first run from
itch's own [broth](https://broth.itch.zone/) distribution channel.
## Setup
1. Build and install the plugin (see below).
2. Generate an API key at <https://itch.io/user/settings/api-keys>.
3. Open the plugin's settings screen in OpenGamepadUI and paste it in.
API key login was chosen over the OAuth + PKCE flow butlerd also supports,
because OAuth requires registering a redirect URI / custom URL scheme with
itch.io for a specific app, which doesn't make sense for a self-built,
unpublished plugin. If you're distributing this plugin publicly, switching
to OAuth is worth doing — see `Profile.LoginWithOAuthCode` in the
[butlerd launcher guide](https://itch.io/docs/butler/launcher-integration.html).
## Requirements
See the [OpenGamepadUI requirements](https://github.com/ShadowBlip/OpenGamepadUI#requirements).
This plugin additionally needs `unzip` on the host (used to unpack the
downloaded `butler` binary).
## Building
Same as any other OpenGamepadUI plugin:
```bash
make help
make build
make install
```
## Known limitations / good next steps
This was put together from butlerd's public spec rather than against a
running instance, so a few corners are simplifications rather than the
"real" solution. If you pick this up:
- **Launch target discovery.** butlerd's `Launch` call is the "correct" way
to start a game (it handles prerequisites, manifest actions, sandboxing,
etc.), but OpenGamepadUI's library items launch via a plain
`command` + `args` OS exec, not an RPC call. This plugin currently
side-steps that by scanning each installed game's folder for an
executable file and pointing `command` directly at it
(`library_itch.gd::_find_executable`). That works for straightforward
native builds but skips prerequisite installation and manifest-declared
launch actions. Parsing `.itch/receipt.json.gz` in the install folder
would give the authoritative answer.
- **Field names.** The JSON-RPC field names used in `itch_client.gd` follow
butlerd's documented camelCase convention, cross-checked against the
[butlerd Go package docs](https://pkg.go.dev/github.com/itchio/butler/butlerd)
for the calls that matter most (`Install.Queue`/`Install.Perform`,
`Uninstall.Perform`). A couple of the less-central ones (`Launch`,
`Profile.LoginWithAPIKey`, `Fetch.ProfileOwnedKeys`) were written from the
documented naming convention rather than a byte-for-byte spec check —
worth diffing against your `butler`'s actual behavior (run with `--log`
to see the raw JSON-RPC traffic) if a call comes back with an unexpected
error shape.
- **Install location picker.** `_ensure_install_location()` silently picks
the first existing install location, or creates one under the plugin's
own data directory. No UI for choosing/managing install locations yet.
- **Settings screen.** Uses plain Godot `Control` nodes rather than
OpenGamepadUI's themed widget set (the one the built-in Steam plugin's
settings scene uses), since this was written without editor access to
those theme resources.
- **`has_update()`** always returns `false` — wiring up `CheckUpdate` (and
periodic background polling) is a natural next step.
- **No progress→UI wiring.** `install_progressed` is re-emitted from raw
butlerd notifications but not yet mapped back to a `LibraryLaunchItem`
through `LibraryManager` (see the TODO in `library_itch.gd`).
## How it fits together
```
plugin.gd entrypoint; wires client + library + settings menu
core/itch_client.gd spawns butlerd, speaks JSON-RPC 2.0 over TCP to it
core/library_itch.gd extends Library; turns butlerd data into LibraryLaunchItems
core/itch_settings.* API key entry screen
```