Behaviors

A behavior is a reusable rule that reacts to an event affecting an airdrop. Each one follows the same structure:

TRIGGER  →  (optional) CONDITIONS  →  ACTIONS

Behaviors are defined once in behaviors.yml and assigned to airdrops from the Behaviors button of the in-game editor, which opens a selector in which each behavior can be enabled or disabled. They replace the former broadcast-*, commands-on-airdrop-* and explosion-on-drop-spawn options, which are migrated into behaviors automatically.

Changes to behaviors.yml are applied with /airdrops reload.


Anatomy of a behavior

format-version: 1

behaviors:

  warn-unlock-5s:
    description: "Warns everyone 5 seconds before the airdrop unlocks"
    trigger: TICK
    conditions:
      - "%locked_seconds% == 5"
    actions:
      - type: message
        all: true
        text: "%prefix% &e%airdrop_name% &7opens in &c5 &7seconds!"
      - type: sound
        all: true
        sound: BLOCK_NOTE_BLOCK_PLING
  • description (optional) — a single line or a list of lines displayed on the behavior’s button in the selector. Rendered as plain yellow text; colour codes are ignored.
  • trigger — the event that runs the behavior. See the table below.
  • conditions (optional) — expressions evaluated before the actions. If any of them fails, the deny-actions are executed instead, when present.
  • actions — the actions executed when the conditions pass.
  • deny-actions (optional) — the actions executed when a condition fails.
  • default: true (optional) — assigns the behavior to every airdrop automatically, as the default value of the Behaviors property. Individual airdrops can still remove it from their own selector.

Triggers

Trigger Fires when
SPAWN The airdrop block is placed in the world.
DESPAWN The airdrop despawns, either through a timer or by being cleared.
UNLOCK The unlock countdown reaches zero.
START_UNLOCKING A player starts the unlock countdown by interacting with the airdrop.
FIRST_OPEN The airdrop is opened for the first time by any player.
OPEN A player opens the airdrop inventory.
OPEN_DENIED A player attempts to open the airdrop while it is still locked.
TICK Once per second, for every live airdrop. Used for countdowns and animations.
RESTORE A live airdrop is restored from the database after a restart.

Actions

Each action is a list entry consisting of a type and its parameters.

type Parameters Description
message text:"..." or lang:"Messages.key", all: world: radius: Sends a chat message. lang reads the line from messages.yml.
title title: subtitle: fade-in: stay: fade-out: all: world: radius: Displays a title and subtitle. Times are expressed in ticks.
actionbar text: all: world: radius: Sends an action-bar message.
bossbar text: color: style: progress: invert: id: stop: all: world: radius: Shows a boss bar above the hotbar. Described below.
sound sound: volume:1.0 pitch:1.0 all: world: radius: at-airdrop: Plays a sound, identified by its Bukkit sound name.
network text: or lang:, server:"ALL" Broadcasts a message to the other servers of a BungeeCord or Velocity proxy. Described below.
console command:"eco give %player% 100" Executes a command from the console.
player command:"spawn" Executes a command as the triggering player.
set_block material:LIME_WOOL Changes the material of the airdrop block.
effect name:"my_effect" stop:false Starts or stops an effect defined in effects.yml.
explosion power:4.0 set-fire:false break-blocks:false Creates a real explosion. It damages nearby players and is not a cosmetic effect.
webhook url: body: content-type:"application/json" Sends an HTTP webhook asynchronously, to Discord, Slack or any other service. Described below.

For purely visual results, use the effect action with a particle effect. The explosion action damages players and can break blocks.

Choosing who receives an action

message, title, actionbar, bossbar and sound all pick their recipients the same way. The most specific parameter present wins:

Parameter Recipients
radius: 200 Players within 200 blocks of the airdrop.
world: true Players in the airdrop’s world.
all: true Every player online on this server.
(none of them) Only the player who triggered the behavior.

Triggers such as SPAWN, UNLOCK, DESPAWN and TICK have no triggering player, so an action on one of them reaches nobody unless it names a scope. radius and world are the natural choice for announcements that should stay local instead of interrupting the whole server.

sound additionally accepts at-airdrop: true, which plays the sound at the airdrop block with the game’s own distance falloff, so it fades with the distance. radius instead plays it at each listener’s own position, so everyone in range hears it at full volume. The bundled sound-unlock behavior uses at-airdrop.

