Skip to content

Experience Sources

Experience source files are stored under plugins/EmakiLevel/sources/*.yml. Each file can contain multiple source rules. A rule binds to a Bukkit or MythicMobs event through trigger, then uses match conditions and an exp formula.

Default source files:

FileDefault sourceDescription
combat.ymlvanilla_entity_killVanilla entity kill exp.
mythicmobs.ymlmythic_mob_killMythicMob kill exp.
block_actions.ymlmining, logging, gathering, farmingBlock break, gathering, and mature crop harvest.
fishing.ymlplayer_fishFishing event exp.
crafting.ymlcraft_itemCraft result exp.
brewing.ymlbrew_completeBrewing completion exp.
smelting.ymlfurnace_extractFurnace extraction exp.
taming.ymlentity_tameTaming exp.

File structure

yaml
id: "combat_sources"
enabled: true
sources:
  vanilla_entity_kill:
    enabled: true
    type: "combat"
    trigger: "entity_kill"
    include_players: false
    anti_abuse:
      exp_cooldown_ticks: 5
      ignore_near_spawner: true
      spawner_scan_radius: 8
    rules:
      - entity_types: ["ZOMBIE", "SKELETON"]
        exp_formula: "10"
      - entity_types: ["WITHER", "ENDER_DRAGON"]
        exp_formula: "500"

Top-level fields:

FieldDescription
idSource file identifier, mainly for readability.
enabledFile switch. When false, the whole file is skipped.
sourcesSource rule map keyed by source ID.

Single source fields:

FieldDescription
enabledRule switch.
typeTarget level type ID.
triggerTrigger ID. See the trigger table below.
include_playersUsed by entity_kill; whether killing players can grant exp. Default false.
count_result_amountDefault false. Parsed by the current implementation but not used in exp calculation; result counts are consumed through the %result_amount% formula variable.
anti_abuse.ignore_player_placed_blocksDefault false. Used by block_break / crop_harvest; whether player-placed blocks are ignored.
anti_abuse.exp_cooldown_ticksDefault 0 (no cooldown). Per-player, per-source exp cooldown in ticks. The timer starts only after a successful grant.
anti_abuse.ignore_near_spawnerDefault false. Used by entity_kill / mythic_mob_kill; skips the source when a spawner is found near the kill location.
anti_abuse.spawner_scan_radiusDefault 8; the effective scan radius is clamped to 0–16. Used together with ignore_near_spawner.
attribution.expire_ticksDefault 1200. Used by brew_complete only; the source is skipped when the brewing completion is older than this many ticks since the player's last interaction with the stand.
rulesMatch rule list. One source uses the first matching rule.
actions.gainReserved config entry. The current implementation does not execute this list; the type-level upgrade.actions.gain is the action path that actually runs.

Triggers

For the complete shared event ID reference, see CoreLib Gameplay Event IDs. This page lists the fields commonly used by EmakiLevel experience sources.

triggerEvent sourceMatch fieldsFormula variablesDefault target type
entity_killCoreLib shared event; killer or recent damagerentity_types%entity_type%combat
mythic_mob_killCoreLib shared event; MythicMobs mob detected in the same deathmob_ids%mythic_id%, %mythic_level%combat
block_breakCoreLib shared event; player breaks a blockblocks%block_type%mining / logging / gathering
crop_harvestDerived from block_break; the broken block is a mature Ageable cropblocks%block_type%farming
player_fishCoreLib shared event; player fishingstates%fish_state%fishing
craft_itemCoreLib shared event; player crafts an itemresult_item_sources%result_amount%, %result_type%crafting
brew_completeCoreLib shared event; attributed to the most recent brewing stand userpotion_types%potion_type%brewing
furnace_extractCoreLib shared event; player extracts a furnace resultresult_item_sources%result_amount%, %result_type%smelting
entity_tameCoreLib shared event; player tames an entityentity_types%entity_type%taming

CoreLib also publishes a block_place shared event, but EmakiLevel only uses it to record player-placed block locations. Writing block_place as a source trigger never grants exp.

Rule matching

Supported match fields:

FieldPurpose
entity_typesBukkit EntityType, e.g. ZOMBIE, WOLF, ENDER_DRAGON.
blocksBukkit Material, e.g. STONE, WHEAT, OAK_LOG.
statesEvent state names, e.g. CAUGHT_FISH.
result_item_sourcesCoreLib ItemSource values, e.g. minecraft-diamond_pickaxe. Used by crafting and smelting results.
potion_typesPotion base types, e.g. AWKWARD, SPEED, STRENGTH.
mob_idsMythicMobs internal IDs, e.g. SkeletonKing. Matching is case-normalized.
exp_formulaExp formula. Values less than or equal to 0 do not grant exp.

Behavior:

  • Multiple sources can share the same trigger; all matching sources are processed.
  • Inside one source, rules are checked in order and the first matching rule is used.
  • An empty match field means no restriction for that field.
  • entity_types, blocks, states, and potion_types are normalized to uppercase for matching.
  • result_item_sources uses CoreLib ItemSource matching, not only vanilla materials.

Exp formulas

Exp formulas use the CoreLib expression engine and %key% variables.

yaml
rules:
  - blocks: ["DIAMOND_ORE", "DEEPSLATE_DIAMOND_ORE"]
    exp_formula: "25"
  - result_item_sources: ["minecraft-diamond_pickaxe"]
    exp_formula: "40 * %result_amount%"
  - mob_ids: ["ForestBoss"]
    exp_formula: "300 + %mythic_level% * 20"

If the formula returns 0 or less, the exp grant is skipped.

Vanilla kills

yaml
sources:
  vanilla_entity_kill:
    enabled: true
    type: "combat"
    trigger: "entity_kill"
    include_players: false
    anti_abuse:
      exp_cooldown_ticks: 5
      ignore_near_spawner: true
      spawner_scan_radius: 8
    rules:
      - entity_types: ["ZOMBIE", "SKELETON", "SPIDER", "CREEPER"]
        exp_formula: "10"
      - entity_types: ["ENDERMAN", "BLAZE", "WITHER_SKELETON"]
        exp_formula: "25"
      - entity_types: ["WITHER", "ENDER_DRAGON"]
        exp_formula: "500"

Notes:

  • Kill attribution is resolved by the CoreLib shared event, which prefers the Bukkit killer.
  • When the kill was not direct and anti_abuse.last_damager_tracking.enabled: false, EmakiLevel skips the event.
  • The recent damager window is controlled by CoreLib config.yml > gameplay_events.last_damager_expire_ticks, default 200 ticks.
  • include_players: false prevents player kills from granting exp.
  • With ignore_near_spawner: true, blocks within spawner_scan_radius (clamped to 0–16) around the kill location are scanned, and the source is skipped when a spawner is found. Larger radii scan many more blocks; keeping the default 8 is recommended.

Block break and crop harvest

yaml
sources:
  mining:
    enabled: true
    type: "mining"
    trigger: "block_break"
    anti_abuse:
      ignore_player_placed_blocks: true
      exp_cooldown_ticks: 2
    rules:
      - blocks: ["STONE", "DEEPSLATE"]
        exp_formula: "1"
      - blocks: ["COAL_ORE", "DEEPSLATE_COAL_ORE", "IRON_ORE", "DEEPSLATE_IRON_ORE"]
        exp_formula: "5"

Anti-abuse behavior:

  • anti_abuse.placed_block_tracking: true records player-placed block locations.
  • If a source sets ignore_player_placed_blocks: true, that source ignores player-placed blocks.
  • Even without source-level ignore_player_placed_blocks, anti_abuse.placed_block_exp: false prevents player-placed blocks from granting break exp.
  • The placed-block record is removed when the block is broken; records older than anti_abuse.placed_block_record_ttl_ticks are pruned on the next read/write.

Mature crops use the same break event, but only trigger when block data is Ageable and fully grown:

yaml
sources:
  farming:
    enabled: true
    type: "farming"
    trigger: "crop_harvest"
    anti_abuse:
      ignore_player_placed_blocks: true
      exp_cooldown_ticks: 2
    rules:
      - blocks: ["WHEAT", "CARROTS", "POTATOES", "BEETROOTS", "NETHER_WART"]
        exp_formula: "4"

Breaking a mature crop fires both block_break and crop_harvest, so sources bound to either trigger can each grant exp.

Fishing

yaml
sources:
  player_fish:
    enabled: true
    type: "fishing"
    trigger: "player_fish"
    rules:
      - states: ["CAUGHT_FISH"]
        exp_formula: "10"
      - states: ["CAUGHT_ENTITY"]
        exp_formula: "5"

%fish_state% is the PlayerFishEvent.State name.

Crafting

yaml
sources:
  craft_item:
    enabled: true
    type: "crafting"
    trigger: "craft_item"
    count_result_amount: true
    rules:
      - result_item_sources: ["minecraft-crafting_table", "minecraft-furnace"]
        exp_formula: "5 * %result_amount%"
      - result_item_sources: ["minecraft-diamond_pickaxe", "minecraft-diamond_sword"]
        exp_formula: "40 * %result_amount%"

Formula variables:

VariableDescription
%result_amount%Recipe result stack amount, minimum 1.
%result_type%Bukkit Material name.

Brewing

yaml
sources:
  brew_complete:
    enabled: true
    type: "brewing"
    trigger: "brew_complete"
    attribution:
      expire_ticks: 1200
    rules:
      - potion_types: ["AWKWARD", "SPEED", "STRENGTH"]
        exp_formula: "15"

Brewing events do not directly include a player. CoreLib records the most recent player who interacted with the brewing stand and attributes the completed brew to that player. Each source can set its own window through attribution.expire_ticks (default 1200 ticks); brews older than that window are skipped by the source.

VariableDescription
%potion_type%First recognized potion base type in the brewing inventory, or UNKNOWN.

Smelting

yaml
sources:
  furnace_extract:
    enabled: true
    type: "smelting"
    trigger: "furnace_extract"
    rules:
      - result_item_sources: ["minecraft-iron_ingot", "minecraft-copper_ingot", "minecraft-gold_ingot"]
        exp_formula: "3 * %result_amount%"
      - result_item_sources: ["minecraft-netherite_scrap"]
        exp_formula: "20 * %result_amount%"

Formula variables:

VariableDescription
%result_amount%Amount extracted from the furnace.
%result_type%Bukkit Material name.

Taming

yaml
sources:
  entity_tame:
    enabled: true
    type: "taming"
    trigger: "entity_tame"
    rules:
      - entity_types: ["WOLF", "CAT", "HORSE", "PARROT"]
        exp_formula: "20"

Only player owners receive exp.

VariableDescription
%entity_type%Bukkit EntityType of the tamed entity.

Custom examples

Main exp for fishing events:

yaml
id: "treasure_sources"
enabled: true
sources:
  fishing_treasure_main:
    enabled: true
    type: "main"
    trigger: "player_fish"
    rules:
      - states: ["CAUGHT_FISH"]
        exp_formula: "2"

All-log logging exp:

yaml
id: "custom_logging"
enabled: true
sources:
  all_logs:
    enabled: true
    type: "logging"
    trigger: "block_break"
    anti_abuse:
      ignore_player_placed_blocks: true
    rules:
      - blocks:
          - "OAK_LOG"
          - "BIRCH_LOG"
          - "SPRUCE_LOG"
          - "JUNGLE_LOG"
          - "ACACIA_LOG"
          - "DARK_OAK_LOG"
          - "MANGROVE_LOG"
          - "CHERRY_LOG"
        exp_formula: "5"

Small main exp for all non-player kills:

yaml
id: "main_kill_bonus"
enabled: true
sources:
  main_entity_kill_bonus:
    enabled: true
    type: "main"
    trigger: "entity_kill"
    include_players: false
    rules:
      - exp_formula: "1"

The last rule has no entity_types, so it matches all entities.