# The Paper and Velocity helper

:::caution
Phase 2, **in development**. This page describes the design of `zaroz-minecraft-helper` (Java 21, Gradle, MIT). Names and options may change until the first `1.x` release, which is versioned with the contract major.
:::

| Module | What it is |
|---|---|
| `common` | contract client (reads `/zaroz/*.json`, signal socket and long-polls), Units API client (authenticates with `/zaroz/credentials/token`, re-reading it on `401`), webhook signature verifier, typed events |
| `paper` | a plugin for Paper servers |
| `velocity` | a plugin for Velocity proxies |

## Paper

- Signals `ready` after `ServerLoadEvent`.
- Signals `busy` on the first join and `idle` after `idle_grace_seconds` with no players (configurable).
- Signals `accepting false` at your configured capacity and `true` below it.
- Registers a `ZarozUnit` service (Bukkit `ServicesManager`) with the key, labels, `user_data` and allocation, and fires `UnitAllocatedEvent` when an allocation arrives.
- On the draining notice it sends a configurable message and asks the proxy to move players to a lobby before SIGTERM.

World persistence stays yours: download on start, upload on SIGTERM, to your own bucket.

```java
ZarozUnit unit = Bukkit.getServicesManager().load(ZarozUnit.class);
getServer().getPluginManager().registerEvents(new Listener() {
    @EventHandler
    void onAllocated(UnitAllocatedEvent e) {
        Match match = Match.fromJson(e.userData());   // the roster you sent to allocate
        startMatch(match);
    }
}, this);
```

## Velocity

- Keeps the proxy's server list in sync with one or more Workloads: it lists ready units and follows the [event long-poll](/guides/units-api/events) (`unit.ready` adds `<key>.<workload>`, `unit.draining` and `unit.destroyed` remove it).
- Balances joins across accepting lobbies.
- A duel API for your plugins: `allocate` on a configured Workload with the party in `user_data`, then it sends the players when `unit.allocation_delivered` arrives.
- A plot API: create by key with `start: true`, and wait for `unit.ready`.

The proxy's Workload needs a [service principal](/guides/units-api/principals) with `units.control` on the Workloads it creates units in and `units.read` on the ones it only watches.

See the `example-game-network` repository for a complete network built with it.
