简体中文
配置详解
下面逐份说明 EmakiLevel 的配置: 主配置 config.yml, 升级需求 requirements.yml, 等级类型 types/*.yml 和玩家数据文件里每个字段的作用
EmakiLevel 的配置分为主配置, 升级需求, 等级类型, 经验来源, GUI 和语言文件. 你平时最常改的是这几处:
config.yml: 全局开关requirements.yml: 升级经验曲线types/*.yml: 等级类型, 升级行为, 奖励, 消耗, 属性贡献sources/*.yml: 哪些事件给哪些类型经验
修改后执行 /elv reload 即可重载大部分配置并同步在线玩家
config.yml
默认主配置:
yaml
version: "1.6.9"
language: "zh_CN"
release_default_data: true
primary_type: "main"
level:
default_start_level: 1
default_max_level: 100
max_auto_upgrade_steps: 10
keep_total_exp_at_max_level: true
multipliers:
enabled: true
global: 1.0
types:
main: 1.0
combat: 1.0
cooking: 1.0
forging: 1.0
reasons:
action: 1.0
mythic_drop: 1.0
event_bonus: 1.0
daily_caps:
enabled: true
default_limit: -1
types:
main: -1
combat: -1
cooking: -1
forging: -1
pdc:
enabled: true
namespace: "emakilevel"
attribute:
enabled: true
provider_id: "emakilevel"
mythicmobs:
enabled: true
kill_sources: true
drops:
enabled: true
names:
- "emakilevel_exp"
- "elv_exp"
anti_abuse:
placed_block_tracking: true
placed_block_exp: false
placed_block_record_ttl_ticks: 864000
last_damager_tracking:
enabled: true
expire_ticks: 200
gui:
enabled: true
default_template: "level_gui"字段说明:
| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
version | string | 否 | 1.6.9 | — | 默认资源的版本标记, 由资源同步流程维护. 它只是个标记, 不是功能开关, 不用改 |
language | string | 否 | zh_CN | — | 指定用哪个语言文件, 即 lang/<language>.yml |
release_default_data | boolean | 否 | true | true / false | 缺了默认数据文件时, 要不要把插件内置的 requirements.yml, types/, sources/, gui/ 写出来 |
primary_type | string | 否 | main | 已加载的等级类型 ID | 默认的主等级类型. /elv levelup 不填类型, 以及部分 Action 不填类型时, 就用它 |
level.default_start_level | int | 否 | 1 | — | 等级类型自己没写 start_level 时, 用这个值作为起始等级 |
level.default_max_level | int | 否 | 100 | — | 等级类型自己没写 max_level 时, 用这个值作为最高等级 |
level.max_auto_upgrade_steps | int | 否 | 10 | 小于 1 时按 1 处理 | 一次经验变化最多自动连升几级, 防止一次给太多经验时无限循环升级 |
level.keep_total_exp_at_max_level | boolean | 否 | true | true / false | 满级后继续获得经验时, total_exp 还要不要继续累加. 当前等级内的 exp 这时不再增加 |
multipliers.enabled | boolean | 否 | true | true / false | 是否启用经验倍率. 关掉后倍率固定为 1.0 |
multipliers.global | double | 否 | 1.0 | 结果不小于 0 | 全局经验倍率 |
multipliers.types.<type> | double | 否 | 1.0 | 结果不小于 0 | 按等级类型分别设的倍率. 键名会统一转成小写, 没列出的类型按 1.0 算 |
multipliers.reasons.<reason> | double | 否 | 1.0 | 结果不小于 0 | 按经验来源 reason 分别设的倍率. 键名会统一转成小写, 没列出的 reason 按 1.0 算 |
daily_caps.enabled | boolean | 否 | true | true / false | 是否启用每日经验上限 |
daily_caps.default_limit | double | 否 | -1 | -1 或正数 | 没有为某个类型单独设上限时, 用这个值. -1 表示不限制 |
daily_caps.types.<type> | double | 否 | -1 | -1 或正数 | 按等级类型分别设的每日上限. -1 表示不限制 |
pdc.enabled | boolean | 否 | true | true / false | 是否把在线玩家的等级数据写进 PDC, 也就是写在实体上, 重启也不会丢的那份数据 |
pdc.namespace | string | 否 | emakilevel | — | PDC 的命名空间, 相当于给数据分组用的前缀. 留空时用 emakilevel |
attribute.enabled | boolean | 否 | true | true / false | 是否试着把等级换算成 EmakiAttribute 的属性贡献. 这个功能需要服务器装了 EmakiAttribute |
attribute.provider_id | string | 否 | emakilevel | — | 注册到 EmakiAttribute 时用的属性来源 ID |
mythicmobs.enabled | boolean | 否 | true | true / false | MythicMobs 集成的总开关. 关掉后击杀来源和 Drop 都不处理 |
mythicmobs.kill_sources | boolean | 否 | true | true / false | 是否启用 mythic_mob_kill 这条来源规则 |
mythicmobs.drops.enabled | boolean | 否 | true | true / false | 是否注册 MythicMobs 的非实物经验 Drop |
mythicmobs.drops.names | list<string> | 否 | emakilevel_exp, elv_exp | — | 能识别的 Drop 名称. 留空时用上面那两个默认名称 |
anti_abuse.placed_block_tracking | boolean | 否 | true | true / false | 是否记录玩家放置过的方块位置 |
anti_abuse.placed_block_exp | boolean | 否 | false | true / false | 玩家自己放下去又挖掉的方块, 要不要给经验. 默认不给 |
anti_abuse.placed_block_record_ttl_ticks | int | 否 | 864000 | <=0 表示不清理 | 放置方块记录能保存多久, 单位是 tick, 也就是 1/20 秒 (一个游戏刻). 超时的记录会在下一次读写时清掉 |
anti_abuse.last_damager_tracking.enabled | boolean | 否 | true | true / false | 是否接受非直接击杀的击杀事件, 也就是把击杀算给最近造成伤害的玩家. 设为 false 时只处理 Bukkit 判定的直接击杀者 |
anti_abuse.last_damager_tracking.expire_ticks | int | 否 | 200 | — | 这个键在默认配置里保留着, 但当前代码不读它. 最近伤害的归属窗口实际由 CoreLib config.yml > gameplay_events.last_damager_expire_ticks 控制, 默认同样是 200 |
gui.enabled | boolean | 否 | true | true / false | 是否启用等级界面 |
gui.default_template | string | 否 | level_gui | — | 默认使用的界面模板 ID |
经验倍率与每日上限
multipliers 和 daily_caps 在经验写入玩家之前生效, 处理顺序是: 倍率 → 每日上限
倍率计算方式:
text
倍率 = multipliers.global × multipliers.types.<type> × multipliers.reasons.<reason>types与reasons中未列出的键按1.0处理, 不参与相乘multipliers.enabled: false时倍率固定为1.0- 倍率结果不会小于 0
<reason>就是经验来源传入的 reason, 例如来源规则的 trigger ID, Action 的reason参数, MythicMobs Drop 的reason
每日上限:
daily_caps.enabled: false时不限制- 类型有
daily_caps.types.<type>时使用该值, 否则使用daily_caps.default_limit -1表示不限制- 当日剩余额度不足时, 本次经验会被裁剪到剩余额度; 额度为 0 时本次操作返回失败原因
daily_cap_reached - 计数按系统默认时区的日期按天分开统计, 只保存在内存里, 服务器重启后就清零
requirements.yml
requirements.yml 控制升级所需经验. 默认结构:
yaml
global:
formula: "floor(100 + 25 * %target_level% + 8 * pow(%target_level%, 2))"
values: {}
groups:
main:
formula: "floor(150 + 40 * %target_level% + 14 * pow(%target_level%, 2))"
values:
2: 150
3: 350
4: 750
5: 1200
combat:
formula: "floor(60 + 18 * %target_level% + 5 * pow(%target_level%, 2))"
values:
2: 80
3: 160
4: 300
# mining / logging / farming / fishing / gathering / taming 使用与 combat 相同的默认曲线
crafting:
formula: "floor(80 + 22 * %target_level% + 6 * pow(%target_level%, 2))"
values: {}
# brewing / cooking / forging / smelting 使用与 crafting 相同的默认曲线默认 requirements.yml 为每个内置等级类型各写了一个同名分组: main, combat, mining, logging, farming, fishing, gathering, taming, crafting, brewing, cooking, forging, smelting. types/<type>.yml > requirement.group 默认指向同名分组
字段说明:
| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
global | mapping | 否 | — | — | 全局需求分组, 是所有类型最后的备用来源 |
global.formula | string | 否 | floor(100 + 25 * %target_level% + 8 * pow(%target_level%, 2)) | 表达式 | 全局需求公式, 在类型与分组都未提供公式时使用 |
global.values.<level> | mapping<int, double> | 否 | {} | 键为正整数等级, 值为需求经验 | 全局层面写死的具体等级需求值. 精确值大于 0 时优先用精确值, 不用公式 |
groups | mapping | 否 | — | — | 需求分组的集合, 里面的键名就是 requirement.group 引用的分组 ID |
groups.<group> | mapping | 否 | — | — | 一个需求分组 |
groups.<group>.formula | string | 否 | 见发货文件 (各内置分组各有默认曲线) | 表达式 | 分组需求公式 |
groups.<group>.values.<level> | mapping<int, double> | 否 | 见发货文件 (main/combat 等分组带示例值) | 键为正整数等级, 值为需求经验 | 分组层面写死的具体等级需求值 |
解析优先级
当玩家从当前等级升到 target_level 时, 需求经验按以下顺序查找:
types/<type>.yml > requirement.values.<target_level>types/<type>.yml > requirement.formularequirements.yml > groups.<group>.values.<target_level>requirements.yml > groups.<group>.formularequirements.yml > global.values.<target_level>requirements.yml > global.formula
只要精确值存在且大于 0, 就优先使用精确值; 否则继续找公式
需求公式变量
需求公式由 CoreLib 表达式引擎计算, 用 %key% 这种变量写法. 注意: 需求按类型缓存, 公式只跟目标等级有关, 拿不到玩家当前的实时等级和经验:
| 变量 | 说明 |
|---|---|
%current_level% | 恒为该类型 start_level (当前实现不注入玩家实时等级) |
%target_level% | 本次要升到的目标等级 |
%max_level% | 该类型最高等级 |
%exp% | 恒为 0 (当前实现不注入玩家实时经验) |
%total_exp% | 恒为 0 (当前实现不注入玩家实时总经验) |
示例:
yaml
groups:
hard_profession:
formula: "floor(120 + 35 * %target_level% + 10 * pow(%target_level%, 2))"
values:
2: 100
3: 250可以用 /elv debug requirement <type> <level> 检查某个目标等级最终命中的来源和值
types/*.yml
每个 types/*.yml 文件定义一个等级类型. 文件名只是备用的 ID, 最终以文件里写的 id 为准
基础结构:
yaml
id: "combat"
enabled: true
display_name: "<red>战斗等级</red>"
description:
- "<gray>通过击杀实体或 MythicMobs 生物获得经验。</gray>"
primary: false
start_level: 1
max_level: 80
requirement:
group: "combat"
formula: ""
values: {}
upgrade:
enabled: true
auto_upgrade: true
manual_upgrade: true
cost:
enabled: false
economy:
enabled: false
currencies: []
materials: []
rewards:
items: []
actions:
gain: []
success: []
failure: []
pdc:
enabled: true
attributes:
enabled: true
values:
physical_attack: "%level% * 0.25"字段说明:
| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
id | string | 否 | 文件名 (去掉 .yml) | — | 等级类型唯一 ID. 命令, Placeholder, 来源规则, Action 都引用它 |
enabled | boolean | 否 | true | true / false | 是否启用. 禁用后不能获得经验或升级 |
display_name | string | 否 | id | — | 显示名称, 用 MiniMessage 格式; 留空时用 id |
description | list<string> | 否 | [] | — | 一段一段的描述文本, 供配置维护和界面展示用 |
primary | boolean | 否 | false | true / false | 是否把该类型标记为主等级, 只是个标记. 真正的主类型还是看 config.yml > primary_type |
start_level | int | 否 | config.yml > level.default_start_level (发货默认 1) | — | 玩家初始等级, 也是 reset 后等级 |
max_level | int | 否 | config.yml > level.default_max_level (发货默认 100) | — | 最高等级. 直接设置等级也会被限制在此范围内 |
requirement.group | string | 否 | global | 已定义的组名 | 使用 requirements.yml > groups.<group> |
requirement.formula | string | 否 | "" | 表达式 | 该类型专用的需求公式. 不为空时会盖过分组和全局的公式 |
requirement.values.<level> | mapping<int, double> | 否 | {} | 键为正整数等级 | 该类型专用的目标等级精确值, 优先级最高 |
upgrade.enabled | boolean | 否 | true | true / false | 是否允许升级. 关闭后自动/手动都无法升级 |
upgrade.auto_upgrade | boolean | 否 | true | true / false | 获得经验后是否自动升级 |
upgrade.manual_upgrade | boolean | 否 | true | true / false | 是否允许玩家执行 /elv levelup |
upgrade.cost.enabled | boolean | 否 | false | true / false | 是否收取升级消耗. 关闭后不检查经济与材料 |
upgrade.cost.economy.enabled | boolean | 否 | false | true / false | 是否启用经济消耗; 仅 cost.enabled: true 时生效 |
upgrade.cost.economy.currencies[] | list<mapping> | 否 | [] | 见"经济消耗" | 经济消耗条目, 仅 economy.enabled: true 时读取, cost.enabled: true 时生效 |
upgrade.cost.materials[] | list<mapping> | 否 | [] | 见"材料消耗" | 材料消耗条目, 仅 cost.enabled: true 时生效 |
upgrade.rewards.items[] | list<mapping> | 否 | [] | 见"升级奖励" | 升级成功时的奖励条目 |
upgrade.actions.gain | list<string> | 否 | [] | CoreLib Action 行 | 获得经验后执行的 Action |
upgrade.actions.success | list<string> | 否 | [] | CoreLib Action 行 | 升级成功后执行的 Action |
upgrade.actions.failure | list<string> | 否 | [] | CoreLib Action 行 | 升级失败后执行的 Action |
pdc.enabled | boolean | 否 | true | true / false | 该类型要不要同步 PDC. 还需要全局 pdc.enabled 也是 true 才生效 |
attributes.enabled | boolean | 否 | false | true / false | 该类型要不要向 EmakiAttribute 贡献属性; 不写这个键时就当成 false |
attributes.values.<attr> | mapping<string, string> | 否 | {} | 属性 ID → 公式 | 属性 ID 到公式表达式的对应关系 |
升级消耗
升级消耗只有在 upgrade.cost.enabled: true 时生效
经济消耗
yaml
upgrade:
cost:
enabled: true
economy:
enabled: true
currencies:
- provider: "auto"
currency_id: ""
base_cost: 100
cost_formula: "%base_cost% * %target_level%"
display_name: "<gold>金币</gold>"| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
provider | string | 否 | auto | CoreLib 经济提供器名, 常用 auto, vault, excellenteconomy | 指定用哪个经济提供器 |
currency_id | string | 否 | "" | — | 经济插件的货币 ID. 用 Vault 时留空, 换成支持多货币的经济插件时按它自己的货币 ID 填 |
base_cost | double | 否 | 0 | — | 基础费用, 会作为 %base_cost% 进入公式 |
cost_formula | string | 否 | %base_cost% * %target_level% | 表达式, 结果 ≤0 时不扣费 | 最终费用公式 |
display_name | string | 否 | "" | — | 展示用的名称, 目前主要为了方便看配置和后续界面展示用 |
经济公式变量:
| 变量 | 说明 |
|---|---|
%target_level% | 本次目标等级 |
%type% | 等级类型 ID |
%base_cost% | 当前货币条目的基础费用 |
材料消耗
yaml
upgrade:
cost:
enabled: true
materials:
- item_sources:
- "minecraft-diamond"
base_amount: 1
amount_formula: "%base_amount% + floor(%target_level% / 10)"| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
item_sources | list<string> | 否 | [] | 合法 CoreLib ItemSource | 可以被消耗的 CoreLib ItemSource 列表. 插件按列表顺序扣除; 认不出来的条目会被跳过 |
base_amount | long | 否 | 1 (也兼容 amount 作为输入) | — | 基础数量, 会作为 %base_amount% 进入公式. 新配置建议写 base_amount |
amount_formula | string | 否 | %base_amount% | 表达式, 结果四舍五入为长时间, ≤0 时不扣材料 | 最终扣除数量公式 |
材料公式变量:
| 变量 | 说明 |
|---|---|
%target_level% | 本次目标等级 |
%type% | 等级类型 ID |
%base_amount% | 当前材料条目的基础数量 |
升级奖励
yaml
upgrade:
rewards:
items:
- levels: "*"
item_source: "minecraft-experience_bottle"
amount: 1
- levels: "10,20,30"
item_source: "minecraft-diamond"
amount: 2
- levels: "50-60"
item_source: "minecraft-nether_star"
amount: 1| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
levels | string | 否 | * | *, 单等级, 逗号列表 (10,20,30) 或 min-max 范围 (50-60) | 这条奖励在哪些等级发放 |
item_source | string | 是 (与 item_sources 二选一) | — | 合法 CoreLib ItemSource | 奖励物品的来源, 这是推荐的写法, 只能写一个 |
item_sources | list<string> | 是 (与 item_source 二选一) | — | 恰好 1 个合法 ItemSource | 旧写法, 只能且必须有 1 项 |
amount | int | 否 | 1 | 最小 1 | 奖励数量 |
item_source 与 item_sources 不能同时声明, item_sources 也只能包含 1 项; 违反任一条会在加载期抛错. 奖励条目上不允许写 matcher. 奖励通过 CoreLib ItemSource 创建物品, 并使用 give-or-drop 逻辑发放; 玩家背包满时会掉落
升级动作变量
upgrade.actions.gain, success, failure 都是 CoreLib Action 字符串列表. 动作上下文提供以下变量:
| 变量 | 说明 |
|---|---|
%type% | 等级类型 ID |
%type_display_name% | 等级类型显示名 |
%level% | 当前等级 |
%old_level% | 操作前等级 |
%new_level% | 操作后等级 |
%exp% | 当前等级内经验, 已格式化 |
%old_exp% | 操作前经验, 已格式化 |
%new_exp% | 操作后经验, 已格式化 |
%total_exp% | 总经验, 已格式化 |
%required_exp% | 升到下一级所需经验, 已格式化 |
%progress% | 0 到 1 的数值进度 |
%progress_percent% | 0 到 100 的百分比数值, 已格式化 |
%amount% | 本次经验或等级操作数量, 已格式化 |
%reason% | 操作原因 |
%failure_reason% | 失败原因; 失败动作里会用到它 |
示例:
yaml
upgrade:
actions:
gain:
- '@chance=10 send_action_bar text="<gray>%type_display_name% 经验 +%amount%</gray>"'
success:
- 'send_message text="<green>%type_display_name% 提升到了 <yellow>%new_level%</yellow> 级!</green>"'
- 'broadcast_message text="<gold>%player%</gold> 的 %type_display_name% 达到了 <yellow>%new_level%</yellow> 级"'
failure:
- 'send_message text="<red>升级失败: %failure_reason%</red>"'属性贡献
安装并启用 EmakiAttribute 后, EmakiLevel 会把启用的等级类型注册为属性贡献来源. 默认来源 ID 是 config.yml > attribute.provider_id, 即 emakilevel
yaml
attributes:
enabled: true
values:
physical_attack: "%level% * 0.25"
physical_crit_rate: "%level% * 0.02"属性公式变量:
| 变量 | 说明 |
|---|---|
%level% | 玩家该类型当前等级 |
%exp% | 当前等级内经验 |
%total_exp% | 总经验 |
当经验, 等级或配置重载导致等级变化时, 插件会尝试刷新在线玩家的 Attribute 属性贡献. 没有安装 EmakiAttribute 时, 这部分会自动跳过, 不影响等级系统本体运行
PDC 同步
全局 pdc.enabled: true 且类型 pdc.enabled: true 时, 在线玩家实体会写入以下逻辑字段:
| 字段 | 类型 | 说明 |
|---|---|---|
player/<type>_level | int | 当前等级 |
player/<type>_exp | double | 当前等级内经验 |
player/<type>_total_exp | double | 总经验 |
player/<type>_required_exp | double | 升到下一级所需经验 |
player/<type>_progress | double | 0 到 1 的进度 |
这些字段放在 config.yml > pdc.namespace 指定的命名空间下, 默认是 emakilevel, 逻辑上归在 player 这一组. PDC 同步会发生在玩家加入, 经验变化, 等级变化, 重载, 以及执行 /elv debug pdc 时
玩家数据文件
玩家数据位于 data/<uuid>.yml, 里面的字段含义如下:
yaml
schema_version: 1
uuid: "00000000-0000-0000-0000-000000000000"
name: "PlayerName"
levels:
main:
level: 1
exp: 0.0
total_exp: 0.0
updated_at: 1730000000000说明:
level是当前等级exp是当前等级内经验, 升级时会扣除需求经验total_exp是累计经验, 用于排行榜排序和长期统计updated_at是最近更新时间戳- 新增等级类型后, 玩家下次加载数据时会自动补齐该类型起始数据
不建议在服务器运行时手改 data/*.yml. 如果确实需要修正数据, 优先使用 /elv setexp, /elv setlevel 或 /elv reset