Skip to content

Action System

The action system is the core execution pipeline of EmakiCoreLib, providing unified action definition, parsing, and execution capabilities. All modules can trigger in-game behaviors through the action system.

Action Line Syntax

Each action follows this format:

[@if=<cond>] [@chance=<prob>] [@delay=<delay>] [@ignore_failure] <actionId> [key=value ...]
PartRequiredDescription
@if=<cond>NoCondition prefix — executes only when the condition is true
@chance=<prob>NoProbability prefix — value between 0.0 and 1.0
@delay=<delay>NoDelay prefix — in ticks (20 ticks = 1 second)
@ignore_failureNoIgnore failure — continues subsequent actions even if this one fails
<actionId>YesAction identifier (see built-in action list below)
key=value ...DependsAction parameters as space-separated key-value pairs

Control Prefixes

@if — Conditional Execution

Executes the action only when the condition expression evaluates to true. See Condition System for condition syntax details.

yaml
actions:
  - "@if=%player_level%>=10 givemoney amount=500"
  - "@if=%player_world%==world_nether sendmessage message=<red>你正在地狱中!"

@chance — Probabilistic Execution

Executes the action with the specified probability, ranging from 0.0 (never) to 1.0 (always).

yaml
actions:
  - "@chance=0.5 givemoney amount=1000"       # 50% chance to give 1000 coins
  - "@chance=0.1 createitem source=vanilla-diamond_sword amount=1"  # 10% chance to give a diamond sword

@delay — Delayed Execution

Delays execution by the specified number of ticks. 20 ticks = 1 second.

yaml
actions:
  - "sendmessage message=<yellow>3 秒后传送..."
  - "@delay=60 teleport world=world x=0 y=100 z=0"   # Teleport after 3 seconds delay

@ignore_failure — Ignore Failure

By default, a failed action interrupts the subsequent action chain. With this prefix, subsequent actions continue even if the current action fails.

yaml
actions:
  - "@ignore_failure takemoney amount=500"    # Continue even if deduction fails
  - "sendmessage message=<green>流程继续执行"

Combined Usage

Control prefixes can be freely combined:

yaml
actions:
  - "@if=%player_level%>=20 @chance=0.3 @delay=20 givemoney amount=2000"

Tip

The evaluation order of control prefixes is: @if@chance@delay → execute action. The condition is checked first, then the dice is rolled, and finally the delayed execution is scheduled.

Common Parameter Formats

Time Format

Some parameters support time format with the following syntax:

SyntaxMeaningExample
4040 ticks (no unit defaults to ticks)duration=40
40t40 ticksduration=40t
2s2 seconds = 40 ticksduration=2s
100ms100 milliseconds ≈ 2 ticksduration=100ms

Coordinate Format

Coordinate parameters support absolute values and relative offsets:

SyntaxMeaning
100.5Absolute coordinate 100.5
~Player's current position
~5Player's current position + 5
~-3Player's current position - 3

Built-in Action List

Message Actions

sendmessage

Send a chat message to the player.

ParameterRequiredTypeDefaultDescription
textYesstringMessage content, supports MiniMessage format
yaml
actions:
  - "sendmessage text=<green>Welcome back, %player_name%!"

sendactionbar

Send an ActionBar message to the player.

ParameterRequiredTypeDefaultDescription
textYesstringMessage content, supports MiniMessage format

broadcastmessage

Broadcast a message to all players. Does not require player context.

ParameterRequiredTypeDefaultDescription
textYesstringMessage content, supports MiniMessage format

sendtitle

Send a title to the player.

ParameterRequiredTypeDefaultDescription
titleYesstringMain title, supports MiniMessage
subtitleNostring""Subtitle, supports MiniMessage
fade_inNotime10tFade-in duration
stayNotime40tStay duration
fade_outNotime10tFade-out duration
yaml
actions:
  - "sendtitle title=<gold>Congratulations subtitle=<yellow>You leveled up! fade_in=10 stay=40 fade_out=10"

Effect Actions

playsound

Play a sound to the player.

ParameterRequiredTypeDefaultDescription
soundYesstringSound key (Bukkit Sound enum name, case-insensitive)
volumeNodouble1.0Volume
pitchNodouble1.0Pitch
yaml
actions:
  - "playsound sound=entity.player.levelup volume=1.0 pitch=1.0"

spawnparticle

Spawn particles at a specified location.

