dragonfly-plugin 0.3.0

Dragonfly gRPC plugin SDK for Rust
Documentation
# Maintaining the Plugin API


This document is for developers who need to update, extend, or maintain the `dragonfly-plugin` API. This is **not** for plugin _users_; that documentation is in the main `README.md`.

## The Golden Rule: Do Not Edit Generated Files


This entire API is code-generated from a "Single Source of Truth." **You must not edit the generated Rust files by hand.** Any manual changes will be overwritten.

The _only_ files you will ever edit manually are:

1.  The `.proto` files (Phase 1).
2.  The `xtask` generator code (Phase 3's _generator_).
3.  The `dragonfly-plugin-macros` crate code.
4.  The `src/*` code in case of BC changes or etc.

## The 3-Phase Generation Pipeline


Our architecture is a 3-phase pipeline. Understanding this flow is critical to maintaining the API.

---

### Phase 1: The Protocol (Source of Truth)


- **What it is:** The `.proto` files that define all our gRPC services, messages, and events.
- **Location:** `../proto` directory.
- **How to change:** This is the **only place** you should start a change. To add a new event (e.g., `PlayerSleepEvent`), you add it to the `EventEnvelope` message in the `.proto` file.

---

### Phase 2: The Raw Bindings (Intermediate)


- **What it is:** The "raw" Rust code (structs, enums, and gRPC clients) generated directly from the `.proto` files. This code is often ugly, un-idiomatic, and not user-friendly.
- **How it's made:** This code is generated by `buf` which uses `prost` (via the makefile).
- **How to update:** When you have made changes to the proto buf files run the buf tool via `make proto`
- **Warning:** **NEVER EDIT THESE FILES BY HAND.**

---

### Phase 3: The Friendly API (The `xtask` Generator)


- **What it is:** This is the **public-facing, idiomatic Rust API** that our users love. It includes:
  - The `EventHandler` trait and its `async fn on_*` methods.
  - The `Server` struct with its friendly helper methods (e.g., `server.send_chat(...)`).
  - The `EventContext` struct and its helpers (`.cancel()`, mutation helpers like `.set_message()`).
  - The `types::EventType` enum.
- **How it's made:** The `xtask` crate is a custom Rust program that **parses the output of Phase 2** (the prost Rust code in `src/generated/df.plugin.rs`) and generates this API via:
  - `generate_actions.rs``server/helpers.rs`
  - `generate_handlers.rs``event/handler.rs`
  - `generate_mutations.rs``event/mutations.rs`
- **How to update:** You run the `xtask` crate from the terminal.
- **Warning:** **NEVER EDIT THESE FILES BY HAND.**

---

## How to add a new event


This is the most common maintenance task. Here is the complete workflow.

**Goal:** Add a new `PlayerSleepEvent`.

1.  **Phase 1: Edit the Protocol**
    - Open the relevant `.proto` file (e.g., `events.proto`).
    - Add the `PlayerSleepEvent` message.
    - Add `PlayerSleepEvent player_sleep = 15;` (or the next available ID) to your main `EventEnvelope`'s `payload` oneof.

2.  **Phase 2: Generate the Raw Bindings**
    - Run `make proto` to use the buf tool to generate all the needed `generated/*` files.

3.  **Phase 3: Generate the Friendly API**
    - Now that the raw types exist, we can generate the friendly API for them.
    - `cd` into the `xtask` directory.
    - Run `cargo run`.
    - The `xtask` generator will see the new `PlayerSleep` variant and automatically:
      - Add `async fn on_player_sleep(...)` to the `PluginEventHandler` trait.
      - Add the `case PlayerSleep` arm to the `dispatch_event` function.

4.  **Review and commit**
    - You are done. Review the changes in `git`.
    - You should see changes in:
      1.  The `.proto` file you edited.
      2.  The Phase 2 raw bindings file.
      3.  The Phase 3 friendly API files (e.g., `event_handler.rs`, `types.rs`).
    - Commit all of them.

- **What xtask generates for events**
  - Adds `async fn on_player_sleep(...)` (and similar) to the `EventHandler` trait in `event/handler.rs`.
  - Adds the `PlayerSleep` arm to the `dispatch_event` function.
  - Adds any required mutation helpers in `event/mutations.rs`.

## The `event_handler`, `Plugin`, and `Command` proc-macros


- **Crate:** `dragonfly-plugin-macro`

### `#[event_handler]`


- **Purpose:** Attached to an `impl EventHandler for MyPlugin` block.
- **How it works:** Scans the methods you define (`on_player_join`, `on_chat`, etc.) and generates an `impl EventSubscriptions for MyPlugin` that returns a `Vec<types::EventType>` with the corresponding variants.
- **Maintenance:** This macro is intentionally simple: it only cares about method names and does not need to change when new events are added. If a user types a non-existent event method, the trait mismatch causes a normal Rust compiler error.

### `#[derive(Plugin)]` + `#[plugin(...)]`


- **Purpose:** Implements the `Plugin` trait and wires the plugin metadata into the runtime.
- **Attributes:** `#[plugin(id = \"...\", name = \"...\", version = \"...\", api = \"...\", commands(Foo, Bar))]`.
- **How it works:**
  - Generates `Plugin` trait methods based on the literals.
  - Generates a `CommandRegistry` implementation that:
    - Collects command specs from the listed command types.
    - Dispatches `types::CommandEvent` into those command types.

### `#[derive(Command)]` + `#[subcommand(...)]`


- **Purpose:** Generates a strongly-typed command parser and handler trait for a struct/enum.
- **How it works:**
  - Produces a `spec()` function returning `types::CommandSpec`.
  - Implements `TryFrom<&types::CommandEvent>` using the SDK’s `parse_required_arg` / `parse_optional_arg` helpers.
  - Generates an `XxxHandler` trait and an `__execute` method that calls into the appropriate handler method on the plugin.
- **Maintenance:** When adding new `ParamType` support (e.g., enums) or changing how arguments map from `String` → Rust types, update the command macro implementation in `macro/src/command/` (parse/model/codegen) to keep codegen consistent with the runtime helpers in `src/command.rs`.

## Testing xtask and macros


- **xtask tests:** The `xtask` crate has:
  - Unit tests in `utils.rs` for AST helpers.
  - Snapshot tests in the generator modules (`generate_actions.rs`, `generate_handlers.rs`, `generate_mutations.rs`) using `insta`, with snapshots under `xtask/src/snapshots/`.
  - Edge-case tests that verify generators fail with clear error messages when prost structures are inconsistent (e.g., missing structs or payloads).
- **Macro tests:** The macro crate uses `trybuild` fixtures under `macro/tests/fixtures` to ensure:
  - Basic usage of `#[derive(Plugin)]`, `#[event_handler]`, and `#[derive(Command)]` compiles against the public SDK.
  - Any breaking change to macro signatures or expectations shows up as a compile error in these tests.