Table of Contents

Mixin注入

介绍

注入(Injects)允许你在已存在的模组中的特定位置放置自定义的代码。关于工作实例可参考本页底部的实例段落。注入的标准如下:

@Inject(method = "方法名称或签名", at = @At("注入点引用"))
private void injectMethod(方法参数, CallbackInfo info) {
 
}

注入点引用 定义了注入目标方法的方法主体的哪个代码。下表描述了几个选项:

名称 描述
HEAD 方法顶部
RETURN 返回语句之前
INVOKE 在方法调用
TAIL 最终的返回语句前

注入点引用语句或成员的情况下,目标值设置在 @At 中。目标值使用 JVM 字节码描述符指定。

Oracle 定义了如下 域描述符

描述符 原名 描述
B byte 带符号的字节
C char Basic Multilingual Plane 中的 Unicode 字符代码点,使用 UTF-16 编码
D double 双精度浮点值
F float 单精度浮点值
I int 正数
J long 长整数
L类名称; reference 类名称的实例
S short 带符号的短整型
Z boolean truefalse
[ reference 单数组维度

方法描述符包括方法名称,接着一系列包含输入类型的括号,以及输出类型。Java 中定义的像 Object m(int i, double[] d, Thread t) 这样的方法会有 m(I[DLjava/lang/Thread;)Ljava/lang/Object; 这样的方法描述符。

在这个返回类型为 void 的例子中,你需要使用 V(空描述符)作为,例如,void foo(String bar) 就会是 foo(Ljava/lang/String;)V

泛型将会移除,因为泛型在运行的时候不存在,因为像 Pair<Integer, ? extends Task<? super VillagerEntity>‍> 这样的就会变成 Lcom/mojang/datafixers/util/Pair

@Inject 方法总是返回 void 类。方法名称不重要,最好用这次注入所做的事情来命名。方法头中,最先是目标方法的变量,随后是 CallbackInfo 对象。如果目标方法有一个返回类型(T),则使用 CallbackInfoReturnable<T> 而不是 CallbackInfo

从注入中返回和取消

如需在方法中提前取消或者返回,使用 CallbackInfo#cancel 或者 CallbackInfoReturnable<T>#setReturnValue(T)。注意在调用 selReturnValue 之后不需要 cancel。在这两个实例中,注入注解中的 cancellable 需要设为 true:

@Inject(method = "...", at = @At("..."), cancellable = true)

向构造器中注入

如需向构造器中注入,方法目标使用 <init>()V,其中 () 包含构造器变量描述符。向构造器中注入时,@At 必须是 TAIL 或者 RETURN,其他格式的注入均不支持。注意有一些类有名为 init 的方法,与 <init> 不同,不要弄混!

如需向静态构造器中注入,方法名称使用 <clinit>

实例

以下示例会把一个 print 语句注入到 TitleScreen#init 的顶部(注意:方法 init 是普通的方法,不是构造器)。

@Mixin(TitleScreen.class)
public class ExampleMixin {
	@Inject(at = @At("HEAD"), method = "init()V")
	private void init(CallbackInfo info) {
		System.out.println("这一行是示例模组mixin输出的!");
	}
}

关于此实例的更多信息,可以在 Fabric Example Mod 仓库中查看其用途。