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:
| File | Default source | Description |
|---|---|---|
combat.yml | vanilla_entity_kill | Vanilla entity kill exp. |
mythicmobs.yml | mythic_mob_kill | MythicMob kill exp. |
block_actions.yml | mining, logging, gathering, farming | Block break, gathering, and mature crop harvest. |
fishing.yml | player_fish | Fishing event exp. |
crafting.yml | craft_item | Craft result exp. |
brewing.yml | brew_complete | Brewing completion exp. |
smelting.yml | furnace_extract | Furnace extraction exp. |
taming.yml | entity_tame | Taming exp. |
File structure
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:
| Field | Description |
|---|---|
id | Source file identifier, mainly for readability. |
enabled | File switch. When false, the whole file is skipped. |
sources | Source rule map keyed by source ID. |
Single source fields:
| Field | Description |
|---|---|
enabled | Rule switch. |
type | Target level type ID. |
trigger | Trigger ID. See the trigger table below. |
include_players | Used by entity_kill; whether killing players can grant exp. Default false. |
count_result_amount | Default 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_blocks | Default false. Used by block_break / crop_harvest; whether player-placed blocks are ignored. |
anti_abuse.exp_cooldown_ticks | Default 0 (no cooldown). Per-player, per-source exp cooldown in ticks. The timer starts only after a successful grant. |
anti_abuse.ignore_near_spawner | Default false. Used by entity_kill / mythic_mob_kill; skips the source when a spawner is found near the kill location. |
anti_abuse.spawner_scan_radius | Default 8; the effective scan radius is clamped to 0–16. Used together with ignore_near_spawner. |
attribution.expire_ticks | Default 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. |
rules | Match rule list. One source uses the first matching rule. |
actions.gain | Reserved 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.
| trigger | Event source | Match fields | Formula variables | Default target type |
|---|---|---|---|---|
entity_kill | CoreLib shared event; killer or recent damager | entity_types | %entity_type% | combat |
mythic_mob_kill | CoreLib shared event; MythicMobs mob detected in the same death | mob_ids | %mythic_id%, %mythic_level% | combat |
block_break | CoreLib shared event; player breaks a block | blocks | %block_type% | mining / logging / gathering |
crop_harvest | Derived from block_break; the broken block is a mature Ageable crop | blocks | %block_type% | farming |
player_fish | CoreLib shared event; player fishing | states | %fish_state% | fishing |
craft_item | CoreLib shared event; player crafts an item | result_item_sources | %result_amount%, %result_type% | crafting |
brew_complete | CoreLib shared event; attributed to the most recent brewing stand user | potion_types | %potion_type% | brewing |
furnace_extract | CoreLib shared event; player extracts a furnace result | result_item_sources | %result_amount%, %result_type% | smelting |
entity_tame | CoreLib shared event; player tames an entity | entity_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:
| Field | Purpose |
|---|---|
entity_types | Bukkit EntityType, e.g. ZOMBIE, WOLF, ENDER_DRAGON. |
blocks | Bukkit Material, e.g. STONE, WHEAT, OAK_LOG. |
states | Event state names, e.g. CAUGHT_FISH. |
result_item_sources | CoreLib ItemSource values, e.g. minecraft-diamond_pickaxe. Used by crafting and smelting results. |
potion_types | Potion base types, e.g. AWKWARD, SPEED, STRENGTH. |
mob_ids | MythicMobs internal IDs, e.g. SkeletonKing. Matching is case-normalized. |
exp_formula | Exp 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, andpotion_typesare normalized to uppercase for matching.result_item_sourcesuses CoreLib ItemSource matching, not only vanilla materials.
Exp formulas
Exp formulas use the CoreLib expression engine and %key% variables.
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
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: falseprevents player kills from granting exp.- With
ignore_near_spawner: true, blocks withinspawner_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
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: truerecords 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: falseprevents 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_ticksare pruned on the next read/write.
Mature crops use the same break event, but only trigger when block data is Ageable and fully grown:
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
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
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:
| Variable | Description |
|---|---|
%result_amount% | Recipe result stack amount, minimum 1. |
%result_type% | Bukkit Material name. |
Brewing
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.
| Variable | Description |
|---|---|
%potion_type% | First recognized potion base type in the brewing inventory, or UNKNOWN. |
Smelting
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:
| Variable | Description |
|---|---|
%result_amount% | Amount extracted from the furnace. |
%result_type% | Bukkit Material name. |
Taming
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.
| Variable | Description |
|---|---|
%entity_type% | Bukkit EntityType of the tamed entity. |
Custom examples
Main exp for fishing events:
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:
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:
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.