ParameterRequiredTypeDefaultDescription
particleYesstringParticle key (Bukkit Particle enum name, case-insensitive)
countNoint1Particle count
targetNostring"player"Spawn location: player = player position, location = specified coordinates
worldNostring""World name (only for target=location)
xNostring""X coordinate, supports relative format (only for target=location)
yNostring""Y coordinate, supports relative format (only for target=location)
zNostring""Z coordinate, supports relative format (only for target=location)
offset_xNodouble0X-axis random offset
offset_yNodouble0Y-axis random offset
offset_zNodouble0Z-axis random offset
extraNodouble0Extra parameter (speed/color etc., depends on particle type)
yaml
actions:
  - "spawnparticle particle=HEART count=10 offset_x=0.5 offset_y=0.5 offset_z=0.5"
  - "spawnparticle particle=FLAME count=20 target=location world=world x=~0 y=~2 z=~0"

Economy Actions

givemoney, takemoney, and setmoney share the same parameters, corresponding to give, deduct, and set balance respectively.

ParameterRequiredTypeDefaultDescription
amountYesdoubleAmount
providerNostring"auto"Economy provider, see table below
currencyNostring""Currency ID (required for ExcellentEconomy)

Provider options:

ValueBehavior
auto (default)If currency is non-empty → ExcellentEconomy; otherwise → Vault
vaultForce Vault
excellenteconomyForce ExcellentEconomy (must also specify currency)
yaml
actions:
  # Use default provider (Vault)
  - "givemoney amount=100"

  # Specify ExcellentEconomy with a specific currency
  - "takemoney amount=50 provider=excellenteconomy currency=gems"

  # Set balance
  - "setmoney amount=1000 provider=vault"

Warning

takemoney returns an ECONOMY_INSUFFICIENT error and interrupts the action chain when balance is insufficient. Add @ignore_failure prefix to continue.


Item Actions

createitem

Create a temporary item and store it in context. Use senditem to deliver it to the player.

ParameterRequiredTypeDefaultDescription
idYesstringTemporary item ID (referenced by senditem / clearitem)
sourceNostring""Item source, see source prefix table below. Aliases: item, item_source
amountNoint1Quantity, minimum 1

senditem

Send a temporary item to the player's inventory. Drops on ground if inventory is full.

ParameterRequiredTypeDefaultDescription
idYesstringTemporary item ID (created by createitem)
keepNobooleanfalsetrue = keep in temp storage after sending; false = remove after sending

clearitem

Clear an item from a specific player slot.

ParameterRequiredTypeDefaultDescription
slotYesstringSlot, see slot table below
sourceNostring""If specified, only clears when the slot item matches this source. Aliases: item, item_source

Slot options:

ValueDescription
mainhand / main_hand / handMain hand
offhand / off_handOff hand
helmetHelmet
chestplate / chestChestplate
leggings / legsLeggings
bootsBoots
0 ~ 35Inventory slot index
hotbar_0 ~ hotbar_8Hotbar

Item source prefixes:

PrefixPluginExample
minecraft- / mc- / v-Vanillaminecraft-diamond_sword
mmoitems- / mi-MMOItemsmmoitems-SWORD:my_sword
itemsadder- / ia-ItemsAdderitemsadder-namespace:item_id
neigeitems- / ni-NeigeItemsneigeitems-item_id
nexo- / no-Nexonexo-item_id
craftengine- / ce-CraftEnginecraftengine-namespace:item_id
No prefixVanilla (fallback)diamond_sword
yaml
actions:
  - "createitem id=reward source=minecraft-diamond_sword amount=1"
  - "senditem id=reward"
  - "clearitem slot=offhand"

Warning

Item sources use - as the separator, not :. Write minecraft-diamond_sword, not minecraft:diamond_sword. See Item Source System for details.


Player State Actions

teleport

Teleport the player to a specified location.

ParameterRequiredTypeDefaultDescription
xYesstringX coordinate, supports relative format ~ / ~N
yYesstringY coordinate, supports relative format
zYesstringZ coordinate, supports relative format
worldNostring""World name, empty = current world
yawNodouble0Horizontal facing (degrees)
pitchNodouble0Vertical facing (degrees)
yaml
actions:
  - "teleport world=world x=0 y=100 z=0 yaw=90 pitch=0"
  - "teleport x=~0 y=~10 z=~0"   # Teleport 10 blocks up

heal / damage / sethealth

Action IDParameterRequiredTypeDescription
healamountYesdoubleRestore health, capped at max health
damageamountYesdoubleDeal damage, minimum 0
sethealthamountYesdoubleSet health, range [0, maxHealth]

giveexp / takeexp / setexp

