经验来源
经验来源文件位于 plugins/EmakiLevel/sources/*.yml。每个文件可以包含多个来源规则,规则通过 trigger 绑定到 Bukkit 或 MythicMobs 事件,再通过匹配条件选择经验公式。
默认来源文件:
| 文件 | 默认来源 | 说明 |
|---|---|---|
combat.yml | vanilla_entity_kill | 原版实体击杀经验。 |
mythicmobs.yml | mythic_mob_kill | MythicMob 击杀经验。 |
block_actions.yml | mining、logging、gathering、farming | 方块破坏、采集、成熟作物收获。 |
fishing.yml | player_fish | 钓鱼事件经验。 |
crafting.yml | craft_item | 合成结果经验。 |
brewing.yml | brew_complete | 炼药完成经验。 |
smelting.yml | furnace_extract | 熔炉提取结果经验。 |
taming.yml | entity_tame | 驯养实体经验。 |
文件结构
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"顶层字段:
| 字段 | 说明 |
|---|---|
id | 来源文件标识,主要用于配置可读性。 |
enabled | 文件总开关。false 时跳过整个文件。 |
sources | 来源规则映射,键名是来源规则 ID。 |
单个来源规则字段:
| 字段 | 说明 |
|---|---|
enabled | 单条来源开关。 |
type | 获得经验的等级类型 ID。 |
trigger | 触发器 ID,见下方触发器表。 |
include_players | 仅 entity_kill 使用;是否允许击杀玩家也给经验。默认 false。 |
count_result_amount | 默认 false。当前实现读取该键但不用于经验计算,结果数量通过公式变量 %result_amount% 使用。 |
anti_abuse.ignore_player_placed_blocks | 默认 false。block_break / crop_harvest 来源使用;是否忽略玩家放置过的方块。 |
anti_abuse.exp_cooldown_ticks | 默认 0(无冷却)。同一玩家在同一来源上的经验发放冷却,单位 tick。发放成功后才会开始计时。 |
anti_abuse.ignore_near_spawner | 默认 false。仅 entity_kill / mythic_mob_kill 使用;击杀点附近存在刷怪笼时跳过该来源。 |
anti_abuse.spawner_scan_radius | 默认 8,实际扫描半径会被限制在 0–16。配合 ignore_near_spawner 使用。 |
attribution.expire_ticks | 默认 1200。仅 brew_complete 使用;炼药完成事件距离玩家最后一次操作炼药台超过该 tick 数时跳过。 |
rules | 匹配规则列表。每个来源会按顺序找到第一条匹配规则。 |
actions.gain | 配置入口保留;当前实现不执行该列表。等级类型自身的 upgrade.actions.gain 是实际生效的经验获得动作。 |
触发器总览
完整共享事件 ID 说明见 CoreLib 的 共享玩法事件 ID。本页只列出 EmakiLevel 经验来源常用字段。
| trigger | 事件来源 | 常用匹配字段 | 公式变量 | 默认目标类型 |
|---|---|---|---|---|
entity_kill | CoreLib 共享事件;击杀者或最近伤害玩家 | entity_types | %entity_type% | combat |
mythic_mob_kill | CoreLib 共享事件;同次死亡中识别到的 MythicMobs 怪物 | mob_ids | %mythic_id%、%mythic_level% | combat |
block_break | CoreLib 共享事件;玩家破坏方块 | blocks | %block_type% | mining / logging / gathering |
crop_harvest | block_break 的派生触发;被破坏方块是已成熟 Ageable 作物 | blocks | %block_type% | farming |
player_fish | CoreLib 共享事件;玩家钓鱼 | states | %fish_state% | fishing |
craft_item | CoreLib 共享事件;玩家合成物品 | result_item_sources | %result_amount%、%result_type% | crafting |
brew_complete | CoreLib 共享事件;归属到最近操作炼药台的玩家 | potion_types | %potion_type% | brewing |
furnace_extract | CoreLib 共享事件;玩家从熔炉取出产物 | result_item_sources | %result_amount%、%result_type% | smelting |
entity_tame | CoreLib 共享事件;玩家驯服实体 | entity_types | %entity_type% | taming |
CoreLib 还会发出 block_place 共享事件,EmakiLevel 只用它记录玩家放置过的方块位置;把 block_place 写进来源规则的 trigger 不会产生任何经验。
规则匹配
每条规则支持以下匹配字段:
| 字段 | 用途 |
|---|---|
entity_types | 匹配 Bukkit EntityType,例如 ZOMBIE、WOLF、ENDER_DRAGON。 |
blocks | 匹配 Bukkit Material,例如 STONE、WHEAT、OAK_LOG。 |
states | 匹配事件状态,例如钓鱼事件的 CAUGHT_FISH。 |
result_item_sources | 匹配 CoreLib ItemSource,例如 minecraft-diamond_pickaxe。适用于合成与冶炼结果。 |
potion_types | 匹配药水基础类型,例如 AWKWARD、SPEED、STRENGTH。 |
mob_ids | 匹配 MythicMobs 内部 ID,例如 SkeletonKing。匹配时会做大小写归一。 |
exp_formula | 经验公式。返回值小于等于 0 时不会给经验。 |
匹配行为:
- 同一个
trigger可以有多条来源;事件触发时会遍历所有同 trigger 来源。 - 每个来源内部按
rules顺序寻找第一条匹配规则。 - 某个匹配字段为空时,表示该字段不限制;例如没有写
entity_types的规则可以匹配所有实体。 entity_types、blocks、states、potion_types会转为大写后匹配。result_item_sources使用 CoreLib ItemSource 识别物品来源,不只是原版 Material。
经验公式
经验公式使用 CoreLib 表达式引擎和 %key% 变量语法。
示例:
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"如果公式返回 0 或负数,插件会跳过本次经验发放。
原版击杀
默认配置:
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"行为说明:
- 击杀归属由 CoreLib 共享事件解析:优先使用 Bukkit killer。
- 如果不是直接击杀,并且
anti_abuse.last_damager_tracking.enabled: false,EmakiLevel 会跳过本次事件。 - 最近伤害归属窗口由 CoreLib
config.yml > gameplay_events.last_damager_expire_ticks控制,默认 200 ticks。 include_players: false时,击杀玩家不会给经验。ignore_near_spawner: true时,会以击杀点为中心扫描spawner_scan_radius(0–16)范围内的方块,发现刷怪笼即跳过该来源。半径越大扫描的方块越多,建议保持默认 8。
方块破坏与作物收获
默认挖掘来源:
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"
- blocks: ["DIAMOND_ORE", "DEEPSLATE_DIAMOND_ORE", "EMERALD_ORE", "DEEPSLATE_EMERALD_ORE"]
exp_formula: "25"防刷行为:
anti_abuse.placed_block_tracking: true时,玩家放置过的方块位置会被记录。- 如果来源设置
ignore_player_placed_blocks: true,该来源会跳过玩家放置过的方块。 - 即使来源没有写
ignore_player_placed_blocks,当anti_abuse.placed_block_exp: false时,玩家放置过的方块也不会给破坏经验。 - 记录在方块被破坏后移除;超过
anti_abuse.placed_block_record_ttl_ticks的记录会在下一次读写时清理。
成熟作物来源使用同一个破坏事件,但只有方块数据是 Ageable 且已成熟时才触发:
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"一次破坏成熟作物会同时触发 block_break 和 crop_harvest 两个触发器,两类来源都可能各自发放经验。
钓鱼
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% 对应 PlayerFishEvent.State 名称。常见状态包括 CAUGHT_FISH、CAUGHT_ENTITY、FISHING、BITE、FAILED_ATTEMPT 等;默认只对真正钓到物品或实体给经验。
合成
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%"合成来源会读取配方结果物品并使用 CoreLib ItemSource 识别。公式变量:
| 变量 | 说明 |
|---|---|
%result_amount% | 配方结果堆叠数量,至少为 1。 |
%result_type% | Bukkit Material 名称。 |
炼药
sources:
brew_complete:
enabled: true
type: "brewing"
trigger: "brew_complete"
attribution:
expire_ticks: 1200
rules:
- potion_types: ["AWKWARD", "SPEED", "STRENGTH"]
exp_formula: "15"炼药台事件本身不直接提供玩家,CoreLib 会记录最近操作该炼药台的玩家,并在炼药完成时把经验归属给该玩家。来源可用 attribution.expire_ticks 设置自己的归属窗口,默认 1200 ticks;事件距离最后一次操作超过该窗口时跳过该来源。公式变量:
| 变量 | 说明 |
|---|---|
%potion_type% | 炼药台产物中第一个可识别药水的基础类型;无法识别时为 UNKNOWN。 |
冶炼
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%"公式变量:
| 变量 | 说明 |
|---|---|
%result_amount% | 玩家从熔炉中取出的物品数量。 |
%result_type% | Bukkit Material 名称。 |
驯养
sources:
entity_tame:
enabled: true
type: "taming"
trigger: "entity_tame"
rules:
- entity_types: ["WOLF", "CAT", "HORSE", "PARROT"]
exp_formula: "20"只有驯养者是玩家时才会发放经验。公式变量:
| 变量 | 说明 |
|---|---|
%entity_type% | 被驯养实体的 Bukkit EntityType。 |
自定义来源示例
新增一个钓到宝藏时给主等级经验的来源:
id: "treasure_sources"
enabled: true
sources:
fishing_treasure_main:
enabled: true
type: "main"
trigger: "player_fish"
rules:
- states: ["CAUGHT_FISH"]
exp_formula: "2"新增一个所有原木都给砍伐经验的来源:
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"新增一个所有非玩家实体击杀都给少量主等级经验的来源:
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"最后一条规则没有写 entity_types,因此会匹配所有实体。