[1.12.2][gui]如何通过按钮清空物品槽

ArcoWave


版本信息
你使用的IDE:IntelliJ IDEA
你使用的IDE版本:2018.3
Forge版本: 1.12.2-14.23.5.2847
Minecraft版本: 1.12.2

错误情况简述
我新创建了一个GUI,并在GUI上添加了一个按钮、四个物品槽
用一个物品Shift+右击可以打开这个GUI
我想通过按下按钮来清空四个物品槽
目前按下后,物品槽确实会清空,但是往槽里放入物品后,物品会重新出现。
个人认为是Container和GuiContainer没有同步导致的,但是不知道该怎么写

还有一个问题,
getSlotStackLimit()这个方法并没有成功限制每个槽内的最大物品个数
我把SlotIn1的这个返回值设定为1,但是下图里可以看到
这个槽里能放三个金锭

相关代码
GuiContainerTestTube


import com.testmod.tm.util.Reference;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.resources.I18n;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

import java.io.IOException;

@SideOnly(Side.CLIENT)
public class GuiContainerTestTube extends GuiContainer {

    private static final String TEXT_PATH = Reference.MODID + ":" + "textures/gui/container/gui_test_tube.png";
    private static final ResourceLocation res = new ResourceLocation(TEXT_PATH);

    private static final int BUTTON_EMPTY = 1;

    private Slot SlotOut2;
    private Slot SlotOut1;
    private Slot SlotIn1;
    private Slot SlotIn2;

    public GuiContainerTestTube(Container inventorySlotsIn) {
        super(inventorySlotsIn);
        this.xSize = 176;
        this.ySize = 166;
        this.SlotOut2 = inventorySlotsIn.getSlot(3);
        this.SlotOut1 = inventorySlotsIn.getSlot(2);
        this.SlotIn2 = inventorySlotsIn.getSlot(1);
        this.SlotIn1 = inventorySlotsIn.getSlot(0);
    }

    @Override
    protected void actionPerformed(GuiButton button) throws IOException {
        switch (button.id){
            case BUTTON_EMPTY:
                this.SlotOut2.putStack(ItemStack.EMPTY);
                this.SlotOut1.putStack(ItemStack.EMPTY);
                this.SlotIn2.putStack(ItemStack.EMPTY);
                this.SlotIn1.putStack(ItemStack.EMPTY);
                break;
            default:
                super.actionPerformed(button);
                return;
        }

    }

    @Override
    protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
        GlStateManager.color(1.0F,1.0F,1.0F,1.0F);

        this.mc.getTextureManager().bindTexture(res);
        int offsetX = (this.width - this.xSize)/2;
        int offsetY = (this.height - this.ySize)/2;

        this.drawGradientRect(0, 0, this.width, this.height, -1072689136, -804253680);
        this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, this.ySize);

    }

    @Override
    protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
        String title = I18n.format("container.test_tube");
        this.fontRenderer.drawString(title,59,11,0x1E90FF);
    }

    @Override
    public void initGui() {
        super.initGui();
        int offsetX = (this.width - this.xSize)/2;
        int offsetY = (this.height - this.ySize)/2;
        this.buttonList.add(new GuiButton(BUTTON_EMPTY, offsetX + 44, offsetY + 59, 15, 14, ""){
            @Override
            public void drawButton(Minecraft mc, int mouseX, int mouseY, float partialTicks) {
                if(this.visible){
                    GlStateManager.color(1.0F,1.0F,1.0F);

                    mc.getTextureManager().bindTexture(res);
                    int x = mouseX - this.x, y = mouseY - this.y;

                    if (x >= 0 && y >= 0 && x < this.width && y < this.height){
                        this.drawTexturedModalRect(this.x, this.y, 63, 167, this.width, this.height);
                    }
                    else{
                        this.drawTexturedModalRect(this.x, this.y, 43, 167, this.width, this.height);
                    }

                }
            }
        });

    }
}

ContainerTestTube