ParameterRequiredTypeDefaultDescription
amountYesintAmount, minimum 0
modeNostring"points"points = experience points; levels = levels
yaml
actions:
  - "giveexp amount=100"
  - "giveexp amount=5 mode=levels"   # Give 5 levels
  - "takeexp amount=50 mode=points"

Potion Effect Actions

givepotioneffect

Apply a potion effect to the player.

ParameterRequiredTypeDefaultDescription
typeYesstringPotion effect ID (e.g., speed, strength, regeneration)
levelYesintLevel (1 = amplifier 0, 2 = amplifier 1, etc.)
durationYestimeDuration, supports time format
ambientNobooleanfalseWhether it's an ambient effect (sparser particles)
particlesNobooleantrueWhether to show particles
iconNobooleantrueWhether to show HUD icon

type format: Use Minecraft vanilla effect IDs like speed, strength, minecraft:regeneration. Namespace minecraft: is auto-prepended if omitted. Spaces are replaced with _.

removepotioneffect

ParameterRequiredTypeDefaultDescription
typeYesstringPotion effect ID (same as above)

clearpotioneffects

No parameters. Clears all potion effects from the player.

yaml
actions:
  - "givepotioneffect type=speed level=2 duration=10s ambient=false particles=true"
  - "removepotioneffect type=poison"
  - "clearpotioneffects"

Command Actions

runcommandasplayer

ParameterRequiredTypeDefaultDescription
commandYesstringCommand executed as the player (leading / is auto-removed)

runcommandasop

ParameterRequiredTypeDefaultDescription
commandYesstringExecuted with temporary OP privileges, restored after execution

runcommandasconsole

ParameterRequiredTypeDefaultDescription
commandYesstringExecuted as console, no player context required
yaml
actions:
  - "runcommandasplayer command=spawn"
  - "runcommandasop command=gamemode creative %player_name%"
  - "runcommandasconsole command=say Server announcement: %player_name% earned an achievement!"

Warning

runcommandasop temporarily grants the player OP privileges — use with caution.


Template Actions

usetemplate

ParameterRequiredTypeDefaultDescription
nameYesstringTemplate name (defined in config.yml under action.templates)
yaml
actions:
  - "usetemplate name=level_up_reward"

Attribute Actions (EmakiAttribute Extension)

attribute_add

Stack a temporary attribute. Same effect_id repeated calls accumulate value and refresh expiry.

ParameterRequiredTypeDefaultDescription
effect_idYesstringUnique effect identifier for later removal or override
attributeYesstringAttribute ID (e.g., physical_attack)
valueYesdoubleAttribute value to stack
duration_ticksYestimeDuration, must be > 0, supports time format

attribute_set

Override a temporary attribute. Directly sets the attribute value; later writes override earlier ones.

ParameterRequiredTypeDefaultDescription
effect_idYesstringUnique effect identifier
attributeYesstringAttribute ID
valueYesdoubleAttribute value to set
duration_ticksYestimeDuration, must be > 0, supports time format

attribute_remove

ParameterRequiredTypeDefaultDescription
effect_idYesstringEffect ID to remove
yaml
actions:
  # Stack 50 physical attack for 10 seconds
  - "attribute_add effect_id=buff_atk attribute=physical_attack value=50 duration_ticks=10s"

  # Override physical defense to 100 for 200 ticks
  - "attribute_set effect_id=override_def attribute=physical_defense value=100 duration_ticks=200"

  # Remove specified effect
  - "attribute_remove effect_id=buff_atk"

Tip

Temporary attribute data exists only in memory and is lost on server restart. For persistent buffs across restarts, use PDC attributes instead.

attributedamage

Deal attribute damage to the player through EmakiAttribute's damage calculation pipeline.

ParameterRequiredTypeDefaultDescription
amountYesdoubleBase damage value
typeNostring""Damage type ID, empty = use default damage type
causeNostring"CUSTOM"Bukkit DamageCause enum name (uppercase)

Common cause values: CUSTOM, MAGIC, FIRE, FALL, POISON, PROJECTILE, ENTITY_ATTACK

yaml
actions:
  - "attributedamage amount=50 type=spell cause=MAGIC"

ActionContext

Each time an action is executed, the system creates an ActionContext object carrying the context information needed for execution.

