Dragonfly Rust Plugin SDK
The dragonfly-plugin crate is the Rust SDK for Dragonfly gRPC plugins. It gives you:
- Derive macros to describe your plugin (
#[derive(Plugin)]) and commands (#[derive(Command)]). - A simple event system based on an
EventHandlertrait and an#[event_handler]macro. - A
Serverhandle with high‑level helpers (likesend_chat,teleport,world_set_block, …). - A
PluginRunnerthat connects your process to the Dragonfly host and runs the event loop.
Crate and directory layout
The Rust SDK lives under packages/rust as a small workspace:
dragonfly-plugin(this crate): Public SDK surface used by plugin authors.src/lib.rs: Re-exports core modules and pulls in this README as crate-level docs.src/command.rs: Command context (Ctx), parsing helpers, andCommandRegistrytrait.src/event/: Event system (EventContext,EventHandler, mutation helpers).src/server/:Serverhandle and generated helpers for sending actions to the host.src/generated/df.plugin.rs: Prost/tonic types generated fromproto/types/*.proto(do not edit).
macro/(dragonfly-plugin-macro): Procedural macros for#[derive(Plugin)],#[derive(Command)], and#[event_handler]. This crate is re-exported bydragonfly-pluginand is not used directly by plugins.xtask/: Internal code generation tooling that readsdf.plugin.rsand regeneratesevent/handler.rs,event/mutations.rs, andserver/helpers.rs. It is not published.example/: A minimal example plugin crate showing recommended usage patterns for the SDK.tests/: Integration tests covering command derivation, event dispatch, server helpers, and the interaction between the runtime and macros.
All APIs in this README reflect the 0.3.x line. Within 0.3.x we intend to keep:
- The
Plugin,EventHandler,EventSubscriptions, andCommandRegistrytrait shapes. - The
event_handler,Plugin, andCommandmacros and their attribute syntax. - The
Serverhelpers andevent::EventContextsemantics (includingcanceland mutation helpers).
Breaking changes may still happen in a future 0.4.0, but not within 0.3.x.
Quick start
1. Create a new plugin crate
2. Add dependencies
[]
= "my_plugin"
= "0.1.0"
= "2021"
[]
= "0.3"
= { = "1", = ["rt-multi-thread", "macros"] }
= { = "0.8", = ["runtime-tokio", "sqlite"] } # optional, for DB-backed examples
Only dragonfly-plugin and tokio are required; other crates (like sqlx) are up to your plugin.
3. Define your plugin
use ;
;
async
The #[event_handler] macro:
- Detects which
on_*methods you implement. - Generates an
EventSubscriptionsimpl that subscribes to the correspondingtypes::EventTypevariants. - Wires those events into
event::dispatch_event.
Commands
The 0.3.x series introduces a first‑class command system.
Declaring a command
use ;
This generates:
- A static
Eco::spec() -> types::CommandSpec. - A
TryFrom<&types::CommandEvent>impl that parses args intoEco. - An
EcoHandlertrait with async methods (pay,bal) and an__executehelper.
Handling commands in your plugin
Add the command type to your plugin’s #[plugin] attribute, and implement the generated handler trait for your plugin type:
use ;
The #[derive(Plugin)] macro then:
- Reports the command specs in the initial hello handshake.
- Generates a
CommandRegistryimpl that:- Parses
CommandEvents into your command types. - Cancels the event if a command matches.
- Dispatches into your
EcoHandlerimplementation.
- Parses
Within 0.3.x the shape of the command API (Ctx, CommandRegistry, CommandParseError, and the Command derive attributes) is considered stable.
Events, context, and mutations
event::EventContext<'_, T>wraps each incoming event:data: &Tgives read‑only access.cancel().awaitmarks the event as cancelled and immediately sends a response.- Event‑specific methods (like
set_messageforChatEvent) live in generated extensions.
event::EventHandleris a trait with an async method per event type; you usually never writeimpl EventHandlerby hand except inside an#[event_handler]block.
You generally do not construct EventContext yourself; the runtime does it for you.
Connection and runtime
Use PluginRunner::run(plugin, addr) from your main function:
- For TCP, pass e.g.
"tcp://127.0.0.1:50050"or"127.0.0.1:50050". - On Unix hosts you may also pass:
"unix:///tmp/dragonfly_plugin.sock"or- an absolute path (
"/tmp/dragonfly_plugin.sock").
On non‑Unix platforms, Unix socket addresses will return an error.
PluginRunner:
- Connects to the host.
- Sends an initial hello (
PluginHello) with your plugin ID, name, version, API version and commands. - Subscribes to your
EventSubscriptions. - Drives the main event loop until the host sends a shutdown message or closes the stream.
Stability policy for 0.3.x
Within the 0.3.x series we aim to keep:
- Trait surfaces for
Plugin,EventHandler,EventSubscriptions,CommandRegistry. - Macro names and high‑level attribute syntax (
#[plugin(...)],#[event_handler],#[derive(Command)],#[subcommand(...)]). Serverhelper method names and argument shapes.EventContextbehavior forcancel, mutation helpers, and double‑send (panic in debug, log in release).
We may still:
- Add new events and actions.
- Add new helpers or mutation methods.
- Improve error messages and diagnostics.
For details on how the code is generated and how to maintain it, see MAINTAINING.md.