Boss bars

The bossbar action is designed to be driven from TICK, which refreshes it once a second, and the bar is removed automatically when the airdrop despawns. Because TICK has no triggering player, a scope is required.

  bossbar-despawn-countdown:
    description: "Boss bar with the despawn countdown for nearby players"
    trigger: TICK
    conditions:
      - "!%airdrop_locked%"
    actions:
      - type: bossbar
        id: "countdown"
        radius: 60
        text: "&e%airdrop_name% &7· despawns in &c%time_left%"
        color: RED
        style: SEGMENTED_10
        progress: "%despawn_seconds% / %despawn_total%"
Parameter Meaning
color PINK BLUE RED GREEN YELLOW PURPLE WHITE. Default RED.
style SOLID SEGMENTED_6 SEGMENTED_10 SEGMENTED_12 SEGMENTED_20. Default SOLID.
progress How full the bar is, from 0.0 to 1.0. See below.
invert Flips the result, so a draining bar fills instead. Default false.
id Names the bar, so one airdrop can show several at once. Default default.
stop true removes the bar with that id, for example on UNLOCK.

progress is any number or placeholder, or a single arithmetic operation between two of them. The operators are / * + - and must always be surrounded by spaces, because a placeholder name may itself contain a -. Parentheses are not supported.

Expression Result
"%despawn_seconds% / %despawn_total%" Drains with the despawn countdown. This is the default.
"%locked_seconds% / %locked_total%" Drains with the unlock countdown.
"%papi_percent% / 100" Rescales an external 0–100 placeholder.
1 or 0 A static full or empty bar.

A value that cannot be resolved to a number leaves the bar full rather than silently emptying it, and a progress that can never resolve is reported in the console when behaviors.yml is loaded.

A %locked_seconds% bar only moves while the unlock countdown is actually running. With start_unlocking_on_interaction it stays full until a player interacts, and on airdrops unlocked by an item or a price it never moves. A boss bar on the DESPAWN trigger is discarded, since the airdrop is already gone.

Network broadcasts

The network action announces an airdrop to the other servers of a BungeeCord or Velocity network, so players in the lobby learn that one has landed on survival.

  network-broadcast-on-spawn:
    trigger: SPAWN
    actions:
      - type: network
        server: "lobby"
        text: "%prefix% &e%airdrop_name% &7has landed on &bsurvival&7! &7(%x_coord%, %z_coord%)"

server is the target server’s name as the proxy knows it. The default, "ALL", includes the server the airdrop spawned on, so local players would see the announcement twice next to the usual spawn broadcast: name a single target server, or disable the local broadcast behavior.

Placeholders and colour codes are resolved before sending, since the receiving servers only display the finished text. The message travels over the proxy’s plugin channel, which needs at least one player online on this server to carry it; with nobody connected the action is skipped. On Velocity the channel is served while its bungee-plugin-message-channel option is enabled, which is the default.

Webhook action

The webhook action works with any service: set the endpoint in url and write in body the payload that the service’s own documentation asks for. The plugin does not add or rename any field.

Parameter Meaning
url The webhook endpoint. Required.
body The payload. Required. See below.
content-type The Content-Type header. Default application/json.

body can be written in two ways:

  • As a YAML block (the recommended form). It is converted to JSON with the same structure: sections become objects, lists become arrays, and numbers and true/false keep their type. Placeholders are resolved in every text value and escaped, so a name containing quotes or line breaks never breaks the JSON.
  • As a string, such as '{"text": "..."}'. It is sent exactly as written after resolving placeholders, which also allows non-JSON payloads together with content-type. Placeholders are not escaped here, so a value containing quotes produces invalid JSON.

A Discord embed, following Discord’s webhook format. Note that Discord expects the colour as a decimal number, not as hex:

  discord-on-spawn:
    trigger: SPAWN
    actions:
      - type: webhook
        url: "https://discord.com/api/webhooks/XXXX/YYYY"
        body:
          username: "UltimateAirdrops"
          embeds:
            - title: "%airdrop_name% has landed!"
              description: "An airdrop just spawned in the world."
              color: 16766720
              fields:
                - name: "Coordinates"
                  value: "%x_coord%, %y_coord%, %z_coord%"
                  inline: true
                - name: "Players online"
                  value: "%players_online%"
                  inline: true