FieldTypeDescription
sourcePluginPluginThe plugin instance that triggered the action
playerPlayerTarget player
phaseStringCurrent execution phase identifier (e.g., on_click, on_complete)
silentbooleanWhether in silent mode (no feedback messages sent)
placeholdersMap<String, String>Custom placeholder mappings
attributesMap<String, Object>Additional attributes (can pass arbitrary objects)
sharedStateMap<String, Object>Shared state within the same action chain
java
ActionContext context = ActionContext.builder()
    .sourcePlugin(plugin)
    .player(player)
    .phase("on_reward")
    .silent(false)
    .placeholder("reward_amount", "500")
    .placeholder("reward_type", "金币")
    .attribute("source_event", event)
    .build();

actionService.execute(actionLines, context);

Tip

sharedState is shared across all actions within the same action chain and can be used to pass intermediate results between actions. For example, a preceding action can store a computed result in sharedState, and subsequent actions can read and use it.

Template System

Action templates allow you to define commonly used action combinations as reusable templates, avoiding repetitive writing.

Defining Templates

Define templates under the action.templates node in config.yml:

yaml
action:
  templates:
    level_up_reward:
      - "playsound sound=entity.player.levelup volume=1.0 pitch=1.0"
      - "spawnparticle particle=TOTEM count=30 offsetX=1 offsetY=1 offsetZ=1"
      - "sendtitle title=<gold>升级! subtitle=<yellow>恭喜你升级了 fadeIn=10 stay=40 fadeOut=10"
      - "givemoney amount=500"
      - "giveexp amount=100"

    error_feedback:
      - "playsound sound=entity.villager.no volume=1.0 pitch=0.8"
      - "sendmessage message=<red>操作失败,请稍后再试。"

Using Templates

Reference templates in any action list via usetemplate:

yaml
actions:
  - "sendmessage message=<green>你完成了任务!"
  - "usetemplate template=level_up_reward"

Actions within a template are expanded and executed in order. Control prefixes also apply to usetemplate:

yaml
actions:
  - "@if=%quest_completed%==true @chance=0.5 usetemplate template=level_up_reward"

Placeholder System

Action parameters can use %placeholder% format placeholders, which are replaced with actual values at execution time.

Built-in Placeholders

PlaceholderDescription
%player_name%Player name
%player_uuid%Player UUID
%player_world%Player's current world name
%player_x%Player's X coordinate
%player_y%Player's Y coordinate
%player_z%Player's Z coordinate
%phase%Current execution phase

Custom Placeholders

Key-value pairs passed through ActionContext's placeholders can be used directly as placeholders:

java
ActionContext context = ActionContext.builder()
    .player(player)
    .placeholder("item_name", "钻石剑")
    .placeholder("item_count", "3")
    .build();
yaml
actions:
  - "sendmessage message=<green>你获得了 %item_count% 个 %item_name%!"

Item Display Tag

Use the <show_item> tag to embed an item's hover display in chat messages:

yaml
actions:
  - "sendmessage message=<green>你获得了 <show_item>!"

Tip

<show_item> renders as a hoverable item display showing the item's name, lore, enchantments, and other details. It requires a corresponding ItemStack in the ActionContext's attributes.

PlaceholderAPI Integration

When PlaceholderAPI is installed on the server, CoreLib automatically recognizes and resolves PAPI placeholders. You can use any registered PAPI placeholder directly in action parameters:

yaml
actions:
  - "sendmessage message=<gray>你的余额:%vault_eco_balance%"
  - "@if=%statistic_play_one_minute%>=72000 sendmessage message=<gold>你已游玩超过 1 小时!"

Tip

CoreLib built-in placeholders take priority over PlaceholderAPI. If a placeholder with the same name exists, the CoreLib built-in value will be used.

Error Types

The following error types may occur during action execution:

Error EnumDescription
UNKNOWN_ACTIONUnknown action ID
INVALID_SYNTAXAction line syntax error
MISSING_PARAMETERMissing required parameter
INVALID_PARAMETERInvalid parameter value
CONDITION_NOT_METCondition not satisfied (not an error, normal skip)
CHANCE_NOT_METProbability not hit (not an error, normal skip)
EXECUTION_FAILEDException occurred during action execution
PLAYER_OFFLINETarget player is offline
ECONOMY_INSUFFICIENTInsufficient economy balance
ITEM_SOURCE_NOT_FOUNDItem source could not be resolved
TEMPLATE_NOT_FOUNDReferenced template does not exist
java
actionService.execute(actionLines, context).whenComplete((result, ex) -> {
    if (result.hasErrors()) {
        for (ActionError error : result.getErrors()) {
            logger.warning("动作执行错误: " + error.type() + " - " + error.message());
        }
    }
});

Released under the GPL-3.0 License