Pipeline Chain Links
Chain links sit between the head and the tails. Each link receives the current PipelineContext, mutates it, and returns it for the next link. Links execute in YAML insertion order.
A failing requirement on a link skips that link but lets the rest of the pipeline continue. An exception thrown by a link aborts the rest of that pipeline run (it is logged but not rethrown).
Some links extend EventBoundedPipelineChainLink<E> — they assert that context.event() is an instance of their bound event type. If the binding doesn't match the link silently no-ops (it does not abort the pipeline). These are marked event-bound in the sections below.
Durability
take-durability
Damages the item by amount. Honours the blueprint's metadata.destroyable:
destroyable = true→ the item is consumed when durability hits zero (viaplayer.damageItemStack).destroyable = false(default) → damage is capped atmaxDurability - 1; the item never breaks.
Field | Type | Description |
|---|---|---|
|
| Damage points to subtract. Supports placeholders. |
Silently no-ops if the item is not Damageable.
repair
Event-bound: InventoryClickEvent. Designed to pair with a drag-and-drop head — repairs the cursor item (the damaged tool the player dropped onto the repair orb) by resetting its damage to zero. Cancels the click event in both success and failure cases.
No configurable fields. No-op if the cursor has no ItemInstance, no damage, or already has zero damage — in the no-damage case the click is still cancelled so the orb isn't consumed pointlessly.
Typical pairing:
unbreakable
Event-bound: InventoryClickEvent. Same shape as repair — designed for a drag-and-drop head. Sets the cursor item's damage to zero and marks it Unbreakable. If the item is already unbreakable, the click is cancelled and the link no-ops so the consumable isn't wasted.
No configurable fields.
Actions
execute-actions
Runs an AstralCore PaperActionList with the player as the target. The pipeline context is passed as the placeholder source, so every context placeholder (%item_*%, %player_*%, %entity_*%, %instance_data_*%, …) resolves.
Field | Type | Description |
|---|---|---|
|
| List of AstralCore action strings — see Actions. |
execute-random-actions
Picks one weighted entry from a map and runs its actions. Useful for randomised drops, randomised buffs, …
Field | Type | Description |
|---|---|---|
|
| Weighted entries. The map key is a free-form id; the value is the weight ( |
Weights are interpreted by RandomCollection — they do not have to sum to 100; pick is proportional.
Drops & experience
multiply-drops
Duplicates everything currently in context.drops() by multiplier. Optional chance (0–100 roll) gates the link.
Field | Type | Description |
|---|---|---|
|
| Total copies of the drop list to leave in context ( |
|
| Optional. 0–100 inclusive; the link is skipped on a failed roll. |
multiply-exp
Same idea as multiply-drops but for context.experience().
Field | Type | Description |
|---|---|---|
|
| Multiplier applied to the captured vanilla XP. |
|
| Optional. 0–100 roll. |
remove-item
Removes amount copies of context.itemStack() from the player's inventory via InventoryUtils.removeItems. Useful for consumable items.
Field | Type | Description |
|---|---|---|
|
| Number of copies to remove. Supports placeholders. |
remove-cursor
Clears the player's cursor stack. Requires the event to be an InventoryClickEvent — throws if used outside that context. Designed to pair with a drag-and-drop head: the cursor is the consumable that was just applied to the slot item.
No configurable fields.
Item data
scalable
Levelling system: accumulates XP on the item's ScalableItemData until a threshold, then increments the level and (optionally) evolves the item into another blueprint.
Field | Type | Description |
|---|---|---|
|
| XP required to reach the next level. |
|
| XP added to the item each pipeline run. |
|
| Optional. Blueprint key to evolve into on level-up. Enchantments and item data (except |
|
| Optional. Action list executed when a level-up occurs. |
|
| Optional. If non-empty, XP is gained only when the broken block is listed. |
|
| Optional. If the broken block is listed, the link is skipped (no XP). |
|
| Optional. If set, XP is gained only when the broken block matches at least one tag. See Material tags. |
The link runs only when the triggering item is in the player's main hand (off-hand triggers are ignored). Setting context.dirty(true) and (on evolve) context.replaceItemStack(true) is handled automatically.
set-stored-material
Event-bound: InventoryClickEvent. Designed for a drag-and-drop head — writes the cursor item's Material onto the slot item's StoredMaterialItemData. Cancels the click event.
Field | Type | Description |
|---|---|---|
|
| Material to store. Usually a placeholder reading the cursor through the drag-and-drop extra context. |
|
| If non-empty, only these materials can be stored. |
|
| Materials that are explicitly rejected. |
The slot item's StoredMaterialItemData must already exist (either created by default-data or by a prior pipeline). Sets context.dirty(true) so the listener persists the change.
set-item-model
Sets the live item's item_model component (Minecraft 1.21.4+) to a namespaced key — e.g. to reskin an item as it levels up.
Field | Type | Description |
|---|---|---|
|
| Item-model key ( |
store-entity
Serialises the captured entity onto the item's StoredEntityItemData (key astralitems:entity) and removes it from the world — a "capture" mechanic (mob catcher, pet wand, …). Any previously stored entity is released first. Sets context.dirty(true).
Requires context.entity() — pair it with an entity-populating head (interact-entity, entity-damage, bucket-entity, fish, shear-entity, entity-kill); it throws if no entity was captured.
No configurable fields.
release-entity
Deserialises the stored entity and spawns it at the player's location, then clears the StoredEntityItemData. No-ops when nothing is stored. Sets context.dirty(true).
No configurable fields.
Ability links
These read the captured event state (block, location, player) and apply specialised side effects.
melt
Replaces every drop in context.drops() with the result of its furnace recipe. Drops without a furnace recipe are left untouched. Recipes are cached after first lookup.
Field | Type | Description |
|---|---|---|
|
| Drop materials skipped by the melt step. |
The resulting amount equals the original stack's amount — one ore in produces one ingot out per stack unit, scaled by the input stack size.
hammer
Event-bound: BlockBreakEvent. Area-of-effect block breaking — uses the player's look direction to compute the affected plane.
Field | Type | Description |
|---|---|---|
| int | Half-extent of the AoE plane on the face perpendicular to the player's look. |
| int | Extra layers in the direction the player is looking. |
|
| Block types skipped by the AoE step. |
|
| If non-empty, only listed materials are broken by the AoE. |
|
| Optional. When present, only blocks matching at least one tag are broken. Omit the key to disable — an explicit empty list breaks nothing. See Material tags. |
For each affected block the link fires a virtual BlockBreakEvent through EventService.fireVirtualEvent so other plugins (protection, logging, claim systems) get a chance to cancel the break.
infinite-bucket
Event-bound: PlayerInteractEvent. Bucket-like behaviour — fill or drain water / lava / powder snow without consuming the item. Handles waterloggable blocks, cauldrons (empty, water, lava, powder-snow), and adjacent fluid placement / removal.
Field | Type | Description |
|---|---|---|
|
| One of |
| boolean | If |
When draining, the adjacent-block sweep also clears powder snow and bubble columns in addition to water and lava (bubble_column is only a drain target — it is not a valid fluid-type). Every fill / drain fires a virtual PlayerBucketFillEvent/PlayerBucketEmptyEvent, so protection plugins can veto the change (anti-grief).
break-leaves
Raytraces forward from the player's eye position and breaks every leaf block in a beam around the ray. Drops the broken leaves into context.drops() so a tail (magnet/drop) can grant them.
Field | Type | Description |
|---|---|---|
|
| Forward distance in blocks. |
|
| Per-step cube radius checked around the ray. |
The leaves tag is built from every Bukkit material whose name ends in LEAVES, plus NETHER_WART_BLOCK and WARPED_WART_BLOCK. For each break the link fires a virtual BlockBreakEvent so other plugins can veto.
build-wand
Event-bound: PlayerInteractEvent. Places up to length blocks of the player's stored material in the direction of the clicked face, consuming matching blocks from the player's inventory. Stops on out-of-bounds, occupied blocks, or empty inventory.
Field | Type | Description |
|---|---|---|
|
| Maximum number of blocks to place. |
The stored material is resolved via StoredMaterialItemData. Each placement fires a virtual BlockPlaceEvent so claim plugins can veto. Cancels the underlying interact event after running.
fell-tree
Event-bound: BlockBreakEvent. Walks upward from the broken block as long as the block above is a log (via MaterialSetTag.LOGS), breaks every log encountered, accumulates drops + XP. For each break the link fires a virtual BlockBreakEvent so other plugins can veto.
Field | Type | Description |
|---|---|---|
|
| Max vertical distance to scan. |
firework-boost
Boosts a gliding player as if they had used a firework rocket — emits no actual firework. Sends not-gliding to the player when not currently gliding.
Field | Type | Description |
|---|---|---|
|
| Firework power (1–3 typical). Defaults to |
plant-crops
Event-bound: PlayerInteractEvent (right-click block only). Plants compatible seeds from the player's inventory in an n × n square around the clicked block. Recognised seed → crop pairs (when the clicked block is farmland) include wheat seeds, potato, carrot, melon seeds, pumpkin seeds, beetroot seeds; soul sand is paired with nether wart. Unused seeds are refunded.
Field | Type | Description |
|---|---|---|
|
| Half-extent of the planting area. |
replant-crops
Event-bound: BlockBreakEvent. When a fully-grown Ageable crop is broken, scans the surrounding n × n square, harvests every fully-grown crop in range (drops + XP added to context), and resets each broken crop's age to 0 so it regrows. The original event is cancelled.
Field | Type | Description |
|---|---|---|
|
| Half-extent of the harvest area. |
|
| If non-empty, only these crop materials are processed. |
|
| Crop materials that are skipped. |
Each replant fires a virtual BlockPlaceEvent (if a protection plugin cancels it, the crop is reverted to its grown state and that block is skipped) and a virtual BlockBreakEvent for the harvest, so claim and logging plugins can veto.
spade-grass
Converts every DIRT/GRASS_BLOCK in an n × n area around context.block() to FARMLAND. No virtual event is fired — bypass claim plugins by design (use sparingly).
Field | Type | Description |
|---|---|---|
|
| Half-extent of the area to till. |
Diagnostics
debug-context
Logs the current PipelineContext summary to the server console: slot, player name, drops list, vanilla experience, dirty, and replaceItemStack flags. No configurable fields. Useful while authoring a new pipeline — remove it before going live (every fired event logs).