> ## Documentation Index
> Fetch the complete documentation index at: https://wiki.refineryteam.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Event Bus

> Cross-plugin, string-channel pub/sub without compile-time dependencies between plugins.

`RefineryBus` (`xyz.refineryteam.refinerycore.api.event`) is a process-wide, string-keyed publish/subscribe bus for lightweight cross-plugin signaling. Unlike Bukkit events, channels are just strings, so one plugin can publish on a channel and another can subscribe to it **without either plugin depending on the other's classes** at compile time.

<Note>
  This is meant for lightweight signaling — notify, refresh, sync. For anything that needs to be **cancellable** or intercepted mid-flow, use a real Bukkit `Event` instead.
</Note>

## Publishing

```java EconomyManager.java icon="java" theme={"system"}
// In an economy plugin, with no dependency on whatever subscribes:
RefineryBus.get().publish("economy:balance-changed", new BalanceChangedPayload(uuid, newBalance));
```

Delivery is **synchronous**, on the calling thread, in subscriber priority order (highest first). A throwing subscriber doesn't prevent others on the same channel from receiving the payload — the exception is logged and swallowed.

## Subscribing

```java EconomyManager.java icon="java" theme={"system"}
// In a cosmetics plugin reacting to balance changes, with no dependency
// on the economy plugin's jar:
RefineryBus.get().subscribe("economy:balance-changed", BalanceChangedPayload.class, payload -> {
    // react to payload.newBalance(), etc.
});
```

Only payloads assignable to the given `type` are delivered to that subscriber, so multiple unrelated payload shapes can technically share a channel name (though using separate channel names per payload shape is usually clearer).

```java RefineryBus.java icon="java" theme={"system"}
public <T> UUID subscribe(String channel, Class<T> type, Consumer<T> handler);
public <T> UUID subscribe(String channel, Class<T> type, Consumer<T> handler, int priority);
```

`subscribe` returns a `UUID` handle you can pass to `unsubscribe(channel, id)` later.

Payloads are plain objects — records work well — shared **by convention**: both the publisher and subscriber need to agree on the payload's shape, typically documented per channel name or via a small shared "API" module.

## Cleaning up — `BusSubscriptions`

Manually tracking every subscription `UUID` to unsubscribe them on plugin disable is tedious, so `BusSubscriptions` groups them for you:

```java MyPlugin.java icon="java" theme={"system"}
public final class MyPlugin extends JavaPlugin implements RefineryPluginImplementation {
    private final BusSubscriptions bus = new BusSubscriptions();

    @Override
    public void onEnable() {
        bus.on("economy:balance-changed", BalanceChangedPayload.class, payload -> {
            // handle it
        });
    }

    @Override
    public void onDisable() {
        bus.unsubscribeAll();
    }
}
```

<Warning>
  Always call `unsubscribeAll()` (or manually `unsubscribe`) in `onDisable()`. Since `RefineryBus` is a JVM-wide singleton, stale subscriptions from a disabled or reloaded plugin will otherwise keep firing against a plugin instance that's no longer active.
</Warning>

## Other operations

| Method                    | Description                                                                                                                                                                                                             |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `hasSubscribers(channel)` | Whether any subscriber is currently registered on a channel                                                                                                                                                             |
| `clearChannel(channel)`   | Removes **every** subscription on a channel, across all plugins. Prefer `unsubscribe`/`BusSubscriptions` in plugin code so you don't tear down another plugin's subscriptions — mainly useful for tests or a full reset |
