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

Java Minecraft Forge-显式调用构造函数时无法引用实例字段,java,minecraft,minecraft-forge,Java,Minecraft,Minecraft Forge,对于我的Minecraft mod,我已经编写了一个自定义按钮类,这样当按下按钮时,它会向服务器发送一个数据包,以更新功能。该按钮还应改变纹理,以便与功能中设置的“样式”具有相同id的按钮为红色,而其他按钮为灰色 然而,我遇到的一个问题是,在具有正确id的按钮之后的下一个按钮是实际变为红色的按钮(例如,如果id为0的按钮是活动id,则id为1的按钮是变为红色的按钮) 这是我的按钮类: package lk1905.gielinorcraft.client.gui.widget; import l

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

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

这是我的按钮类:

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”不应该是静态的(他们不会说为什么,只是“请了解静态的含义”,尽管我找不到足够多的类似示例来理解为什么)

但问题是,我之所以将其设置为静态,首先是因为eclipse在第二个构造函数中给出了错误“无法在显式调用构造函数时引用实例字段yTex”,并告诉我将其设置为静态

据我所知,错误是因为在实例化yTex时,它在调用构造函数之前没有值,因此构造函数无法继续。但我不知道如何重写这个类,使它做同样的事情。我想在这个类中设置yTex的值,由if语句决定它的值


那么,我该如何重写这个类,使它执行我已经告诉它的操作,但yTex不是静态的?

如果要添加逻辑来计算要传递到超类构造函数中的值,您不能使用调用类中的任何实例变量或方法,因为在调用超类的构造函数时,调用类不存在任何相关内容

静态方法可用于运行代码以计算作为参数传递给超类构造函数的值。上述规则同样适用于此静态方法中的代码。下面是如何使用此技术计算要传递到超类构造函数中的值,而不是计算的
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));
        });    
    }
}

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

这是一个非常好的问题,因为它包含了OP所研究的内容(这是一个非常罕见的现象)。LK1905,如果你能将你的Minecraft代码转换成更通用的代码,那么这个问题将是未来用户可以受益的。我不确定我是否理解你的第一个示例,我是否也需要在第一个构造函数中设置
yTex=yTexStartIn
?因为yTex甚至没有被使用,所以它只使用第二个构造函数中设置的值,即0。第二个示例也没有做任何事情。生成
yTex=yTextInitialValue
仅将
yTex
的初始值设置为
yTexInitialValue
的值。更改
yTex
的值不会更改
yTexInitialValue
的值,因此该值保持为0,因此在构造函数中使用该值将值保持为0,
yTex
根本不被使用。我想我第一次不理解您的问题,但现在可能理解了。在第二个构造函数中,您希望根据if
styleCap.getActiveStyleId()==slotId
?,将0或23传递给超类的构造函数?。我可以教你怎么做。我还是不知道你想要第一个构造函数做什么。您只讨论了yTex,但在第一个构造函数中没有使用它,所以我不知道您想在那里做什么。第一个构造函数在那里只是因为这个类是从另一个类扩展而来的。第二个构造函数是我使用的。我以为我需要第一个构造函数,但我只需要在第二个构造函数中创建
this
。但是你的答案很好,谢谢!