自定义数值读取组件
概述
数值读取组件负责从 Lore 文本中提取属性值。例如,系统自带的 NumberValueReader 可以解析:
物理攻击 +100→ 属性「物理攻击」值 100生命值 50-100→ 属性「生命值」范围值 50~100暴击率 10(%)→ 属性「暴击率」百分比值 10%
如果你需要的格式与系统组件不兼容,就需要自定义数值读取组件。
基础结构
Groovy
package scripts.reads
import cn.org.bukkit.craneattribute.api.attribute.data.AttributeData
import cn.org.bukkit.craneattribute.api.attribute.source.AttributeSource
import cn.org.bukkit.craneattribute.api.read.ReadableLine
import cn.org.bukkit.craneattribute.api.utils.StringUtilsKt
import cn.org.bukkit.craneattribute.core.manager.CacheManager
import cn.org.bukkit.craneattribute.core.read.data.ReadValueResult
import groovy.transform.CompileStatic
import scripts.libs.GroovyValueReader
@CompileStatic
class YourValueReader extends GroovyValueReader {
List<String> readFormat = Arrays.asList("{key}:\\s*@value")
YourValueReader() {
super("your_value", 10) // name, priority
}
@Override
ReadValueResult read(ReadableLine readableLine, AttributeData data, AttributeSource attributeSource) {
// 解析逻辑
}
}构造函数参数
Groovy
GroovyValueReader(String name, int priority)| 参数 | 说明 |
|---|---|
name | 读取器名称,会作为 read.yml 中的配置键 |
priority | 优先级,越小越先执行 |
注意:与 GroovyConditionReader 不同,GroovyValueReader 没有 key 参数。数值读取器需要自行判断「这一行包含哪个属性」。
完整示例
实现一个读取器,解析格式为 属性名: 100(用英文冒号分隔):
Groovy
package scripts.reads
import cn.org.bukkit.craneattribute.api.attribute.data.AttributeData
import cn.org.bukkit.craneattribute.api.attribute.source.AttributeSource
import cn.org.bukkit.craneattribute.api.read.ReadableLine
import cn.org.bukkit.craneattribute.api.utils.StringUtilsKt
import cn.org.bukkit.craneattribute.core.manager.CacheManager
import cn.org.bukkit.craneattribute.core.read.data.ReadValueResult
import groovy.transform.CompileStatic
import scripts.libs.GroovyValueReader
@CompileStatic
class ColonValueReader extends GroovyValueReader {
// 匹配: 属性名: 100 或 属性名: 50-100 格式
List<String> readFormat = Arrays.asList("(.*?):\\s*@value")
ColonValueReader() {
super("colon_value", 10)
}
@Override
ReadValueResult read(ReadableLine readableLine, AttributeData data, AttributeSource attributeSource) {
// 使用缓存获取正则解析结果
List<String> list = CacheManager.INSTANCE.getStringList(readableLine) {
extractValues(readableLine, readFormat, "(.*?)") // 自定义组捕获属性名
}
if (list == null || list.isEmpty()) return null
// list[0] = 属性名(正则第一个捕获组)
// list[1] = 属性值(@value 匹配的内容)
String attrName = list.get(0)
double[] numbers = StringUtilsKt.toDoubleArray(list.get(1))
// 构造返回结果
return new ReadValueResult(
attrName, // 属性ID(这里直接用属性名,也可做映射)
numbers[0], // 最小值
numbers[1], // 最大值
0.0D, // 百分比最小值(无百分比则填0)
0.0D, // 百分比最大值
false // 是否为百分比属性
)
}
}ReadValueResult 参数详解
Groovy
new ReadValueResult(
String attributeId, // 属性ID,对应该属性的唯一标识
double minValue, // 最小值
double maxValue, // 最大值(与最小值相等则为固定值)
double percentMinValue, // 百分比最小值(无百分比填 0.0D)
double percentMaxValue, // 百分比最大值
boolean isPercent // 是否为纯百分比属性
)关于百分比属性:
- 基本值 + 百分比值:Lore
物理攻击 10-20(10-20)→ 基本值 10~20,百分比加成 10~20。基本值和百分比值独立计算 - 纯百分比属性:
暴击率 10(%)→isPercent = true,该属性的值会被以百分比方式累加
自定义正则提取
extractValues 的第三个参数允许你自定义属性名的捕获方式:
Groovy
// 使用 @key 捕获属性名 —— 需要配合正则中的捕获组使用
extractValues(readableLine, readFormat, "(.*?)")
// 如果你不需要捕获属性名(比如属性名固定)
extractValues(readableLine, readFormat)
// @value 会使用默认的数值正则readFormat 中的正则替换规则:
| 标记 | 替换为 |
|---|---|
@value | 数值正则(匹配 100、50-100、-10-10 等) |
| 自定义(第三个参数) | 捕获组正则,用于提取属性名 |
另一个示例:固定前缀格式
假设你的 Lore 格式是 ⊙ 属性名 · 值:
Groovy
// 匹配 "⊙ 物理攻击 · 100" 格式
List<String> readFormat = Arrays.asList("⊙\\s*(.*?)\\s*·\\s*@value")
// 自定义捕获组提取属性名
extractValues(readableLine, readFormat, "(.*?)")返回值说明
| 返回值 | 含义 |
|---|---|
ReadValueResult | 解析成功,包含属性 ID 和数值 |
null | 当前行不匹配,交给下一个组件 |
返回 null 是关键——它告诉插件「这行我不认识,让下一个读取器试试」。如果你返回了一个空的 ReadValueResult(数值为 0),插件会认为「这一行我处理了,但是值是 0」,就不会再交给其他读取器。
注意事项
- 总是使用
CacheManager——避免每次解析都执行正则,显著提升性能 - 正则要严格——避免匹配到不相关的文本(比如聊天信息也有类似的数字格式)
- 返回
null而非 0 值结果——返回null才能让其他读取器有机会处理 - 数值读取组件需要自行识别属性名(不像条件读取器有
key辅助)
下一步
继续学习 自定义映射读取组件 —— 将整行文本批量映射为多个属性。
