使用 Access Transformer

警告

这些文档是为 SpongeAPI 7 编写的,可能已经过时。 如果你觉得你可以帮助更新它们,请提交一个 PR!

由于 Minecraft 的部分代码一开始设计时并没有希望外部代码进行调用,所以说当你希望访问一个非公有(Public)的字段或方法时,事情就变得麻烦了起来。虽然你可能会通过使用反射(Reflection)的方式使用这些字段或方法,但由于 MCP 的存在,你不得不考虑两种不同的名称——用于开发环境的 MCP 名以及用于生产环境的 Searge 名。

作为示例,你可能会使用反射的方式调用 tick() 方法,这一方法在开发环境中的名字为 tick ,而在生产环境中的名字为 func_71217_p 。对于插件的重混淆(Reobfuscation)操作只会修改针对方法或字段的直接引用,而通过反射引用的字符串名称不会发生变化。

ForgeGradle 提供了一种名为 Access Transformer 的解决方案。该方案会将开发者指定的方法或字段的访问级设置为公有,这样你就可以直接引用它们,而不是使用诸如反射的间接方式。虽然这主要应用于 Minecraft 的源代码,但你也可以将其应用到一些第三方项目的类上。一旦你将 Access Transformer 的配置在 JAR 的 Manifest 文件中指明,SpongeVanilla 和 Forge 就会在生产环境中自动应用它们。

部署工作环境

ForgeGradle 会自动在你的资源文件夹(Resource Folder)中寻找以 _at.cfg 结尾的配置文件。如果你想要在运行时使用 Access Transformer,你需要在你的资源文件夹下新建一个名为 META-INF 的文件夹,并将你的配置文件,如 META-INF/myplugin_at.cfg 放进去。

有三种不同类型的 AT,分别用于对类、字段、和方法作出修改。Access Transformer配置中的每一行由两个(对于类而言)或三个(对于方法和字段而言)部分,部分与部分之间使用空格隔开。

  • 用于修改方法或字段的访问级标识符,如 publicprotected 等。如果你还想同时去除 final 修饰符,你可以在其后添加 -f 标记,如 public-f

  • 一个类的全名,如 net.minecraft.server.MinecraftServer

  • 字段或方法的 Searge 名(方法需要添加相应的方法签名),如 field_54654_afunc_4444_a()V

小技巧

你可以通过添加 # 前缀以添加注释。一个良好的习惯是为每行 AT 都写相应的注释,这样每一个字段或方法的引用就一目了然。

下面是几行 Access Transformer 的示例:

public-f net.minecraft.server.MinecraftServer field_71308_o # anvilFile
public net.minecraft.server.MinecraftServer func_71260_j()V # stopServer
public-f net.minecraft.item.ItemStack

如果你想要在你的开发环境中应用 Access Transformer,你需要重新运行一遍名为 setupDecompWorkspace 的 Gradle 任务,同时更新你的 Gradle 项目。

gradle setupDecompWorkspace

小技巧

你可以使用 MCP Bot 以快速地获取用于字段和方法的 Access Transformer 配置。MCP Bot 在 MCP 和 Sponge 的 IRC 频道中都有提供。你也可以在 MCP 的 Discord 服务器的 #bot-spam 频道找到 MCP Bot。当使用诸如 !gm <mcp method name>!gf <mcp field name> 的方式查找字段和方法对应的 AT 配置后,你只需要直接地把输出复制进你的 AT 配置就可以了。

备注

AT 并不支持使字段或方法的访问级变严格(如 public -> private )的行为。

生产环境

如果你想要把 AT 应用于生产环境,你需要在你的插件 JAR Manifest 中添加 FMLAT 选项,并注明你的位于 META-INF 目录下的 Access Transformer 配置文件名。

jar {
    manifest.attributes('FMLAT': 'myplugin_at.cfg')
}