shire Docs

Events

Events avoid polling. The plugin declares the event names it needs with events.subscribe; the Host samples public state and sends notifications to the plugin's connection(s).

Current events (API 1.0)

Event Data Produced when
scene.changed {scene, previous} the public scene id changes
player.position {x, y, z, scene} the local player moved > 0.75 m; sampled at ~4 Hz
plugin.started plugin id string a plugin handshake completed with all permissions approved
plugin.stopped plugin id string the plugin process/connection stopped cleanly
plugin.error plugin id string the plugin process exited with a non-zero code
collect.progress {target, live} auto-collect target/live counts changed
unlock.progress {running, done, sent, total, skipped} waypoint unlock progress changed
chests.progress {running, current, total, found, confirmed} chest collection progress changed

The Core is sampled at approximately 4 Hz and only when at least one plugin has an event subscription. This keeps an idle Host from touching game state.

Subscribe

{"jsonrpc":"2.0","id":10,"method":"events.subscribe",
 "params":{"events":["player.position","scene.changed"]}}

The result is the accepted list. Unknown events are ignored. Call events.unsubscribe with the same shape to stop delivery.

The subscription requires events.subscribe in the manifest and the user's approval.

Delivery

{
  "jsonrpc": "2.0",
  "method": "shire.event",
  "params": {"event": "player.position", "data": {"x":123.5,"y":200,"z":-45,"scene":3}}
}

Each event is an independent notification; it has no id and must not be answered. If the plugin is slow, the Host keeps at most 256 pending lines per connection and drops the oldest. Subscriptions are per plugin, not per connection: both the request and event connections receive the same event stream.

Python example

plugin.subscribe("player.position", "scene.changed")

def on_position(data):
    plugin.set_ui([
        plugin.text("Last position", "title"),
        plugin.text(f"{data['x']:.1f}, {data['z']:.1f}", "pos"),
    ])

def on_scene(data):
    plugin.notify("Scene", f"{data['previous']} -> {data['scene']}")

plugin.on_event("player.position", on_position)
plugin.on_event("scene.changed", on_scene)
plugin.run()

UI events

UI interactions are separate notifications (shire.uiEvent); see UI.

Backpressure and limits

  • Events are sampled and queued by the Host on the game/render thread.
  • Outbound queues are bounded; old events are dropped before the connection is allowed to grow without bound.
  • A plugin that never reads its pipe eventually fills the pipe and is disconnected on write timeout; it does not block the Shire renderer because the writer runs on a separate connection thread with a timeout.
  • Event filters and priorities are not in API 1.0. Filter in the plugin or subscribe only to the names you need. New event names are additive within a minor API version; check api.info/the handshake before subscribing.

Shire Plugin API 1.0 · Written in English. Documentation home · API status · Changelog

Independent project. Not affiliated with HoYoverse. Never put secrets in a plugin, manifest or package.