Skip to content

使用枚举类管理属性

为什么需要枚举?

当你的插件有几十个属性时,管理它们的 ID、名称、优先级、战斗力会变得很麻烦。属性 ID 散落在各个文件中,改一个名字可能要改好几个地方。

解决方法:用一个枚举类统一管理所有属性的配置,然后所有脚本都引用这个枚举。

插件的系统属性就是这么做的——scripts/libs/ 下有一个 AttributeName.groovy 枚举类。

AttributeName 枚举

Groovy
package scripts.libs

import groovy.transform.CompileStatic

@CompileStatic
enum AttributeName {

    // ———— 枚举条目:id, name, priority, power, max ————
    HIT_CHANCE("HIT_CHANCE", "命中几率", 1, 1.0D, -1),
    PHYSICAL_ATTACK("PHYSICAL_ATTACK", "物理攻击", 1, 1.0D, -1),
    PHYSICAL_ARMOR("PHYSICAL_ARMOR", "物理护甲", 1, 0.0D, -1),
    HEALTH("HEALTH", "生命值", 1, 1.0D, -1),
    SPEED("SPEED", "移速加成", 1, 0.0D, -1),
    // ... 更多属性

    // ———— 成员变量 ————
    final String id
    final String name
    final int priority
    final double power
    final double max

    // ———— 构造函数 ————
    AttributeName(String id, String name, int priority, double power, double max) {
        this.id = id
        this.name = name
        this.priority = priority
        this.power = power
        this.max = max
    }
}

在属性脚本中使用

有了枚举后,属性脚本可以这样写:

Groovy
class HitChance extends GroovyAttribute {

    HitChance() {
        // 使用枚举,一行搞定
        super(AttributeTypes.ATTACK_AND_DEFENSE, AttributeName.HIT_CHANCE)

        // 注册子属性也使用枚举
        Utils.registerDefaultAttribute(AttributeName.DOGE_CHANCE)
    }

    @Override
    boolean onAttackAndDefense(LivingEntity attacker, LivingEntity entity, AttackAndDefenseHandler handler) {
        // 通过枚举获取属性名称
        double v = handler.getRandomValue(attacker, AttributeName.HIT_CHANCE.name)
        // ...
    }
}

好处:

  1. 属性名拼写错误会被编译器检查出来(编译时错误,而不是运行时才发现)
  2. 修改属性名只需改枚举中的一处
  3. IDE 可以自动补全 AttributeName. 后面的内容
  4. 优先级排序一目了然

注意事项

  1. 枚举只是一种推荐的管理方式,不是必须的。你完全可以不用枚举,直接在构造函数里写字符串
  2. 枚举文件可以放在 scripts/libs/ 下的任意位置
  3. JavaScript 无法使用 Groovy 枚举——JS 脚本只能直接用字符串
  4. config.ymlgroovy load sort 中,libs 必须在 attributes 之前加载(默认配置已经这样做了)

不使用枚举的对比

Groovy
// 不使用枚举——属性名散落在各处,容易拼错
super(AttributeTypes.ATTACK_AND_DEFENSE, "物理攻击", "物理攻击", 1, 1.0D, -1.0D)
// ... 另一个文件
handler.getRandomValue(entity, "物理攻击")  // 字符串拼写错误要到运行时才发现!
handler.getRandomValue(entity, "物理功击")  // 拼错了!但编译器不报错

// 使用枚举——编译器帮你检查
super(AttributeTypes.ATTACK_AND_DEFENSE, AttributeName.PHYSICAL_ATTACK)
handler.getRandomValue(entity, AttributeName.PHYSICAL_ATTACK.name)
// 如果写错 AttributeName.xxx,编译时就会报错