A Slack message, with Slack’s own fields:

      - type: webhook
        url: "https://hooks.slack.com/services/XXXX/YYYY/ZZZZ"
        body:
          text: "*%airdrop_name%* has landed at %x_coord%, %z_coord%"

If the service rejects the request, the console shows the HTTP status and the response it returned, which usually says which field is wrong.

Upgrading from an older version: the Discord shortcut fields (content, username, avatar-url and embed placed directly on the action) are no longer supported. Move them under body using Discord’s real field names, as in the example above: avatar-url becomes avatar_url, embed becomes an embeds list, and a hex colour becomes a decimal number. A webhook action without body is ignored and reported in the console.


Conditions

Conditions are expressions evaluated before the actions. They support the placeholders listed below and the following forms:

Form Example
Numeric or string comparison "%locked_seconds% == 5". Operators: == != > < >= <=
Containment "%airdrop_name% contains Rare", or !contains for the negated form
Boolean "%airdrop_locked%" and "!%airdrop_locked%"

When several conditions are listed, all of them must pass.


Placeholders

The following placeholders are available in behavior text and conditions:

Placeholder Value
%airdrop_name% %airdrop_id% Name and id of the airdrop.
%player% Name of the triggering player.
%x_coord% %y_coord% %z_coord% Real coordinates of the airdrop.
%world% World the airdrop is located in.
%max_corner_x_coord% %max_corner_z_coord% Maximum corner of the public (approximate) location.
%min_corner_x_coord% %min_corner_z_coord% Minimum corner of the public location.
%locked_time_left% %time_left% Formatted unlock and despawn countdowns.
%locked_seconds% %despawn_seconds% Raw second counts, intended for conditions.
%locked_total% %despawn_total% The airdrop’s configured countdown lengths, in seconds.
%players_online% Number of players currently online.
%airdrop_locked% %airdrop_opened% State flags, as true or false.

PlaceholderAPI placeholders are also resolved in behaviors that have a triggering player, including the plugin’s own ultimateairdrops placeholders.


Default sound behaviors

No behavior is hardcoded. Every behavior the plugin executes is defined in behaviors.yml, including the default sounds shipped with it. sound-open, sound-open-locked, sound-start-unlocking and sound-unlock are ordinary entries flagged default: true, and can be adjusted, renamed or deleted like any other behavior.

  sound-open:
    description: "Plays a chest-open sound when a player opens the airdrop"
    trigger: OPEN
    default: true
    actions:
      - type: sound
        sound: BLOCK_CHEST_OPEN

  sound-unlock:
    description: "Plays a door-opening sound at the airdrop when it finishes unlocking"
    trigger: UNLOCK
    default: true
    actions:
      - type: sound
        sound: BLOCK_IRON_DOOR_OPEN
        at-airdrop: true    # UNLOCK has no triggering player, so the sound is played at the block

The same applies to the default broadcasts, such as broadcast-spawn. Removing default: true keeps a behavior available in the selector without applying it to every airdrop, and any airdrop can also deselect a default behavior from its own Behaviors button.


Additional examples

  # A title shown to every player when the airdrop lands
  title-on-spawn:
    trigger: SPAWN
    actions:
      - type: title
        all: true
        title: "&e%airdrop_name%"
        subtitle: "&7has landed!"
        fade-in: 10
        stay: 50
        fade-out: 10

  # Turns the block lime during the last 2 seconds of the lock
  flash-while-locked:
    trigger: TICK
    conditions:
      - "%airdrop_locked%"
      - "%locked_seconds% == 2"
    actions:
      - type: set_block
        material: LIME_WOOL

  # Plays an effects.yml effect when the airdrop unlocks
  unlock-flare-fx:
    trigger: UNLOCK
    actions:
      - type: effect
        name: unlock-flare

  # A real explosion on spawn, damaging players without breaking blocks
  explosion-on-spawn:
    trigger: SPAWN
    actions:
      - type: explosion
        power: 4.0
        set-fire: false
        break-blocks: false

Custom actions (developers)

The action list is extensible. Third-party plugins can register their own ActionType through the API, making it available as a type: in behaviors.yml.