Skip to content

配置目录 ​

EmakiAttribute 配置文件的位置, 主配置 config.yml 的字段含义, 以及改完配置后的排查顺序如下

EmakiAttribute 的配置分几块: 主配置, 属性定义, 伤害类型, 条件, Lore 格式和属性平衡文件. 建议你先定好属性 ID 和命名规则, 再去扩展伤害类型和装备来源

默认目录结构 ​

text
plugins/EmakiAttribute/
├── config.yml
├── attribute_balance.yml
├── attributes/
├── damage_types/
├── conditions/
├── lore_formats/
├── presets/
├── gui/
├── lang/
└── data/
路径作用
config.yml主配置, 控制默认资源, 伤害接管, 自然回复, 衰减曲线和原版伤害映射
attribute_balance.yml属性战力分数与平衡参数
attributes/单个属性的定义, 例如攻击, 防御, 暴击, 资源, 原版属性映射
damage_types/伤害类型管线, 例如物理, 投射物, 法术
conditions/属性读取条件 (也就是 PDC 读取规则)
lore_formats/属性展示格式模板
presets/属性预设定义
gui/属性点 GUI 配置 (attribute_points.yml)
lang/多语言文本, 内置 zh_CN.yml 与 en_US.yml
data/运行时数据目录, 例如 data/parent_attributes/<UUID>.yml, 不用手动改

建议修改顺序 ​

  1. 先在 attributes/ 定义属性 ID, 展示名, 数值类型和上限
  2. 再在 lore_formats/ 定义旧物品 Lore 的读取或展示格式
  3. 接着在 damage_types/ 配置伤害阶段
  4. 最后接入 Item, Forge, Strengthen, Gem 等模块写入 PDC 属性
  5. 每次改完先运行 /ea lint, 再 /ea reload 和 /ea resync <player>

主配置字段 ​

下表覆盖 config.yml 的全部顶层键; 嵌套小节 (default_profile, shield, synthetic_hit_feedback, damage_indicator, scaling_curves, allowed_damage_causes) 的字段在各自小节列出

发货默认值 (只列顶层键; default_profile, shield, synthetic_hit_feedback, damage_indicator, allowed_damage_causes 的完整内容见各自小节):

yaml
version: "4.8.7"
language: "zh_CN"
release_default_data: true
attribute_sources:
  read_lore_attributes: true
  read_pdc_attributes: true
  require_lore_pdc_match: false
hard_lock_damage: true
default_damage_type: physical
projectile_damage_type: projectile
vanilla_event_damage:
  enabled: true
  damage_type: physical
same_signature_ignores_invulnerability:
  enabled: true
  window_ms: 500
attack_speed:
  scope: global
regen_interval_ticks: 20
sync_delay_ticks: 1
health_display_scaling:
  enabled: false
  target: 20.0
