v0.5.0
Adds the Lifecycle modality (graceful shutdown), a one-shot camera
screenshot, inventory thumbnail fetching, and engine/renderer host PIDs in
Info. Also breaking: the Dash modality is redesigned from a flat tree to
a tab/control model (gRPC route / C# surface / Python client + CLI all change),
so update the ResoniteIO mod and the resoio Python package in lockstep.
Added
Lifecycle.ShutdownRPC: A newLifecyclemodality with a unary
ShutdownRPC that asks the engine to quit gracefully
(Engine.RequestShutdown, the in-app Quit path). The mod schedules the
shutdown on the engine tick and ACKs before the process tears down, so the
RPC returns promptly and the engine exits asynchronously. Exposed as
LifecycleClient.shutdown()ServerInfo.resonite_pid/renderer_pid:Info.GetServerInfonow also
reports the engine (Resonite.exe) and renderer (Renderite.Renderer.exe)
host PIDs. The engine runs natively on Linux (is_wine=false), so
resonite_pid(Environment.ProcessId) andrenderer_pid
(RenderSystem.RendererProcess,0when headless) are real host kernel PIDs.
Surfaced onServerInfoand in theresoio infooutput (newresonite_pid=/
renderer_pid=lines)resoio terminate/resoio.terminate: Stops the running Resonite client
gracefully — it reads the engine PID fromInfo(for reporting) and sends
Lifecycle.Shutdown; the engine quits itself and Steam/Proton reaps the
renderer + launch wrappers. A pure gRPC call (no OS signals), so it works from
anywhere the UDS is reachable. Prints / returns the engine's host PID, or
"resonite not running" /Nonewhen no engine is reachableCameraClient.shot()andresoio screenshot: A convenience method that
captures a single Camera frame and closes the stream (instead of opening a
stream and breaking on the first frame), plus a CLI command that saves it as
an opaque PNG.resoio screenshottakes-o/--output(a.pngpath or
-for stdout) and otherwise writes a timestamped
screenshot_<timestamp>.pngto the current directory. The PNG drops the alpha
channel, because the engine framebuffer's non-opaque alpha would otherwise
render washed-out in image viewers. Exposed asCameraClient.shot()Inventory.FetchThumbnailRPC: A unary RPC that returns the thumbnail
image of an inventory item, resolving the item'sRecord.ThumbnailURI
server-side and returning the raw image bytes plus their content type (e.g.
"image/webp", returned verbatim from the Resonite CDN, not re-encoded).
Exposed asInventoryClient.fetch_thumbnail()(returning the new
InventoryThumbnaildataclass) and thethumbcommand in the interactive
resoio inventoryREPL
Changed
- Breaking — the Dash modality is redesigned to a tab/control model: the
flat-tree contract (GetTree/ListScreens/SetScreenwith the
DashTree/DashElement/DashRect/DashScreen/DashScreenList
messages) is replaced by a tab-first model. The bottom tab bar is enumerated
withListTabs→DashTabList, the current tab's controls (Button /
ScrollRect) withListControls→DashControlList, and a newSetTabRPC
switches tabs (Open/Close/GetState/Invoke/Scroll/
Highlightare retained). On the Python side theDashTree/DashElement/
DashScreendataclasses are replaced byDashTab/DashControl, and the
resoio dashCLI is restructured intoopen/close/state/tabs/
tab/ls/invoke/scroll/highlight(tab navigation first, then
control interaction within the current tab). The gRPC route is wire-broken by
the message/RPC changes — update the ResoniteIO mod and theresoioPython
package in lockstep