主题
这页帮你弄明白三件事:
- 装备属性是怎么被读进系统的
- 为什么有些 Lore 看起来像属性,但系统不认
source为什么是最重要的排查入口
一、属性读取的工作流程
HNAttribute 不是“看到数字就自动加属性”的插件。
它真正做的事情是:
- 先识别这段文本 / 标签是不是某个已注册属性
- 再根据读取规则把它转成修饰符
- 再按
source写入玩家或实体的属性系统 - 最后才进入战斗、Buff、显示、原版属性同步等后续流程
所以你排查问题时,不应该只问:
- “这段 Lore 看起来对不对?”
而应该问:
- “它有没有匹配到已注册属性?”
- “它用了哪种 read-pattern?”
- “它最后是以哪个 source 进入系统的?”
二、先跟着做一个最小读取实验
先拿一件测试装备,写下面几行 Lore:
text
攻击力: 120
攻击速度: 15%
最大生命值: 60然后装备到身上,执行:
text
/hnattr inspect
/hnattr lookup
/hnattr source
/hnattr trace attack_damage你应该分别看到什么
/hnattr inspect
看的是“这件物品到底被读到了什么”。
你重点检查:
- Lore 原文是不是这三行
- 解析结果里有没有
attack_damage - 百分比那行有没有被识别出来
- 当前物品是否已经带上标准 identity
attributeKind是不是符合预期- 如果这是模板化 token / material,
templateMatched / templateKey / templateCategory是否正确
/hnattr lookup
看的是“这些属性最终有没有真的加到你身上”。
/hnattr source
看的是“这些值来自哪一个来源”。
你大概率会看到:
text
equipment:mainhand/hnattr trace attack_damage
看的是“这个属性到底由哪些修饰符组成”。
如果这四个命令能对上,你就已经真正跑通了“读取层”。
如果你启用了属性映射 / 派生属性
现在 source / trace 还会把派生来源一起展示出来。
例如你定义了:
yml
strength:
priority: 100
mapping:
targets:
attack_damage:
operation: ADD
formula: "total * 0.5"那么当 strength 生效后,/hnattr trace attack_damage 里除了装备、Buff 这类显式来源,还会看到类似:
text
mapping:strength而且现在 trace 会继续把它往上展开,告诉你:
- 这是从哪个源属性映射过来的
- 这个源属性的
priority是多少 - 当前命中的公式模式与脚本内容
- 上游属性本身又是被哪些来源撑起来的
这表示:
strength已经先按自己的来源算出最终值- 然后它把结果继续派生到了
attack_damage - 这个派生值和普通来源一样,真的进入了最终结算链路
所以如果你发现某个属性"看起来没人加,但最终值却变了",第一时间就该想到有没有映射来源。
如果你需要一份能直接复制的完整示例,可以直接翻插件默认自带的:attributes/mapping-demo.yml。
如果你想直接使用一套已经启用的经典主属性模板,也可以看:attributes/rpg-derived.yml。
当前这套模板里,vitality -> health_regen 已经使用表达式分段公式实现,不依赖额外的 Groovy 映射脚本,默认启用时更稳。
新版配置格式: 已简化 mapping 结构,直接在 mapping 下定义目标属性,公式自动推断类型(单行=expression,多行=groovy)。
三、Lore 是怎么匹配成功的
Lore 能不能生效,不取决于“像不像属性”,而取决于两部分同时成立:
- 这个名字是否出现在属性定义的
names - 这个属性使用的
read-pattern是否能匹配当前文本
也就是说,Lore 识别本质上是:
属性别名 + 读取规则
四、默认属性别名从哪里来
当前默认属性主要在:
text
attributes/base.yml
attributes/combat.yml
attributes/element.yml例如 attributes/base.yml 里就有:
attack_damagemax_healthhealth_regen
像 attack_damage 默认别名就会包括:
攻击力物理伤害
所以:
text
攻击力: 120是能被识别的。
但如果你写成:
text
攻击: 120而你又没有把“攻击”加进 names,那系统不会自动猜它等于 attack_damage。
五、默认 read-pattern 是怎么工作的
当前默认 read-patterns.yml 至少有两种模式:
default
适合单值:
text
攻击力: 100
攻击速度:15%range
适合区间:
text
火焰伤害: 10-20当前默认配置里,大部分属性用的是:
yml
read-pattern: default新手最容易忽略的一点
下面这两行虽然都像属性,但意义不同:
text
攻击力: 100
攻击速度: 15%因为带 % 的值,在系统里通常会被理解成百分比类修饰,而不是普通加法值。
也就是说,15 和 15% 不只是显示差异,运算语义也不同。
六、区间值什么时候适合用
如果你想让一件装备每次刷新时在范围内随机取值,就可以考虑 range。
例如:
text
火焰伤害: 10-20但要注意:
- 不是所有属性默认都在用
range - 你要看这个属性自己的
read-pattern
如果某个属性还是:
yml
read-pattern: default那你写区间,系统也不会自动按区间读。
七、条件系统是怎么挂在 Lore 上的
当前版本支持在属性行后面带条件。
例如:
text
攻击力: 100/Lv.10,权限: vip意思是:
- 主属性还是
攻击力: 100 - 但只有满足等级和权限条件时,这条属性才生效
怎么理解最简单
可以把它理解成:
- 先匹配属性
- 再检查条件
- 条件不满足,这整行就被忽略
排查这种问题时最稳的方法
如果你怀疑“为什么我这件装备看起来对,但加不上去”,优先查:
- Lore 有没有命中属性名
- 条件是不是不满足
这也是为什么:
text
/hnattr inspect一定要优先用。
八、为什么有时整件 Lore 都被跳过了
当前 config.yml 里有一个很关键的开关:
yml
attribute-read:
lore:
skip-contains: []它的行为不是“跳过某一行”,而是:
只要任意 Lore 行包含命中词,整件装备的 Lore 读取都跳过。
所以如果你把这些词放进去:
绑定不可升级活动道具
而你的装备 Lore 里刚好又有这些文本,那整件装备的 Lore 属性都会失效。
这是很多“看起来完全没问题,但系统一条都没读到”的根本原因。
九、PDC / NBT 读取是怎么工作的
除了 Lore,当前系统还支持:
- PDC
- 原始 NBT / SNBT
默认读取 key 是:
text
attribute_tag两种 key 写法
1)只写 key
text
attribute_tag表示:
- 任意 namespace 下,只要 key 叫
attribute_tag都尝试读
2)完整 namespace:key
text
custom:attribute_tag表示:
- 只精确匹配这个 key
为什么这很重要
很多“我明明打了 PDC,但系统没读到”的问题,本质上是:
- 你实际写入的 key 不叫这个名字
- 或者 namespace 不一致
十、PDC / NBT 里可以放什么结构
当前实现支持的思路不只一种。
例如你可以理解成它能处理类似:
1)字符串
text
attribute_tag: "攻击力: 100"2)对象
text
attribute_tag: {attack_damage: 100}3)列表
text
attribute_tag: ["攻击力: 100", "火焰伤害: 20"]所以它不只是会读单一纯文本,还能读更结构化的标签内容。
十一、source 为什么这么重要
这是这一页最关键的概念。
HNAttribute 里所有修饰符最终都会按 source 分组管理。
对于装备来说,默认通常会看到:
equipment:mainhandequipment:offhandequipment:helmetequipment:chestplateequipment:leggingsequipment:boots
对于 Buff,你会看到:
buff:力量提升buff:钢铁护体
对于程序注入来源,你可能会看到:
custom:quest-rewardcustom:artifact-bonus
source 的价值是什么
它至少有三个作用:
- 知道“值从哪来”
- 在换装或移除时精确删除旧来源
- 让
/hnattr source与/hnattr trace能稳定排查
所以你可以把 source 理解成:
这个属性系统里真正的来源身份证。
十二、为什么 Buff 也属于“来源”问题
很多人会把 Buff 当成另一个完全独立的系统。
但在 HNAttribute 里,Buff 最终还是会被编译成修饰符,然后以:
text
buff:<key>这样的来源进入系统。
这就是为什么当你排查 Buff 时,不应该只看:
text
/hnattr buffs还应该配合:
text
/hnattr source
/hnattr trace <属性ID>一起看。
十三、自动刷新是怎么发生的
当前玩家常见换装行为都会触发自动刷新,例如:
- 切换主手
- 主副手交换
- 点击背包
- 拖拽背包
- 关闭背包
- 丢弃物品
- 捡起物品
- 玩家加入服务器
刷新时,插件会:
- 先移除旧的槽位来源
- 再读取新的物品结果
- 再把新修饰符按对应 source 写回系统
所以它不是“直接覆盖全部值”,而是按来源做精确替换。
十四、最推荐的读取排查路线
情况 1:Lore 没生效
text
/hnattr inspect
/hnattr source
/hnattr trace <属性ID>情况 2:PDC / NBT 没生效
text
/hnattr inspect重点看:
- PDC Keys
- Raw NBT
- 解析结果
情况 3:Buff 看起来挂上了,但属性不对
text
/hnattr buffs
/hnattr source
/hnattr trace <属性ID>十五、这一页最该记住的重点
- Lore 能否生效,取决于 属性别名 + read-pattern + 条件。
- PDC / NBT 与 Lore 可以同时生效,不是二选一。
source不是装饰文本,而是装备、Buff、外部注入统一管理的核心标识。- 读取问题最稳的起手式永远是:
text
/hnattr inspect