Skip to content

配置详解 ​

下面逐份说明 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"

字段说明:

字段类型必填默认值取值范围说明
versionstring否1.6.9—默认资源的版本标记, 由资源同步流程维护. 它只是个标记, 不是功能开关, 不用改
languagestring否zh_CN—指定用哪个语言文件, 即 lang/<language>.yml
release_default_databoolean否truetrue / false缺了默认数据文件时, 要不要把插件内置的 requirements.yml, types/, sources/, gui/ 写出来
primary_typestring否main已加载的等级类型 ID默认的主等级类型. /elv levelup 不填类型, 以及部分 Action 不填类型时, 就用它
level.default_start_levelint否1—等级类型自己没写 start_level 时, 用这个值作为起始等级
level.default_max_levelint否100—等级类型自己没写 max_level 时, 用这个值作为最高等级
level.max_auto_upgrade_stepsint否10小于 1 时按 1 处理一次经验变化最多自动连升几级, 防止一次给太多经验时无限循环升级
level.keep_total_exp_at_max_levelboolean否truetrue / false满级后继续获得经验时, total_exp 还要不要继续累加. 当前等级内的 exp 这时不再增加
multipliers.enabledboolean否truetrue / false是否启用经验倍率. 关掉后倍率固定为 1.0
multipliers.globaldouble否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.enabledboolean否truetrue / false是否启用每日经验上限
daily_caps.default_limitdouble否-1-1 或正数没有为某个类型单独设上限时, 用这个值. -1 表示不限制
daily_caps.types.<type>double否-1-1 或正数按等级类型分别设的每日上限. -1 表示不限制
pdc.enabledboolean否truetrue / false是否把在线玩家的等级数据写进 PDC, 也就是写在实体上, 重启也不会丢的那份数据
pdc.namespacestring否emakilevel—PDC 的命名空间, 相当于给数据分组用的前缀. 留空时用 emakilevel
attribute.enabledboolean否truetrue / false是否试着把等级换算成 EmakiAttribute 的属性贡献. 这个功能需要服务器装了 EmakiAttribute
attribute.provider_idstring否emakilevel—注册到 EmakiAttribute 时用的属性来源 ID
mythicmobs.enabledboolean否truetrue / falseMythicMobs 集成的总开关. 关掉后击杀来源和 Drop 都不处理
mythicmobs.kill_sourcesboolean否truetrue / false是否启用 mythic_mob_kill 这条来源规则
mythicmobs.drops.enabledboolean否truetrue / false是否注册 MythicMobs 的非实物经验 Drop
mythicmobs.drops.nameslist<string>否emakilevel_exp, elv_exp—能识别的 Drop 名称. 留空时用上面那两个默认名称
anti_abuse.placed_block_trackingboolean否truetrue / false是否记录玩家放置过的方块位置
anti_abuse.placed_block_expboolean否falsetrue / false玩家自己放下去又挖掉的方块, 要不要给经验. 默认不给
anti_abuse.placed_block_record_ttl_ticksint否864000<=0 表示不清理放置方块记录能保存多久, 单位是 tick, 也就是 1/20 秒 (一个游戏刻). 超时的记录会在下一次读写时清掉
anti_abuse.last_damager_tracking.enabledboolean否truetrue / false是否接受非直接击杀的击杀事件, 也就是把击杀算给最近造成伤害的玩家. 设为 false 时只处理 Bukkit 判定的直接击杀者
anti_abuse.last_damager_tracking.expire_ticksint否200—这个键在默认配置里保留着, 但当前代码不读它. 最近伤害的归属窗口实际由 CoreLib config.yml > gameplay_events.last_damager_expire_ticks 控制, 默认同样是 200
gui.enabledboolean否truetrue / false是否启用等级界面
gui.default_templatestring否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 默认指向同名分组

字段说明:

字段类型必填默认值取值范围说明
globalmapping否——全局需求分组, 是所有类型最后的备用来源
global.formulastring否floor(100 + 25 * %target_level% + 8 * pow(%target_level%, 2))表达式全局需求公式, 在类型与分组都未提供公式时使用
global.values.<level>mapping<int, double>否{}键为正整数等级, 值为需求经验全局层面写死的具体等级需求值. 精确值大于 0 时优先用精确值, 不用公式
groupsmapping否——需求分组的集合, 里面的键名就是 requirement.group 引用的分组 ID
groups.<group>mapping否——一个需求分组
groups.<group>.formulastring否见发货文件 (各内置分组各有默认曲线)表达式分组需求公式
groups.<group>.values.<level>mapping<int, double>否见发货文件 (main/combat 等分组带示例值)键为正整数等级, 值为需求经验分组层面写死的具体等级需求值

