访问转换器
访问转换器(Access Transformer,简称 AT)可以扩大类、方法和字段的可见范围,并修改它们的 final 标记。开发者由此能够访问和修改其他代码中原本不可访问的成员。
完整规范文档可在 NeoForged 的 GitHub 仓库中查看。
添加 AT
在 Mod 项目中使用访问转换器,需要先在 build.gradle 中声明。AT 文件可以放在任意位置,只要编译时会被复制到 resources 输出目录即可。
// In build.gradle:
// This block is where your mappings version is also specified
minecraft {
accessTransformers {
file('src/main/resources/META-INF/accesstransformer.cfg')
}
}
NeoForge 默认会查找 META-INF/accesstransformer.cfg。如果在 build.gradle 中指定了其他位置,还需要在 neoforge.mods.toml 中声明对应路径:
# In neoforge.mods.toml:
[[accessTransformers]]
## The file is relative to the output directory of the resources, or the root path inside the jar when compiled
## The 'resources' directory represents the root output directory of the resources
file="META-INF/accesstransformer.cfg"
也可以指定多个 AT 文件,它们会按顺序应用。这对包含多个包的大型 Mod 很有用。
// In build.gradle:
minecraft {
accessTransformers {
file('src/main/resources/accesstransformer_main.cfg')
file('src/additions/resources/accesstransformer_additions.cfg')
}
}
# In neoforge.mods.toml
[[accessTransformers]]
file="accesstransformer_main.cfg"
[[accessTransformers]]
file="accesstransformer_additions.cfg"
添加或修改访问转换器后,必须刷新 Gradle 项目,转换才会生效。
访问转换器规范
注释
从 # 到行末的内容均视为注释,不会参与解析。
访问修饰符
访问修饰符决定目标成员转换后的可见范围。按可见范围从大到小排列:
public:包内、包外的所有类均可访问。protected:同包中的类和子类可访问。default:仅同包中的类可访问。private:仅所属类内部可访问。
还可以在上述修饰符后添加 +f 或 -f,分别用于添加或移除 final。final 可以阻止类被继承、方法被重写或字段被修改,具体取决于它修饰的目标。
重要警告 指令只会修改直接指定的方法,不会同时转换重写该方法的其他方法。应确保转换后的方法没有未转换、且访问范围更小的重写方法,否则 JVM 会抛出错误。
通常可以安全转换
final方法、final类中的方法,以及static方法。private方法一般也安全,但可能导致子类型中原本无关的方法意外构成重写,因此还需要手动检查。
目标与指令
类
指定类的格式:
<access modifier> <fully qualified class name>
内部类使用外部类的完全限定名、$ 分隔符和内部类名称表示。
字段
指定字段的格式:
<access modifier> <fully qualified class name> <field name>
方法
指定方法时,需要使用特殊语法表示参数类型和返回类型:
<access modifier> <fully qualified class name> <method name>(<parameter types>)<return type>
指定类型
这套表示法也称为“描述符”。技术细节见 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,值为true或false。[:数组的一维。- 例如,
[[S表示short[][]。
- 例如,
L<class name>;:引用类型。- 例如,
Ljava/lang/String;表示java.lang.String,注意使用斜杠而不是句点。
- 例如,
(:方法描述符的参数部分;括号内填写参数类型,没有参数则留空。- 例如,
<method>(I)Z表示接受一个整数参数并返回布尔值的方法。
- 例如,
V:方法没有返回值,只能放在方法描述符末尾。- 例如,
<method>()V表示无参数、无返回值的方法。
- 例如,
示例
# Makes public the ByteArrayToKeyFunction interface in Crypt
public net.minecraft.util.Crypt$ByteArrayToKeyFunction
# Makes protected and removes the final modifier from 'random' in MinecraftServer
protected-f net.minecraft.server.MinecraftServer random
# Makes public the 'makeExecutor' method in Util,
# accepting a String and returns an ExecutorService
public net.minecraft.Util makeExecutor(Ljava/lang/String;)Ljava/util/concurrent/ExecutorService;
# Makes public the 'leastMostToIntArray' method in UUIDUtil,
# accepting two longs and returning an int[]
public net.minecraft.core.UUIDUtil leastMostToIntArray(JJ)[I
来源: NeoForged/Documentation(1.21.1)。中文翻译依据提交
4a680cdd4d15。