> For the complete documentation index, see [llms.txt](https://edseries-plugins.gitbook.io/p/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://edseries-plugins.gitbook.io/p/edmortars/reference/api.md).

# Developer API

Add the EdMortars jar as a `provided` dependency and `softdepend: [EdMortars]` (or `depend`) in your plugin.yml.

Only the `es.edwardbelt.edmortars.api` package is public API. Every other class of the plugin may be renamed or changed between versions (and is obfuscated in released jars), so never import or reflect into them. Keep the API calls in a class that only loads once `Bukkit.getPluginManager().isPluginEnabled("EdMortars")` is true.

## EdMortarsAPI

All methods are static and thread-safe. While EdMortars is disabled they return null, an empty collection, false or 0. Methods reading a player's state by `UUID` only see online players (their data is loaded while they play).

| Method                                                          | What it does                                                                               |
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| `available()`                                                   | EdMortars runs                                                                             |
| `mortarTypes()`                                                 | every type id                                                                              |
| `mortarType(id)`                                                | a `MortarTypeInfo`, or null                                                                |
| `isUnlocked(uuid, type)`                                        | the player unlocked that type                                                              |
| `getUpgradeLevel(uuid, type, upgrade)` / `getUpgradeValue(...)` | level / current stat                                                                       |
| `getCooldownRemaining(uuid, type)`                              | ms until it can fire, 0 when ready                                                         |
| `getPlacedMortars(owner)` / `getPlacedMortar(owner, type)`      | `MortarInfo` snapshots of the mortars in the owner's loaded mine                           |
| `fire(player, type)`                                            | fires their placed mortar now (skips cooldown and shell limit), returns whether it started |
| `setUnlocked(uuid, type, boolean)`                              | unlock / lock, online or offline, `CompletableFuture<Boolean>`                             |
| `setUpgradeLevel(uuid, type, upgrade, level)`                   | set a level (clamped), online or offline, `CompletableFuture<Boolean>`                     |
| `openMenu(player, type)`                                        | opens their own mortar's menu (null type = their first mortar)                             |

`MortarUpgrade`: `CHANCE`, `MULTIPLIER`, `RADIUS`, with `id()` and `fromId(String)`.

`MortarTypeInfo`: `getId()`, `getDisplayName()`, `getRequirementIds()`, `getCooldownMillis()`, `isUpgradeEnabled(u)`, `getMaxLevel(u)`, `getValue(u, level)`, `getCost(u, level)`, `getCurrency(u)`, `getUpgradeName(u)`.

`MortarInfo` (a snapshot): `getOwnerId()`, `getMortarType()`, `getLocation()`, `isUnlocked()`, `getLevel(u)`, `getValue(u)`, `getCooldownRemainingMillis()`, `isReady()`, `getActiveShells()`.

## Events

| Event                | When                                                                                                                  | Thread                        | Cancellable |
| -------------------- | --------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ----------- |
| `MortarPlaceEvent`   | a mortar was placed in a mine that loaded (or was rebuilt after a reload)                                             | usually async                 | no          |
| `MortarUnlockEvent`  | a player unlocks from the menu, after the requirement check, before anything is taken                                 | main                          | yes         |
| `MortarUpgradeEvent` | a player buys a level, after the price check, before payment (`getFromLevel`, `getToLevel`, `getCost`, `getCurrency`) | main                          | yes         |
| `MortarFireEvent`    | a mortar is about to fire (`isForced()` for admin / API shots); cancelled = no shot, no cooldown                      | usually async (mining thread) | yes         |
| `MortarExplodeEvent` | a shell landed and the blast was broken and paid (`getBlocksBroken`, `getRadius`, `getMultiplier`, `getImpact`)       | async                         | no          |

Async events: never touch the world in the listener without hopping to the main thread first.

```java
@EventHandler
public void onExplode(MortarExplodeEvent event) {
    if (event.getBlocksBroken() >= 100) {
        Bukkit.getScheduler().runTask(plugin, () ->
                event.getOwner().sendMessage("Huge blast: " + event.getBlocksBroken() + " blocks!"));
    }
}
```

## Without the API

Shops, crates and quests can use the console: `edmortars unlock <player> <type>`, `edmortars setlevel <player> <type> <upgrade> <level>`, and read `%edmortars_unlocked_<type>%`.
