API

UltimateAirdrops provides a small, stable public API through which other plugins can register custom airdrop properties, custom behavior actions, and react to airdrop lifecycle events. It is the same surface the official region add-ons (WorldGuard, Towny, Lands and the rest) are built on.

Full Javadoc: keysetstudios.gitlab.io/ultimateairdrops


Adding UltimateAirdrops to a 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")
}

UltimateAirdrops must be declared in the consuming plugin’s plugin.yml under depend or softdepend so that it is loaded first. The API can then be used from the plugin’s onEnable.


Accessing the API

UltimateAirdropsAPI api = UltimateAirdropsAPI.getInstance();

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


Registering a custom property

Airdrop configuration is an extensible registry of typed properties rather than a fixed set of fields. A PropertyType is built, usually with DefaultPropertyType.builder, and then registered. If it provides an edit button, it appears 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);

Validation and parsing for a button are implemented in a ValueParser. The built-in parsers cover the common cases:

Parser Accepts
ValueParsers.STRING Any text.
ValueParsers.BOOL true or false.
ValueParsers.intRange(min, max) An integer within the given range.
ValueParsers.doubleRange(min, max) A decimal within the given range.
ValueParsers.MATERIAL A valid block material id.
ValueParsers.BIOME A valid biome id.
ValueParsers.oneOf("A", "B", ...) One of a fixed set of values, case-insensitively.
ValueParsers.regex("...") Text matching the given regular expression.

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

Reading a property

Airdrop airdrop = Airdrop.getAirdrop(0);

// Typed access, without a cast. Preferred:
int value = airdrop.getProperty(myProp);

// Access by id, for dynamic lookups:
int sameValue = airdrop.getProperty("my_prop");

Registering a custom action

Behavior actions are extensible in the same way. Implementing ActionType and registering it makes the action available 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 reside in the events package, are fired on the main thread, and expose fully documented @NotNull getters. They are handled like any other Bukkit event.

Event Cancellable Fired when
AirdropSpawnPoolEvent No (the list is mutable) The pool of eligible types is built, before the weighted selection. Types can be added or removed to change what may spawn; emptying the list skips the cycle.
SpawnLocationValidateEvent Yes A candidate location has passed the built-in checks. Cancelling rejects it and allows the search to continue with the next candidate. This is the event the region add-ons use to veto protected areas.
PreAirdropSpawnEvent Yes The final location has been selected, immediately before the airdrop is placed. It is the last point at which the spawn can be vetoed, and it also allows the block or the airdrop type to be replaced.
PostAirdropSpawnEvent No A new airdrop has been placed. Intended for spawn-only side effects; it is not fired on restore.
AirdropRestoreEvent No An existing airdrop is restored from the database after a restart or reload.
PlayerOpenAirdropEvent Yes A player is about to open an unlocked airdrop. Cancelling denies access to 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 and claim integrations (WorldGuard, RedProtect, Towny, Lands and GriefPrevention) are standalone add-on plugins rather than part of the core. Each one:

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

This is the reference pattern for modular integrations: the core never references those APIs directly, which keeps it lightweight and free of hard dependencies. Add-ons developed by third parties can be shared on our Discord.