Generated protobuf/gRPC bindings shared across the Bottles Next workspace.
Types are generated at build time via tonic-prost-build (see build.rs)
and re-exported under next_proto::bottles::<package>::v1 (plus
next_proto::winebridge for the WineBridge protocol).
Bottles Next is split into several processes that talk to each other over these protocols:
flowchart BT
UI["next-ui"]
Server["next-server\nProfile · Accounts · Steam\nLibrary · Plugin · Bottle"]
Registry["next-registry\nbottles.registry.v1"]
NextCore["next-core\nCore library"]
subgraph Plugins["Plugins"]
direction TB
EGS["next-plugin-egs\nbottles.plugin.v1"]
GOG["next-plugin-gog\nbottles.plugin.v1"]
OtherPlugin["next-plugin-*\nbottles.plugin.v1"]
end
WineBridge["WineBridge agent\n(inside a Wine prefix)"]
Server --> NextCore
UI --> NextCore
UI -->|"next-server's own RPCs"| Server
Server -->|"Resolve"| Registry
EGS -->|"Register / Heartbeat / Deregister"| Registry
GOG -->|"Register / Heartbeat / Deregister"| Registry
OtherPlugin -->|"Register / Heartbeat / Deregister"| Registry
Server --> WineBridge
classDiagram
class Profile {
ListProfiles()
GetProfile()
CreateProfile()
DeleteProfile()
RenameProfile()
UpdateProfile()
GetActiveProfile()
ActivateProfile()
WatchActiveProfile() stream
}
class Accounts {
LinkProfile()
RefreshAccount()
UnlinkProfile()
ActivateAccounts()
}
class Steam {
LinkSteamAccount()
UnlinkSteamAccount()
WatchSteamSessions() stream
}
class Library {
ListGames()
WatchGames() stream
InstallGame() stream
CancelInstall()
UninstallGame()
}
class Plugin {
BeginLogin()
CompleteLogin()
RefreshSession()
RevokeSession()
ListGames()
WatchGames() stream
GetInstallManifest()
}
class Bottle {
CreateBottle() stream
DeleteBottle() stream
GetBottle()
ListBottles()
WatchBottles() stream
WatchBottle() stream
EditBottle()
SetComponent() stream
RemoveComponent() stream
InstallDependency() stream
RunProgram()
ListProcesses()
KillProcess()
StopBottle()
ListDllOverrides()
SetDllOverride()
UnsetDllOverride()
CreateSnapshot() stream
ListSnapshots()
Rollback() stream
}
class Registry {
RegisterPlugin()
Heartbeat()
DeregisterPlugin()
ResolvePlugin()
ListPlugins()
}
Profile, Accounts, Steam, Library, and Bottle are hosted by
next-server. Plugin is implemented by each storefront plugin process
(next-plugin-egs, next-plugin-gog, ...) and re-exposed by next-server
as a forwarding facade with the same method set. Registry is hosted by
next-registry. Methods marked stream are server-streaming RPCs.
-
bottles.registry.v1(Registry) — a small standalone process (next-registry) that lets out-of-process storefront plugins announce themselves and letsnext-serverresolve which endpoint owns a givenStorefrontat runtime. Exactly one plugin may own a given storefront at a time. -
bottles.plugin.v1(Plugin) — the storefront-agnostic contract every storefront plugin process (next-plugin-egs,next-plugin-gog, ...) implements: interactive login, session refresh/revoke, and the storefront's game catalog/install manifest. Adding a new storefront never requires changing this file — everything storefront-specific is expressed through oneofs (LoginChallenge, etc). -
bottles.profiles.v1(Profile),bottles.accounts.v1(Accounts),bottles.steam.v1(Steam),bottles.library.v1(Library), andbottles.bottle.v1(Bottle) — hosted bynext-server, the processnext-uitalks to directly. Each is a thin gRPC facade over anext-coremanager, plus whatever Registry/Plugin dialing that manager deliberately doesn't own:Profileowns profile CRUD, the active-profile pointer, andWatchActiveProfile. It does not touch storefront credentials.Accountsowns linking/unlinking/refreshing storefront accounts (ActivateAccounts), dialingPluginthroughRegistryas needed.Steamis separate fromPluginbecause Steam sessions are read directly off the localloginusers.vdf, not through an out-of-process plugin.Libraryaggregates each linked storefront'sPlugin.ListGames/WatchGamesinto one merged view, and drives installs viaPlugin.GetInstallManifest.Pluginonnext-serveris a thin forwarding facade: it resolves the right storefront plugin throughRegistryand passes the call through unchanged, so callers don't need to dialRegistrythemselves.Bottleis next-core's Wine-prefix lifecycle/configuration surface.
-
bottles.common.v1(common) — shared value types (Storefront,LinkedAccount,Game,InstallState) referenced across the otherbottles.*packages; not a service of its own. -
winebridge(top-levelproto/winebridge.proto, not underbottles.*) — used bynext-coreto talk to the WineBridge agent running inside a Wine prefix (registry, processes, services, DLL overrides, filesystem). Unrelated to thebottles.*packages above: it's an in-prefix control channel, not part of the storefront/profile/library surface.
Register it in build.rs's compile_protos call — the module path under
next_proto::bottles mirrors the proto package (e.g.
bottles.accounts.v1 → next_proto::bottles::accounts::v1).