default_profile:        # 见"默认资源与属性"
shield:                 # 见"盾牌格挡"
synthetic_hit_feedback: # 见"合成命中反馈"
damage_indicator:       # 见"伤害飘字"
scaling_curves: {}      # 默认空映射, 即不启用衰减
allowed_damage_causes:  # 见"原版伤害映射", 默认 33 条 cause 映射
字段类型必填默认值取值范围说明
versionstring否"4.8.7"—配置版本号, 由内置资源同步流程维护, 不要手工改
languagestring否"zh_CN"—语言文件名, 对应 lang/<language>.yml
release_default_databoolean否truetrue / false关掉后, 缺失的内置数据文件 (属性, 伤害类型, 条件, Lore 格式, 预设, GUI 等) 就不再自动生成
attribute_sources.read_lore_attributesboolean否truetrue / false要不要从物品 Lore 解析属性
attribute_sources.read_pdc_attributesboolean否truetrue / false要不要从物品 PDC (挂在物品上的原版附加数据) 读取属性
attribute_sources.require_lore_pdc_matchboolean否falsetrue / false启用后, 同一个属性必须在 Lore 和 PDC 两侧都存在且数值一致, 才计入一次; 只存在一侧或数值不一致, 这个属性就不生效
hard_lock_damageboolean否truetrue / false为了兼容旧配置保留的字段: 配置解析器会读它, 但运行时没有任何地方用它, 改了也不会改变任何行为. 没被 allowed_damage_causes 白名单命中的原版伤害, 由 vanilla_event_damage 决定怎么处理
default_damage_typestring否physical—没指定伤害类型时使用的默认类型; 应该指向一个已经加载的伤害类型 ID, 没加载的话 /ea lint 会报出来
projectile_damage_typestring否projectile—投射物发射时会先把攻击者的属性快照存下来, 命中时用这个伤害类型 ID 结算; 没加载的话 /ea lint 会报出来
vanilla_event_damage.enabledboolean否truetrue / false启用时保留原版事件并原地改写最终伤害 (完美接管); 关闭时取消事件, 由 EA 重施伤害 (兼容模式)
vanilla_event_damage.damage_typestring否同 default_damage_type (physical)—没被单独映射的原版伤害用哪个伤害类型 ID; 只在上一个开关启用时才用得上, 没加载的话 /ea lint 会报出来
same_signature_ignores_invulnerability.enabledboolean否truetrue / false同一个攻击者, 属性快照签名和伤害类型都相同的多段命中, 要不要互相无视原版的受伤间隔
same_signature_ignores_invulnerability.window_mslong否500≥ 0同一批判定的时间窗, 单位毫秒
attack_speed.scopestring否globalglobal / attribute_only攻击速度冷却的接管范围, 填了别的值都按 global 处理. global 会接管所有攻击, 按 Bukkit ATTACK_SPEED 换算冷却; attribute_only 只接管 Lore/PDC 里明确带 EA 攻速的物品
regen_interval_ticksinteger否20≥ 1资源自然回复的计算间隔, 单位是游戏刻 (1/20 秒), 20 个游戏刻就是 1 秒
sync_delay_ticksinteger否1≥ 0属性同步到 Bukkit 的延迟, 单位是游戏刻 (1/20 秒)
health_display_scaling.enabledboolean否falsetrue / false要不要压缩客户端看到的血条显示; 这不改变真实生命值, 也不改变伤害结算
health_display_scaling.targetdouble否20.0有限数值且 > 0客户端血条换算后的目标刻度; 20 就是一排红心. 填了非法值或 ≤ 0 时回退成 20.0
default_profileobject否见"默认资源与属性"—玩家的默认属性与资源基础值
shieldobject否见"盾牌格挡"—盾牌格挡交给谁结算
synthetic_hit_feedbackobject否见"合成命中反馈"—接管原版伤害之后, 用来补上击退和受伤音效
damage_indicatorobject否见"伤害飘字"—伤害飘字的配置
scaling_curvesmap否空 (不启用衰减)—属性超过阈值之后怎么衰减, 详见属性衰减曲线
allowed_damage_causeslist否见"原版伤害映射"—原版 DamageCause 到属性伤害类型的映射白名单

示例: 只从 PDC 读取物品属性, 并保留完美接管

yaml
attribute_sources:
  read_lore_attributes: false
  read_pdc_attributes: true
vanilla_event_damage:
  enabled: true
  damage_type: physical

物品属性来源策略 ​

attribute_sources 控制物品属性是否从 Lore, PDC 读取, 以及双来源是否需要互相校验:

yaml
attribute_sources:
  read_lore_attributes: true
  read_pdc_attributes: true
  require_lore_pdc_match: false

默认模式保持旧行为: 只要启用了 Lore 与 PDC 来源, 它们就会一起参与物品属性收集. 你开启 require_lore_pdc_match 后, 系统会按属性 ID 逐项比较:

  • Lore 与 PDC 都存在且数值一致: 该属性只计入一次
  • 两侧数值不一致: 该属性不计入
  • 仅 Lore 或仅 PDC 存在: 该属性不计入
  • 固定值与区间 (spread) 值都执行相同的一致性检查

注意, 一致模式要求两个读取开关同时打开. 关掉其中任何一个, 预检都会给出警告, 物品属性也无法形成双来源一致结果. 如果 Lore 与 PDC 都关掉, 玩家仍可拥有默认, 临时和其他实体来源属性, 只是装备物品不再贡献 Lore/PDC 属性

默认资源与属性 ​

default_profile 定义玩家初始化时拥有的资源和属性基础值:

yaml
default_profile:
  resources:
    health:
      display_name: "生命值"
      default_max: 20.0
      min_max: 1.0
      max_max: 2048.0
      sync_to_bukkit: true
      full_on_init: true
    mana:
      display_name: "法力值"
      default_max: 100.0
      min_max: 0.0
      max_max: 99999.0
      sync_to_bukkit: false
      full_on_init: true
  attributes:
    physical_attack: 0.0
    physical_defense: 0.0
    health_regen: 0.1
    mana_regen: 0.1

