Skip to content

Getting started

Addon developer

AbstractMenus 2.0 ships an SPI: addons register custom actions, rules, item properties, activators, catalogs, and provider handlers (economy, permissions, levels, placeholders, skins) at runtime. Same SPI the built-in types use.

There are two ways to deliver an addon. Pick one:

The pages below cover the API surface itself. The addons page covers delivery: which path to pick, manifest format, lifecycle.

The AbstractMenus API is published on GitHub Packages and built per release on JitPack.

build.gradle.kts
repositories {
maven("https://jitpack.io")
}
dependencies {
compileOnly("com.github.AbstractMenus:minecraft-plugin:2.0.0-alpha.2")
}

The artifactId is minecraft-plugin (the repo name). JitPack publishes multi-module Gradle projects under one root coord; the jar contents are the api module.

Declare the dependency in plugin.yml (Path 2 only)

Section titled “Declare the dependency in plugin.yml (Path 2 only)”

Path 2 plugin-as-addons declare AbstractMenus as a hard dependency so Bukkit guarantees ordering — your onEnable runs after AbstractMenus is up.

plugin.yml
name: MyAddon
version: 1.0.0
depend:
- AbstractMenus

Use softdepend: if your plugin should still load when AbstractMenus is missing — then guard API calls with Bukkit.getPluginManager().getPlugin("AbstractMenus") != null.

Path 1 addons don’t have a plugin.yml. They use addon.conf instead, with a pluginDependencies field. See the addons page.

The entry point is AbstractMenusApi, looked up via the static get() method:

import ru.abstractmenus.api.AbstractMenusApi;
AbstractMenusApi api = AbstractMenusApi.get();

It returns null if AbstractMenus has not enabled yet. With depend: [AbstractMenus] declared, your onEnable will always see a non-null result.

For Path 1 addons, you don’t call get() at all — the API is passed as a parameter to the lifecycle methods:

public final class MyAddon implements MenuExtension {
@Override
public void onEnable(AbstractMenusApi api) {
// api is already wired up
}
}
api.actions(); // TypeRegistry<Action>
api.rules(); // TypeRegistry<Rule>
api.activators(); // TypeRegistry<Activator>
api.itemProperties(); // TypeRegistry<ItemProperty>
api.catalogs(); // TypeRegistry<Catalog<?>>
api.providers(); // ProviderRegistry — economy, permissions, levels, placeholders, skins
api.serializers(); // shared HOCON NodeSerializers
api.variables(); // VariableManager — read/write player and global variables
api.openMenu(activator, ctx, player, menu);
api.getOpenedMenu(player);
api.loadMenus();
api.apiVersion(); // version string for diagnostics
api.getPlugin(); // raw Bukkit Plugin handle

Each registry, manager, and helper has its own page on this docs section.

Optional: GitHub Packages instead of JitPack

Section titled “Optional: GitHub Packages instead of JitPack”

If you must use GitHub Packages (e.g. CI policy):

  1. Generate a Personal Access Token (classic) with the read:packages scope.

  2. Put credentials in ~/.gradle/gradle.properties:

    ~/.gradle/gradle.properties
    gpr.user=your-github-username
    gpr.token=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  3. Add the repository and switch the coord to the native ru.abstractmenus:api:

    build.gradle
    repositories {
    maven {
    url = uri('https://maven.pkg.github.com/AbstractMenus/minecraft-plugin')
    credentials {
    username = providers.gradleProperty('gpr.user')
    .orElse(providers.environmentVariable('GITHUB_ACTOR')).getOrNull()
    password = providers.gradleProperty('gpr.token')
    .orElse(providers.environmentVariable('GITHUB_TOKEN')).getOrNull()
    }
    }
    // JitPack is still required for the api's transitive
    // com.github.AbstractMenus:hocon dep:
    maven { url 'https://jitpack.io' }
    }
    dependencies {
    compileOnly 'ru.abstractmenus:api:2.0.0-alpha.2'
    }