Godot JSON.parse decodes every JSON number as a float, so integer ids (7670) round-trip through JSON.stringify as 7670.0, which Go's int64 fields reject with RPC error -32700. Normalize at the parse boundary so profile/game/upload ids serialize correctly. Also drop the nonexistent 'fresh' parameter from Fetch.ProfileOwnedKeys. |
||
|---|---|---|
| assets | ||
| core | ||
| .gitignore | ||
| export_presets.cfg | ||
| LICENSE | ||
| Makefile | ||
| plugin.gd | ||
| plugin.json | ||
| README.md | ||
OpenGamepadUI-itch
An itch.io library plugin for OpenGamepadUI, built against itch's official butlerd 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 distribution channel.
Setup
- Build and install the plugin (see below).
- Generate an API key at https://itch.io/user/settings/api-keys.
- 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.
Requirements
See the OpenGamepadUI requirements.
This plugin additionally needs unzip on the host (used to unpack the
downloaded butler binary).
Building
Same as any other OpenGamepadUI plugin:
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
Launchcall is the "correct" way to start a game (it handles prerequisites, manifest actions, sandboxing, etc.), but OpenGamepadUI's library items launch via a plaincommand+argsOS exec, not an RPC call. This plugin currently side-steps that by scanning each installed game's folder for an executable file and pointingcommanddirectly 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.gzin the install folder would give the authoritative answer. - Field names. The JSON-RPC field names used in
itch_client.gdfollow butlerd's documented camelCase convention, cross-checked against the butlerd Go package docs 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 yourbutler's actual behavior (run with--logto 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
Controlnodes 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 returnsfalse— wiring upCheckUpdate(and periodic background polling) is a natural next step.- No progress→UI wiring.
install_progressedis re-emitted from raw butlerd notifications but not yet mapped back to aLibraryLaunchItemthroughLibraryManager(see the TODO inlibrary_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