default_profile.resources.<id> ​

每个小节 key 就是资源 ID. 字段如下:

字段类型必填默认值取值范围说明
<资源 id> (小节 key)string否小节 key—资源 ID, 同时作为资源定义的 id (如 health, mana)
display_namestring否同资源 ID—展示名称
default_maxdouble否0有限数值 (非法回退 0)默认最大值; 填了非法值会回退成 0
min_maxdouble否0有限数值最大值下限; 上限值经过 clampMax 后不会低于这个值
max_maxdouble否Double.MAX_VALUE有限数值最大值上限
sync_to_bukkitboolean否falsetrue / false要不要把资源同步到 Bukkit (health 必须为 true); 填 false 的资源 (例如 mana) 始终以 PDC 为准
full_on_initboolean否truetrue / false初始化的时候要不要把资源填满
regen_per_seconddouble否0≥ 0每秒自动回复多少; 实际回复按 regen_interval_ticks 分摊
is_healthboolean否falsetrue / false要不要把它标记为生命资源

default_profile 还识别可选的 id (默认 default), priority (默认 1000000), description (默认空) 三个节级键; 发货 config.yml 未写出它们

default_profile.attributes.<attribute_id> ​

字段类型必填默认值取值范围说明
<属性 id>double否0有限数值 (非法回退 0)玩家初始化时给该属性注入的基础值; 没列出来的属性不会得到默认值

内置默认资源:

  • health: 默认最大 20, 同步到 Bukkit, 最小上限 1, 最大上限 2048
  • mana: 默认最大 100, 不同步到 Bukkit, 最小上限 0, 最大上限 99999

简单分: 资源管生命, 法力, 怒气这类会变化的数值, 属性管装备, 宝石, 强化, 技能和伤害计算. 设了 sync_to_bukkit: true 的资源会同步到 Bukkit 的对应表现, 生命值就靠它

yaml
# 新增一个每秒回复 5 点的怒气资源
default_profile:
  resources:
    rage:
      display_name: "怒气"
      default_max: 100.0
      min_max: 0.0
      max_max: 100.0
      sync_to_bukkit: false
      full_on_init: false
      regen_per_second: 5.0

盾牌格挡 ​

shield 决定格挡由原版还是 EA 结算. 详见伤害系统的"盾牌格挡"

yaml
shield:
  mode: vanilla
  require_facing: true
  facing_angle_degrees: 180
字段类型必填默认值取值范围说明
modestring否vanillavanilla / attributevanilla 保留原版 BLOCKING; attribute 把它清零, 改由伤害类型的 block 阶段结算. 填了别的值都按 vanilla 处理
require_facingboolean否truetrue / false只在 attribute 模式生效, 要不要要求伤害来源位于正面. 环境伤害没有来源方向, 所以不算正面格挡
facing_angle_degreesdouble否1800 ~ 180 (超出会被夹到区间内)正面判定的张角, 单位度; 180 表示以视线为中心的半平面

示例: 改为百分比格挡

yaml
shield:
  mode: attribute
  require_facing: true
  facing_angle_degrees: 180
# 再把 default_profile.attributes.block_reduction 调低 (如 40) 即得到 40% 减伤

合成命中反馈 ​

synthetic_hit_feedback 只在兼容模式 (vanilla_event_damage.enabled: false) 下补发击退与受伤音效

yaml
synthetic_hit_feedback:
  knockback: true
  knockback_strength: 0.4
  hurt_sound: true
字段类型必填默认值取值范围说明
knockbackboolean否truetrue / false要不要补发击退
knockback_strengthdouble否0.4≥ 0 (负值按 0)击退强度; 数值越高, 位移越明显
hurt_soundboolean否truetrue / false要不要播放受伤音效

示例: 与自定义击退插件共存时关闭合成击退

yaml
synthetic_hit_feedback:
  knockback: false
  hurt_sound: true

伤害飘字 ​

damage_indicator 管伤害飘字. 用哪种渲染后端由 EmakiCoreLib 的 display.backend 决定: packet 后端只有下方 visible_to 指定的相关玩家能看到; bukkit 后端飘字是真实体, 附近所有玩家都能看到, visible_to 不生效

