Skip to main content
Version: 1.21.4

访问转换器(Access Transformers)

访问转换器(Access Transformers,简称 ATs)允许你提升类、方法和字段的可见性,并修改它们的 final 标志。通过 ATs,模组开发者可以访问和修改那些原本无法访问、且不受自己控制的类成员。

你可以在 NeoForged 的 GitHub 上查看 规范文档

添加访问转换器(Adding ATs)

在你的模组项目中添加访问转换器非常简单,只需在 build.gradle 文件中添加一行配置即可:

访问转换器需要在 build.gradle 中声明。AT 文件可以放在任意位置,只要在编译时被复制到 resources 输出目录即可。

// 在 build.gradle 中:
// 这个代码块同时指定了你的映射(mappings)版本
minecraft {
accessTransformers {
file('src/main/resources/META-INF/accesstransformer.cfg')
}
}

默认情况下,NeoForge 会查找 META-INF/accesstransformer.cfg 文件。如果你在 build.gradle 中指定了其他位置的访问转换器文件,则需要在 neoforge.mods.toml 文件中定义它们的位置:

# 在 neoforge.mods.toml 中:
[[accessTransformers]]
## 文件路径是相对于资源(resources)输出目录的,或者在编译后 JAR 包内的根路径
## 'resources' 目录代表资源输出的根目录
file="META-INF/accesstransformer.cfg"

此外,你也可以指定多个 AT 文件,并且它们会按顺序依次应用。这对于包含多个包的大型模组来说非常有用。

// 在 build.gradle 中:
minecraft {
accessTransformers {
file('src/main/resources/accesstransformer_main.cfg')
file('src/additions/resources/accesstransformer_additions.cfg')
}
}
# 在 neoforge.mods.toml 中
[[accessTransformers]]
file="accesstransformer_main.cfg"

[[accessTransformers]]
file="accesstransformer_additions.cfg"

每次添加或修改访问转换器后,都必须刷新 Gradle 项目,才能使转换生效。

访问转换器规范(The Access Transformer Specification)

注释(Comments)

所有在 # 之后直到行尾的文本都会被视为注释,并且不会被解析。

访问修饰符(Access Modifiers)

访问修饰符用于指定目标成员将被转换为的新可见性。按照可见性从高到低的顺序如下:

  • public - 对包内外的所有类可见
  • protected - 仅对包内类和子类可见
  • default - 仅对包内类可见
  • private - 仅对本类内部可见

你还可以在上述修饰符后附加特殊修饰符 +f-f,分别用于添加或移除 final 修饰符。final 修饰符会阻止子类化、方法重写或字段修改。

danger

指令(Directive)只会修改它们直接引用的方法;任何重写(override)该方法的方法都不会被访问性变换(access-transformed)。建议确保被变换的方法没有未被变换且限制可见性的重写方法,否则 JVM 会抛出错误。

可以安全进行访问性变换的方法包括 private 方法、final 方法(或 final 类中的方法)、以及 static 方法。

目标与指令(Targets and Directives)

类(Classes)

要指定目标为类时:

<访问修饰符> <类的全限定名>

内部类(Inner class)需要将外部类的全限定名与内部类名用 $ 连接。

字段(Fields)

要指定目标为字段时:

<访问修饰符> <类的全限定名> <字段名>

方法(Methods)

指定方法(method)时需要用特殊语法来标明方法参数和返回类型:

<访问修饰符> <类的全限定名> <方法名>(<参数类型>)<返回类型>
类型的指定(Specifying Types)

也称为 "描述符(descriptors)":更多技术细节可参考 Java 虚拟机规范,SE 21,4.3.2 和 4.3.3 节

  • B - byte,有符号字节
  • C - char,UTF-16 编码的 Unicode 字符
  • D - double,双精度浮点数
  • F - float,单精度浮点数
  • I - integer,32 位整数
  • J - long,64 位整数
  • S - short,有符号短整型
  • Z - boolean,布尔值(truefalse
  • [ - 表示一维数组
    • 例如:[[S 表示 short[][]
  • L<class name>; - 引用类型
    • 例如:Ljava/lang/String; 表示 java.lang.String 引用类型(注意用斜杠 / 替代点号 .
  • ( - 表示方法描述符(method descriptor),此处填写参数类型,无参数时留空
    • 例如:<method>(I)Z 表示一个需要一个整数参数并返回布尔值的方法
  • V - 表示方法无返回值,只能用于方法描述符结尾
    • 例如:<method>()V 表示无参数且无返回值的方法

示例(Examples)

# 将 Crypt 中的 ByteArrayToKeyFunction 接口(interface)变为 public
public net.minecraft.util.Crypt$ByteArrayToKeyFunction

# 将 MinecraftServer 中的 'random' 字段变为 protected,并移除 final 修饰符
protected-f net.minecraft.server.MinecraftServer random

# 将 Util 中的 'makeExecutor' 方法变为 public,
# 接收一个 String 参数并返回一个 TracingExecutor
public net.minecraft.Util makeExecutor(Ljava/lang/String;)Lnet/minecraft/TracingExecutor;

# 将 UUIDUtil 中的 'leastMostToIntArray' 方法变为 public,
# 接收两个 long 参数并返回一个 int[]
public net.minecraft.core.UUIDUtil leastMostToIntArray(JJ)[I