Minecraft 修改私有变量

问题描述 投票:0回答:1

我正在尝试为 Minecraft 1.12.2 编写一个 Forge mod。我想对主菜单进行修改(某些模组会这样做,所以我知道这是可能的),但我想要更改的内容(其他模组也会这样做)是私有变量。我这样做是通过扩展 GuiMainMenu 来实现的,但是我在使用私有变量时遇到了问题。特别是,我想将

GuiMainMenu.MINECRAFT_TITLE_TEXTURE
(这是一个
private static final
)绑定到纹理管理器,以便我可以像在香草主菜单中一样绘制 Minecraft 标题纹理,并且我想添加启动文本选项(如下所示:
this.splashText = "example_splash";
)。
GuiMainMenu.splashText
private String

到目前为止,人们似乎使用反射来解决此类问题,这就是我尝试过的方法,代码如下:

    private Field splashTextField;
    private static Field minecraftTitleTextureField;

    static {
        initField("MINECRAFT_TITLE_TEXTURES", minecraftTitleTextureField);
    }

    private static void initField(String fieldName, Field destinationField) {
        try {
            // Accessing private variable using reflection
            destinationField = GuiMainMenu.class.getDeclaredField(fieldName);
            destinationField.setAccessible(true);
        } catch (NoSuchFieldException e) {
            e.printStackTrace(); // Handle the exception appropriately
        }
    }

    // Wrapper methods to handle IllegalAccessException
    private static void setFieldValue(Object target, Field field, Object value) {
        try {
            field.set(target, value);
        } catch (IllegalAccessException e) {
            e.printStackTrace(); // Handle the exception appropriately
        }
    }

    private static Object getFieldValue(Object target, Field field) {
        try {
            return field.get(target);
        } catch (IllegalAccessException e) {
            e.printStackTrace(); // Handle the exception appropriately
            return null;
        }
    }

但是当我这样做时,当我尝试对这些变量中的任何一个执行任何操作时,我都会收到 NullPointerExceptions。我做错了什么?

java reflection minecraft-forge private-members
1个回答
0
投票

评论者已经对如何使用反射进行修复给出了很好的解释,但对于后人来说,我发现为 Minecraft Forge Mod 开发执行此操作的常用方法是使用访问变压器,它可以完成所有正确的反射评论者提到,您不需要自己编写反射代码。反射仍然会影响性能,但使用访问转换器可以轻松做到这一点。

这涉及将

accesstransformer.cfg
添加到
src/main/resources/META-INF/
文件夹,并添加 github这些文档这些文档 上指定的行。然后,需要通过添加到minecraft块来在build.gradle文件中启用Access Transformer:

minecraft {
    //// stuff before
    accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
    //// stuff after
}

但是,如果你只这样做,它就会编译,并且当你这样做时它可能会正常运行

./gradlew runClient
,但是当你将 mod .jar 文件复制到 mods 文件夹中时,它将无法工作。这是因为需要告诉 forge modloader 有一个 Access Transformer 文件及其名称,以便它知道在运行时执行适当的反射。这是必要的,因为访问转换是由 forge 完成的,而不是由 mod 本身完成的。构建只需添加到minecraft{}块即可进行,因为这会对构建环境进行必要的更改才能成功构建。这有点像 Linux 中的链接器和
ld

因此,要使其在运行时工作,您需要将访问转换器文件添加到清单中,这应该通过 build.gradle 文件完成,如下所示:

jar {
    manifest {
        attributes([
                "Specification-Title"     : "sometitle",
                "FMLAT": 'accesstransformer.cfg' // The name of the accesstransformer file
        ])
    }
}

FMLAT 代表 Forge ModLoader 访问变压器。

(我对访问变压器也进行反射的看法可能是错误的,但我认为我的理解是正确的)

© www.soinside.com 2019 - 2024. All rights reserved.