yaml
damage_indicator:
  enabled: true
  merge_window_ms: 500
  max_per_target_per_second: 4
  visible_to: "involved"
  ignored_causes:
    - FIRE_TICK
    - POISON
    - WITHER
    - DROWNING
    - FREEZE
    - SUFFOCATION
    - STARVATION
  lifetime_ticks: 24
  spawn:
    offset:
      x: 0.0
      y: 2.0
      z: 0.0
    random_offset:
      x: 0.4
      y: 0.15
      z: 0.4
  motion:
    enabled: true
    step_ticks: 2
    speed: 0.30
    gravity: -0.030
    direction:
      mode: "random"
      fixed:
        x: 0.0
        y: 1.0
        z: 0.0
      pitch:
        min: 55.0
        max: 85.0
      yaw:
        min: -180.0
        max: 180.0
    scale:
      pop_from: 0.6
      pop_ticks: 3
      shrink_to: 0.0
      shrink_ticks: 6
  triggers:
    normal:
      enabled: true
    critical:
      enabled: true
    heal:
      enabled: true
    dodge:
      enabled: true
字段类型必填默认值取值范围说明
enabledboolean否truetrue / false要不要启用伤害飘字
merge_window_msinteger否500≥ 0同一个目标在这个时间窗 (毫秒) 内的多次伤害会合并成一个飘字; 0 表示不合并, 窗口内再次命中会重新开始计时
max_per_target_per_secondinteger否4≥ 0同一个目标每秒最多生成几个飘字; 0 表示不限
visible_tostring否involvedinvolved / all只在 packet 后端生效: involved 只有双方能看到, all 附近玩家都能看到; 填了别的值按 all 处理
ignored_causeslist<string>否7 项 (FIRE_TICK, POISON, WITHER, DROWNING, FREEZE, SUFFOCATION, STARVATION)任意 Bukkit DamageCause 名不显示飘字的伤害原因; 空列表会回退成默认的那 7 项
lifetime_ticksinteger否24≥ 1存活与抛物运动的总时长, 单位是游戏刻 (1/20 秒); 到期后由 CoreLib 回收
spawn.offset.x / .y / .zdouble否0.0 / 2.0 / 0.0—相对目标脚部的固定偏移, 单位格
spawn.random_offset.x / .y / .zdouble否0.4 / 0.15 / 0.4—各轴随机散布范围是 ±该值, 单位格; 0 表示这个轴不散布
motion.enabledboolean否truetrue / false要不要启用抛物运动
motion.step_ticksinteger否2≥ 1关键帧间隔 (游戏刻), 同时也是客户端插值时长; 1 最平滑, 值越大包越少, 折线感越强
motion.speeddouble否0.30≥ 0抛出初速度 (格/游戏刻)
motion.gravitydouble否-0.030—竖直加速度 (格/游戏刻²), 负值是下坠, 决定抛物线的弯曲程度
motion.direction.modestring否randomrandom / fixed / away_from_attacker抛出方向模式; 填了别的值按 random 处理
motion.direction.fixed.x / .y / .zdouble否0.0 / 1.0 / 0.0—mode: fixed 时使用的方向向量
motion.direction.pitch.min / .maxdouble否55.0 / 85.0— (min > max 时自动交换)仰角区间 (度), 90 是正上方
motion.direction.yaw.min / .maxdouble否-180.0 / 180.0— (min > max 时自动交换)水平角区间 (度)
motion.scale.pop_fromdouble否0.6≥ 0出场起始缩放, 在前 pop_ticks 内线性放大到 1.0
motion.scale.pop_ticksinteger否3≥ 0出场放大的时长 (游戏刻)
motion.scale.shrink_todouble否0.0≥ 0退场目标缩放, 在最后 shrink_ticks 内从 1.0 线性缩到这个值; 0 表示缩到看不见
motion.scale.shrink_ticksinteger否6≥ 0退场缩小的时长 (游戏刻)
triggers.<normal|critical|heal|dodge>object 或 boolean否各自 enabled: true—四个触发器 (普通命中, 暴击, 治疗, 闪避). 可以只写要改的键 (enabled, lifetime_ticks, spawn.*, motion.*), 没写的键会继承上面的默认值; 也可以直接写布尔值, 那样只设置 enabled. dodge 还需要闪避判定本身被启用; 原版战斗默认不做闪避判定

示例: 暴击飘字更快, 并抑制持续伤害刷屏

yaml
damage_indicator:
  enabled: true
  max_per_target_per_second: 2
  triggers:
    critical:
      enabled: true
      motion:
        speed: 0.42
        gravity: -0.036
        scale:
          pop_from: 0.35
          pop_ticks: 4