解析优先级 ​

当玩家从当前等级升到 target_level 时, 需求经验按以下顺序查找:

  1. types/<type>.yml > requirement.values.<target_level>
  2. types/<type>.yml > requirement.formula
  3. requirements.yml > groups.<group>.values.<target_level>
  4. requirements.yml > groups.<group>.formula
  5. requirements.yml > global.values.<target_level>
  6. 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"

字段说明:

字段类型必填默认值取值范围说明
idstring否文件名 (去掉 .yml)—等级类型唯一 ID. 命令, Placeholder, 来源规则, Action 都引用它
enabledboolean否truetrue / false是否启用. 禁用后不能获得经验或升级
display_namestring否id—显示名称, 用 MiniMessage 格式; 留空时用 id
descriptionlist<string>否[]—一段一段的描述文本, 供配置维护和界面展示用
primaryboolean否falsetrue / false是否把该类型标记为主等级, 只是个标记. 真正的主类型还是看 config.yml > primary_type
start_levelint否config.yml > level.default_start_level (发货默认 1)—玩家初始等级, 也是 reset 后等级
max_levelint否config.yml > level.default_max_level (发货默认 100)—最高等级. 直接设置等级也会被限制在此范围内
requirement.groupstring否global已定义的组名使用 requirements.yml > groups.<group>
requirement.formulastring否""表达式该类型专用的需求公式. 不为空时会盖过分组和全局的公式
requirement.values.<level>mapping<int, double>否{}键为正整数等级该类型专用的目标等级精确值, 优先级最高
upgrade.enabledboolean否truetrue / false是否允许升级. 关闭后自动/手动都无法升级
upgrade.auto_upgradeboolean否truetrue / false获得经验后是否自动升级
upgrade.manual_upgradeboolean否truetrue / false是否允许玩家执行 /elv levelup
upgrade.cost.enabledboolean否falsetrue / false是否收取升级消耗. 关闭后不检查经济与材料
upgrade.cost.economy.enabledboolean否falsetrue / 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.gainlist<string>否[]CoreLib Action 行获得经验后执行的 Action
upgrade.actions.successlist<string>否[]CoreLib Action 行升级成功后执行的 Action
upgrade.actions.failurelist<string>否[]CoreLib Action 行升级失败后执行的 Action
pdc.enabledboolean否truetrue / false该类型要不要同步 PDC. 还需要全局 pdc.enabled 也是 true 才生效
attributes.enabledboolean否falsetrue / 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>"
字段类型必填默认值取值范围说明
providerstring否autoCoreLib 经济提供器名, 常用 auto, vault, excellenteconomy指定用哪个经济提供器
currency_idstring否""—经济插件的货币 ID. 用 Vault 时留空, 换成支持多货币的经济插件时按它自己的货币 ID 填
base_costdouble否0—基础费用, 会作为 %base_cost% 进入公式
cost_formulastring否%base_cost% * %target_level%表达式, 结果 ≤0 时不扣费最终费用公式
display_namestring否""—展示用的名称, 目前主要为了方便看配置和后续界面展示用

经济公式变量:

变量说明
%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_sourceslist<string>否[]合法 CoreLib ItemSource可以被消耗的 CoreLib ItemSource 列表. 插件按列表顺序扣除; 认不出来的条目会被跳过
base_amountlong否1 (也兼容 amount 作为输入)—基础数量, 会作为 %base_amount% 进入公式. 新配置建议写 base_amount
amount_formulastring否%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
字段类型必填默认值取值范围说明
levelsstring否**, 单等级, 逗号列表 (10,20,30) 或 min-max 范围 (50-60)这条奖励在哪些等级发放
item_sourcestring是 (与 item_sources 二选一)—合法 CoreLib ItemSource奖励物品的来源, 这是推荐的写法, 只能写一个
item_sourceslist<string>是 (与 item_source 二选一)—恰好 1 个合法 ItemSource旧写法, 只能且必须有 1 项
amountint否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>_levelint当前等级
player/<type>_expdouble当前等级内经验
player/<type>_total_expdouble总经验
player/<type>_required_expdouble升到下一级所需经验
player/<type>_progressdouble0 到 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