import com.testmod.tm.items.ModItems;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Items;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.SlotItemHandler;

import javax.annotation.Nonnull;

public class ContainerTestTube extends Container {

    private ItemStackHandler items = new ItemStackHandler(4);
    protected Slot SlotIn1;
    protected Slot SlotIn2;
    protected Slot SlotOut1;
    protected Slot SlotOut2;

    public ContainerTestTube(EntityPlayer player){
        super();

        this.addSlotToContainer(this.SlotIn1 = new SlotItemHandler(items, 0, 59+0*18, 39){
            @Override
            public boolean isItemValid(@Nonnull ItemStack stack) {
                return !stack.isEmpty() && stack.getItem() == Items.GOLD_INGOT && super.isItemValid(stack);
            }

            @Override
            public int getSlotStackLimit() {
                return 1;
            }
        });
        this.addSlotToContainer(this.SlotIn2 = new SlotItemHandler(items, 1, 59+1*18, 39){
            @Override
            public boolean canTakeStack(EntityPlayer playerIn) {
                return false;
            }

            @Override
            public int getSlotStackLimit() {
                return 8;
            }
        });
        this.addSlotToContainer(this.SlotOut1 = new SlotItemHandler(items, 2, 125+0*18,39));
        this.addSlotToContainer(this.SlotOut2 = new SlotItemHandler(items, 3, 125+1*18,39));

        for(int i =0; i < 9; ++i){
            this.addSlotToContainer(new Slot(player.inventory, i, 8 + i * 18, 142));
        }
        for(int i = 0; i < 3; ++i){
            for(int j = 0; j < 9; ++j){
                this.addSlotToContainer(new Slot(player.inventory, 9*i+j+9, 8+j*18, 84+i*18));
            }
        }
    }



    @Override
    public boolean canInteractWith(EntityPlayer playerIn) {
        return new ItemStack(ModItems.TEST_TUBE).isItemEqual(playerIn.getHeldItemMainhand());
    }

    @Override
    public ItemStack transferStackInSlot(EntityPlayer playerIn, int index) {
        return null;
    }

}

出错图

如图,我往四个物品槽里放了一些金锭

我点击了按钮,物品槽是清空了
此时,我再往左边第一个槽里放一个金锭

所有槽里的物品都回来了

查到的资料
参考的教程:3.4.3 GUI界面中的交互 · GitBook


dbydd


你没有发包,需要发包通知服务端更新方块


ArcoWave


那这句话

⑥传输的是玩家对于物品槽的操作,客户端会将其同步至服务端。

的范围是限制在“玩家操作“,而像putStack()是需要自己手动同步么

对了,我这个是通过物品右击打开的GUI,不是方块


dbydd


emm那我就不知道了,没写过


FledgeXu


对了,我这个是通过物品右击打开的GUI,不是方块

如果是这样你需要手动同步数据,请看文档关于 SimpleImpl的内容。


ArcoWave


好的,那请问关于第二个问题getSlotStackLimit()不起作用的问题该如何解决呢


FledgeXu


看上去应该没问题,这个方法,你可以下个断点试试看看有没有执行到这个方法。

其次你确定函数的对的吗?我1.14用的是以下方法:

addSlot(new SlotItemHandler(handler, index, x, y));

ArcoWave


方法是对的,1.12.2这里好像没有addSlot这个方法
我设置断点试试吧
谢谢


FledgeXu


如果要同步数据,Container有个叫做detectAndSendChanges的方法。


ArcoWave


(帖子被作者删除,如无标记将在 24 小时后自动删除)


ArcoWave


我能详细问下吗,
按下按钮触发的pustack是在客户端的GuiContainer上执行的吧
然后服务器端的Container对此并不知情,所以我只需要给Container发个包就能解决问题了对么…
(detectAndSendChanges好像是Container给GuiContainer发数据的…?)


FledgeXu


对是这样的。


system


该主题在最后一个回复创建后7天后自动关闭。不再允许新的回复。