原版伤害映射 ​

allowed_damage_causes 决定哪些 Bukkit DamageCause 会进入 Attribute 结算:

yaml
allowed_damage_causes:
  - cause: FALL
    damage_type: physical
    enabled: true
  - cause: LAVA
    damage_type: physical
    enabled: true
字段类型必填默认值取值范围说明
causestring是—Bukkit EntityDamageEvent.DamageCause 名要映射的原版伤害原因; 缺失时这条会被忽略
damage_typestring否default_damage_type—使用的 damage_types/*.yml 伤害类型 ID; 没加载的话 /ea lint 会报出来
damagedouble否省略时用原版事件伤害≥ 0 (负值按 0)进入属性管线前的基础伤害. 留空时直接使用服务端已经算好的原版伤害值, 适合摔落, 爆炸, 燃烧, 溺水这类随高度或状态变化的来源
enabledboolean否truetrue / false这条映射要不要生效; false 时不会参与匹配
context.<key> (或其它任意键)任意否——注入到本次伤害的上下文里, 供阶段表达式和消息模板读取. cause, damage_type, damage, enabled, context 是保留键, 其余键直接当作上下文变量

示例: 让摔落伤害按原版数值走物理管线, 并单独指定岩浆伤害的基础值

yaml
allowed_damage_causes:
  - cause: FALL
    damage_type: physical
    enabled: true          # 省略 damage, 使用原版摔落伤害
  - cause: LAVA
    damage_type: spell
    damage: 8              # 覆盖为固定 8 点基础伤害
    enabled: true

没被映射命中的原版伤害由 vanilla_event_damage 决定, 与 hard_lock_damage 无关: enabled: true 时按 vanilla_event_damage.damage_type 进入属性管线; enabled: false 时只有本表中允许的原因进入 EA, 其余保留原版行为

属性衰减曲线 ​

scaling_curves 为高数值属性配置超阈值折算, 默认为空映射 (不启用):

yaml
scaling_curves:
  physical_attack_cap:
    attribute: "physical_attack"
    threshold: 500
    curve_type: "logarithmic"
    factor: 100
字段类型必填默认值取值范围说明
<规则 id> (小节 key)object否——规则 ID; 省略 attribute 时, key 本身就当作属性 ID
attributestring否小节 key—被衰减的属性 ID; 指向不存在的属性时这条规则不生效
thresholdnumber否0≥ 0 (负值按 0)衰减开始的阈值; 低于或等于这个值时保持原值
curve_typestring否logarithmiclogarithmic / sqrt / piecewise_linear (别名 linear)衰减函数类型; 填了识别不了的值按 logarithmic 处理, 并在配置预检时告警
factornumber否1logarithmic / sqrt: > 0 (≤ 0 按 1); piecewise_linear / linear: ≥ 0衰减系数: 前两者拿它当除数, 后者拿它当保留比例, 0 是合法值 (超出部分全部作废)

完整曲线的含义和调参办法见属性衰减曲线

排查建议 ​

  • 属性不显示: 依次检查属性文件是否加载, Lore 格式是否匹配, 物品装配是否触发刷新
  • 属性不生效: 检查属性 ID 是否与伤害类型, 条件或外部模块一致
  • 环境伤害异常: 检查 vanilla_event_damage 与 allowed_damage_causes (hard_lock_damage 没有运行时的作用, 不用排查)
  • 生命不同步: 先看资源是否设置了 sync_to_bukkit: true. health 资源的天花板取修饰后的 MAX_HEALTH: EA 自己算出的值写入 base, max_health_vanilla, 生命提升药水与第三方插件贴的 modifier 叠加在其上, 三者不再互相冲突. 若上限与预期不符, 开启 resource 调试查看 生命上限解析 与 最大生命修饰器 两行, 逐条定位修饰器来源
  • 外部回血被撤销: health 的当前值以玩家实体血量为准, 因此其他插件或命令直接设置血量后, 不会被下一次同步抹掉. 若仍出现回落, 开启 resource 调试对比 生命自然回复 行的 旧当前值 与 引擎基线值: 两者持续偏离, 说明该资源没有同步到 Bukkit, 或者血量被另一插件在同一个游戏刻内反复改写
  • 数值膨胀: 给核心输出, 防御, 暴击等属性配上 scaling_curves