@Mixin 注解
重要的注解,写在类名上,用来表示注入到哪个类
@Mixin(TeleportCommand.class)@Shadow 注解
当你mixin一个类的时候,然后要用该类的某个内部字段,或者某个方法签名的时候
// @Invoker("teleportToPos")
@Shadow
private static int teleportToPos(CommandSourceStack p_139026_, Collection<? extends Entity> p_139027_, ServerLevel p_139028_, Coordinates p_139029_, @Nullable Coordinates p_139030_, @Nullable TeleportCommand.LookAt p_139031_) throws CommandSyntaxException {
throw new AssertionError();
}
// @Invoker("teleportToEntity")
@Shadow
private static int teleportToEntity(CommandSourceStack source, Collection<? extends Entity> targets, Entity destination) throws CommandSyntaxException {
throw new AssertionError();
}如果有某些无语的问题,比如私有方法中还调用了注入类的内部接口或者各种奇葩方法,那干脆直接方法全部复制一遍也可以
@Inject注解
该注解是直接注入方法
@Inject(method = "register", at = @At("HEAD"),cancellable = true)method 代表需要注入的方法
at 参数详解
at代表注入位置
HEAD 代表方法头插入
RETURN 代表方法RETURN之前插入
TAIL 在方法的最后一条指令之前注入(在return之前)。
INVOKE 方法调用相关的注入点
@At(value = "INVOKE", target = "目标方法签名")
// 在调用特定方法时注入。
@At(value = "INVOKE",
target = "Lnet/minecraft/world/entity/Entity;getX()D")INVOKE_ASSIGN 在调用方法并将结果赋值给变量时注入。
@At(value = "INVOKE_ASSIGN", target = "目标方法签名")INVOKE_STRING 在调用方法且栈顶有特定字符串常量时注入。
@At(value = "INVOKE_STRING",
target = "目标方法签名",
args = "ldc=要匹配的字符串")FIELD 字段访问相关的注入点
@At(value = "FIELD", target = "字段签名")
//在访问(读取或写入)字段时注入。
@At(value = "FIELD",
target = "Lnet/minecraft/world/entity/Entity;x:D")GETFIELD
@At(value = "GETFIELD", target = "字段签名")
在读取字段值时注入。PUTFIELD
@At(value = "PUTFIELD", target = "字段签名")
在写入字段值时注入。FIELD_GET
@At(value = "FIELD_GET", target = "字段签名")
同GETFIELD。FIELD_SET
@At(value = "FIELD_SET", target = "字段签名")
同PUTFIELD。数组访问相关的注入点
ARRAY@At(value = "ARRAY") 在数组访问时注入。
ARRAY_GET
@At(value = "ARRAY_GET")
在读取数组元素时注入。ARRAY_SET
@At(value = "ARRAY_SET")
在写入数组元素时注入。- 局部变量相关的注入点
STORE
@At(value = "STORE", ordinal = 0)
在存储到局部变量时注入。LOAD
@At(value = "LOAD", ordinal = 0)
在从局部变量加载时注入。JUMP 条件判断相关的注入点
@At(value = "JUMP", opcode = Opcodes.IFNE)
在条件跳转指令处注入。IFNULL
@At(value = "IFNULL")
在ifnull指令处注入。IFNONNULL
@At(value = "IFNONNULL")
在ifnonnull指令处注入。IF_ACMPEQ, IF_ACMPNE
@At(value = "IF_ACMPEQ")
在对象引用比较时注入。IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT等
@At(value = "IF_ICMPEQ")
在整数比较时注入。- 常量相关的注入点
CONSTANT
@At(value = "CONSTANT", args = "doubleValue=0.0")
在加载常量时注入。- 新建对象相关的注入点
NEW
@At(value = "NEW", target = "类签名")
在创建新对象时注入。
@At(value = "NEW",
target = "net/minecraft/world/item/ItemStack")- 异常处理相关的注入点
THROW
@At(value = "THROW")
在抛出异常时注入。- 特殊注入点
INVOKE_SPECIAL
@At(value = "INVOKE_SPECIAL", target = "方法签名")
在调用私有方法或构造方法时注入。INVOKE_VIRTUAL
@At(value = "INVOKE_VIRTUAL", target = "方法签名")
在调用虚方法时注入。INVOKE_STATIC
@At(value = "INVOKE_STATIC", target = "方法签名")
在调用静态方法时注入。INVOKE_INTERFACE
@At(value = "INVOKE_INTERFACE", target = "方法签名")
在调用接口方法时注入。- 字节码指令相关的注入点
INVOKE_DYNAMIC
@At(value = "INVOKE_DYNAMIC")
在invokedynamic指令处注入。INSTANCEOF
@At(value = "INSTANCEOF")
在instanceof检查时注入。常用的组合参数
ordinal参数
指定第几次出现的位置:
@At(value = "INVOKE", target = "...", ordinal = 0)
shift参数
调整注入位置:
Shift.BEFORE: 在目标指令之前
Shift.AFTER: 在目标指令之后
Shift.BY: 偏移指定数量
@At(value = "INVOKE", target = "...", shift = Shift.BEFORE)by参数
与Shift.BY一起使用:
@At(value = "INVOKE", target = "...", shift = Shift.BY, by = 2)cancellable 参数
它控制是否允许取消(跳过)原始方法的执行
@Inject(method = "register", at = @At("HEAD"),cancellable = true)
private static void modifyCommandPermissions(CommandDispatcher<CommandSourceStack> dispatcher, CallbackInfo ci) {
ci.cancel();
}
评论 (0)