API

UltimateAirdrops ships a small, stable public API so other plugins can extend it — register custom airdrop properties, custom behavior actions, and react to airdrop lifecycle events. This is the same surface the official region add-ons (WorldGuard, Towny, Lands…) are built on.

Full Javadoc: keysetstudios.gitlab.io/ultimateairdrops


Add UltimateAirdrops to your project

Maven

<repositories>
    <repository>
        <id>gitlab-maven</id>
        <url>https://gitlab.com/api/v4/projects/34899751/packages/maven</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>es.keyset</groupId>
        <artifactId>ultimateairdrops</artifactId>
        <version>LATEST_VERSION</version> <!-- Replace with the latest available version -->
        <scope>provided</scope>
    </dependency>
</dependencies>

Gradle

repositories {
    maven { url = uri("https://gitlab.com/api/v4/projects/34899751/packages/maven") }
}

dependencies {
    // Replace LATEST_VERSION with the latest available version
    compileOnly("es.keyset:ultimateairdrops:LATEST_VERSION")
}

Declare UltimateAirdrops in your plugin.yml under depend (or softdepend) so it loads first, then use the API from your own onEnable.


Access the API

UltimateAirdropsAPI api = UltimateAirdropsAPI.getInstance();

The facade is deliberately minimal — it exposes the property registry and the action registry, and nothing more. All API calls are expected to run on the main server thread.


Register a custom property

Airdrop configuration is an extensible registry of typed properties, not a fixed set of fields. Build a PropertyType (usually with DefaultPropertyType.builder) and register it. If it supplies an edit button, it shows up automatically in the in-game editor and is persisted to airdrops.yml under its id.

UltimateAirdropsAPI api = UltimateAirdropsAPI.getInstance();

PropertyType<Integer> myProp = DefaultPropertyType.<Integer>builder("my_prop", Integer.class)
        .defaultValue(() -> 5)
        .button(type -> new TextInputButton(
                new ItemStack(Material.PAPER), "My Prop",
                new String[]{"My custom property"},
                type, "Enter a number", ValueParsers.intRange(0, 100)))
        .build();

api.registerPropertyType(myProp);

The button’s validation and parsing live in a ValueParser. The built-ins cover the common cases:

Parser Accepts
ValueParsers.STRING any text
ValueParsers.BOOL true / false
ValueParsers.intRange(min, max) an integer in range
ValueParsers.doubleRange(min, max) a decimal in range
ValueParsers.MATERIAL a valid block material id
ValueParsers.BIOME a valid biome id
ValueParsers.oneOf("A", "B", ...) one of a fixed set (case-insensitive)
ValueParsers.regex("...") text matching a regex

Other reusable input buttons are available too: ArrayInputButton, MapInputButton, ToggleInputButton. For a fully custom control, extend AbstractDataButton.

Read a property back

Airdrop airdrop = Airdrop.getAirdrop(0);

// Typed, no cast — preferred:
int value = airdrop.getProperty(myProp);

// Or by id (dynamic access):
int sameValue = airdrop.getProperty("my_prop");

Register a custom action

Behavior actions are extensible the same way. Implement ActionType and register it so it can be used as a type: in behaviors.yml:

UltimateAirdropsAPI.getInstance().registerActionType(new MyCustomAction());
# behaviors.yml
my-behavior:
  trigger: SPAWN
  actions:
    - type: my_custom_action
      some-param: "value"

Events

All public events live in the events package, are fired on the main thread, and have fully documented @NotNull getters. Listen to them like any Bukkit event.

Event Cancellable Fired when…
AirdropSpawnPoolEvent No (mutate list) The pool of eligible types is built, before the weighted pick. Remove/add types to change what can spawn; empty the list to skip this cycle.
SpawnLocationValidateEvent Yes A candidate location passed the built-in checks. Cancel to reject it and let the search try the next one. The region add-ons use this to veto protected areas.
PreAirdropSpawnEvent Yes The final location is chosen, just before the airdrop is placed. Last veto point; you can also swap the block or the airdrop type.
PostAirdropSpawnEvent No A brand-new airdrop was placed. The place for spawn-only side effects (not fired on restore).
AirdropRestoreEvent No An existing airdrop is restored from the database after a restart/reload.
PlayerOpenAirdropEvent Yes A player is about to open an unlocked airdrop. Cancel to deny that player.
AirdropUnlockEvent No An airdrop’s unlock timer reaches zero.
AirdropDespawnEvent No An airdrop is removed from the world.

Building an add-on

The region/claim integrations (WorldGuard, RedProtect, Towny, Lands, GriefPrevention) are standalone add-on plugins, not part of the core. Each one:

  1. Registers a check_* property through registerPropertyType(...) so it appears in the editor.
  2. Listens to SpawnLocationValidateEvent and cancels it to veto spawns inside protected regions.

That’s the template for modular integrations — the core never hard-references those APIs, so it stays lightweight and dependency-free. Want to publish your own add-on? Share it with us on Discord.