Minecraft Forge - 在显式调用构造函数时无法引用实例字段

Minecraft Forge - Cannot refer to an instance field while explicitly invoking a constructor

对于我的 Minecraft mod 我写了一个自定义按钮 class 这样当按钮被按下时,它会向服务器发送一个数据包,以更新功能。该按钮还应该更改纹理,以便与 capability 中设置的“样式”具有相同 id 的按钮为红色,而其他按钮为灰色。

但是,我遇到的一个问题是,在具有正确 ID 的按钮 之后的下一个按钮 是实际变为红色的按钮(例如如果 ID 为 0 的按钮是活动 ID,则 ID 为 1 的按钮变为红色)。

这是我的按钮 class:

package lk1905.gielinorcraft.client.gui.widget;
import lk1905.gielinorcraft.Gielinorcraft;
import lk1905.gielinorcraft.capability.attackstyle.AttackStyleCapability;
import lk1905.gielinorcraft.capability.attackstyle.IAttackStyle;
import lk1905.gielinorcraft.network.AttackStyleClientPacket;
import lk1905.gielinorcraft.network.PacketHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.widget.button.ImageButton;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.ResourceLocation;

public class AttackStyleButton extends ImageButton{

    
    private PlayerEntity player =  Minecraft.getInstance().player;
    private IAttackStyle styleCap = player.getCapability(AttackStyleCapability.STYLE_CAP).orElse(null);
    private static int yTex = 0;
    
    public AttackStyleButton(int xIn, int yIn, int widthIn, int heightIn, int xTexStartIn, int yTexStartIn,
            int yDiffTextIn, ResourceLocation resourceLocationIn, IPressable onPressIn) {
        super(xIn, yIn, widthIn, heightIn, xTexStartIn, yTexStartIn, yDiffTextIn, resourceLocationIn, onPressIn);
    }
    
    public AttackStyleButton(int xIn, int yIn, int slotId) {    
        this(xIn, yIn, 56, 20, 137, yTex, 0 , new ResourceLocation(Gielinorcraft.MODID, "textures/gui/combat.png"), (button) -> {
            PacketHandler.sendToServer(new AttackStyleClientPacket(slotId));
        });
    
        if(styleCap.getActiveStyleId() == slotId) {
            yTex = 23;
        }else {
            yTex = 0;
        }
    }
    
}

在此之前,我去 Minecraft forge 网站询问问题是什么,他们声称变量“yTex”不应该是静态的(他们实际上不会说为什么,只是“请学习static 是什么意思”,尽管我找不到足够相似的例子来理解原因。

问题是,我首先将其设为静态的原因是因为 eclipse 给我错误“在显式调用构造函数时无法引用实例字段 yTex”,位于第二个构造函数中,并告诉我将其设为静态。

据我了解,错误是因为yTex是实例化的,在调用构造函数之前它没有值,所以构造函数无法继续。但是我不确定如何重写 class 以便它做同样的事情。我希望在此 class 中设置 yTex 的值,并由 if 语句决定其值。

那么我该如何重写这个 class 以便它执行我已经告诉它要做的事情,但 yTex 不是静态的?

如果你想添加逻辑来计算要传递给 superclass 的构造函数的值,你不能使用来自调用 class 的任何实例变量或方法,因为没有关于调用 class 在调用 superclass 的构造函数时存在。

静态方法可用于运行代码来计算要作为参数传递给超级class构造函数的值。上面提到的相同规则适用于此静态方法中的代码。以下是您如何使用此技术来计算要传递给 superclass 的构造函数的值,以代替计算的 yTex 值:

package lk1905.gielinorcraft.client.gui.widget;

import lk1905.gielinorcraft.Gielinorcraft;
import lk1905.gielinorcraft.capability.attackstyle.AttackStyleCapability;
import lk1905.gielinorcraft.capability.attackstyle.IAttackStyle;
import lk1905.gielinorcraft.network.AttackStyleClientPacket;
import lk1905.gielinorcraft.network.PacketHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.widget.button.ImageButton;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.ResourceLocation;

public class AttackStyleButton extends ImageButton{

    private static int yTex(int slotId) {
        PlayerEntity player =  Minecraft.getInstance().player;
        IAttackStyle styleCap = player.getCapability(AttackStyleCapability.STYLE_CAP).orElse(null);
        if (styleCap.getActiveStyleId() == slotId) {
            return 23;
        } else {
            return 0;
        }
    }
    
    public AttackStyleButton(int xIn, int yIn, int slotId) {    
        super(xIn, yIn, 56, 20, 137, yTex(slotId), 0 , new ResourceLocation(Gielinorcraft.MODID, "textures/gui/combat.png"), (button) -> {
            PacketHandler.sendToServer(new AttackStyleClientPacket(slotId));
        });    
    }
}

您在评论中说 “第一个构造函数存在只是因为这个 class 是从另一个 class 扩展而来的。第二个构造函数是我使用的。”。 =20=] 我不确定你在这里说的为什么你有第一个构造函数。如果 AttackStyleButton class 仅使用第二个构造函数实例化,那么第一个构造函数就没有理由存在。