本篇教程由作者设定使用 CC BY-NC 协议。

注解

注解的类注解

注解类要求生命周期为运行时,即要有@Retention(RetentionPolicy.RUNTIME);

一般其使用范围为仅用于字段,即要有@Target(ElementType.FIELD);

为了确定目标字段的类型,Anno添加了一个新的注解@TargetType(Class<?>[] value)用于注解类,

例如:注册燃料应该限制类型为Item,那么注册燃料的@TargetType应该为@TargetType({Item.class})。如果要求字段可重复标注(例如@Lang),可以自行百度@Repeatable注解。

注解的属性

自由发挥,属性需要具体需要具体分析,请保证你会Java中创建新的注解。

示例(燃料注解)

@TargetType(Item.class)
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Burnable {
    int value();
}

解析器

解析器用于处理字段实例与注解,不同情况下具体实现差异较大。


我们这里以燃料注解为例子。

示例

public class FuelResolver implements Resolver<Burnable> {
    @Override
    public <T> void process(Target<T> target, Class<?> registration) {
        if (target.object() instanceof Item item) {
            int time = target.field().getAnnotation(Burnable.class).value();
            FuelRegistry.INSTANCE.add(item, time);
        }
    }

    @Override
    public Class<Burnable> annoClass() {
        return Burnable.class;
    }

    @Override
    public String name() {
        return "Fuel";
    }
}

说明

解析器的实现也很简单,Target<T>为一个记录类,它包装了实例与字段。

process(arg...)为具体的处理流程,这里我们新增燃料的流程如下:

首先判断实例的类型,转换后直接用Fabric API的新增燃料注册。

annoClass()仅仅只需要返回注解的类。

在Minecraft-1.21.1及其后续版本,我们还需要实现name(),该名称不应与其他解析器相同。

注册

注解无需注册,解析器应该在模组主类的onInitialize()位于顶部使用AnnoResolvers.regiter(arg...)注册。

示例

public class Anno implements ModInitializer {
    public static final String MOD_ID = "anno";

    @Override
    public void onInitialize() {
        AnnoResolvers.register(id("fuel"), new FuelResolver());
        
        AnnoResolvers.resolve(AnnoRegistration.class);
    }

    public static Identifier id(String path) {
        return Identifier.of(MOD_ID, path);
    }
}

注意事项

  • 如果需要DataGeneration相关解析器可以参考Anno官方实现

  • 相同id的解析器,后注册的会覆盖先注册的。