Skip to content

自定义数值读取组件

概述

数值读取组件负责从 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数值正则(匹配 10050-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」,就不会再交给其他读取器。

注意事项

  1. 总是使用 CacheManager——避免每次解析都执行正则,显著提升性能
  2. 正则要严格——避免匹配到不相关的文本(比如聊天信息也有类似的数字格式)
  3. 返回 null 而非 0 值结果——返回 null 才能让其他读取器有机会处理
  4. 数值读取组件需要自行识别属性名(不像条件读取器有 key 辅助)

下一步

继续学习 自定义映射读取组件 —— 将整行文本批量映射为多个属性。