Skip to content

API

Quick Start: Extend the plugin.

JManhunt exposes a versioned public API so other plugins can read match, lobby, compass, and score state, react to 15 lifecycle and combat events, resolve placeholders, toggle modifiers, and run lifecycle actions.

For curated gameplay twists with no code, see JManhunt-Challenges: a pack of 40+ ready-made mods and presets, not an API consumer.

The API lives in its own repository, jruk8/JManhunt-API, and ships as its own artifact. The engine implements it in apiimpl/ and registers the implementation with Bukkit's ServicesManager on enable.

Getting the API

Add the artifact as a compileOnly dependency (the engine supplies the implementation at runtime). JitPack builds it from the repo; pin a commit SHA:

repositories {
    maven { url = uri("https://jitpack.io") }
}

dependencies {
    compileOnly("com.github.jruk8:JManhunt-API:<commit-sha>")
}
<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>com.github.jruk8</groupId>
        <artifactId>JManhunt-API</artifactId>
        <version>commit-sha</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

Declare the dependency so Bukkit loads JManhunt first:

depend:
  - JManhunt

Then look the API up once JManhunt has enabled:

import com.jruk8.jmanhunt.api.JManhuntApi;
import java.util.Optional;

Optional<JManhuntApi> api = JManhuntApi.lookup();

lookup() is empty when JManhunt is absent or not yet enabled. If your plugin must react the moment JManhunt enables, listen for PluginEnableEvent instead of polling.

Registering your addon

Registering declares the minimum API version you need and fails fast when the engine is too old. The engine releases the handle automatically when your plugin disables, so you only call unregister() when dropping the integration early:

import com.jruk8.jmanhunt.api.AddonHandle;
import com.jruk8.jmanhunt.api.ApiVersion;

AddonHandle handle = api.registerAddon(this, new ApiVersion(1, 0, 0));
// ... on early teardown: handle.unregister();

registerAddon throws IllegalStateException when the running engine does not satisfy your minimum (same major, engine minor at least yours). Treat that as "disable yourself with a clear message", never as a crash.

Versioning

ApiVersion is semantic: the major must match exactly, the engine minor must meet or exceed the required minor, and the patch never affects compatibility. ApiVersion.CURRENT reports the version the artifact was released with, ApiVersion.compatible(required, actual) runs the check, and api.version() reports the running engine's version.

Additive changes (new services, methods, events) bump the minor; breaking changes bump the major. Your registerAddon minimum is the contract: the engine guarantees everything up to that version keeps working.

Where next

  • Reading State: matches, lobbies, players, compass, scores, placeholders, modifiers, queues.
  • Events: the 15 events, prepare hooks, and a worked example.
  • Developer Tools: in-game tooling for addon authors.

Design notes

  • Read first, act rarely. Most integrations only need the state reads plus two or three events. The actions (start, begin, cancel, setEnabled, adjustScore) exist for automation and admin tooling, and they behave exactly like their in-game counterparts.
  • JMHScript owns behavior. Custom match mechanics, triggers, and win-condition twists belong in modifier files, not in an addon: authors get reloads, validation, and the tag engine for free. Reach for the API when you need another plugin's data (or need to push JManhunt data out), not when you need a new rule.
  • Unknown reads empty. Never null-check defensively around the API: design for empty optionals and empty collections and your addon survives ended matches, offline players, and typos in ids.