Jump to content

[1.10.2][GUI][Containers]I don't know how to do GUI


Starless

Recommended Posts

I can't move items in the hotbar. I'm not even close to finish the GUI and the container, and I already ran into this problem...

 

This is a super class implementing some basics. As it is, the players hotbar is part of the rectangle drawn. I will move it out so some GUIs can choose not to display the hotbar. This class apparently works fine (the entire drawing process works as intended. What is not working is the interaction: to pick a hot bar item and put it somewhere else. Also, the inventory seems to be duplicating stacks)

public class GuiBasicContainer extends GuiContainer
{
/**
 * The {@code ResourceLocation} for the basic GUI elements
 */
    private static final ResourceLocation texture = new ResourceLocation(TheMod.MODID, "textures/gui/gui_01.png");
    
        private int windowX;
private int windowY;

public GuiBasicContainer(Container inventorySlotsIn)
{
	super(inventorySlotsIn);
}

@Override
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY)
{
	GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
                this.mc.getTextureManager().bindTexture(texture);
	windowX = (this.width - this.xSize) / 2;
	windowY = (this.height - this.ySize) / 2;
	this.drawTexturedModalRect(windowX, windowY, 0, 0, this.xSize, this.ySize);
}

protected void drawPlayerInventory(int relativeX, int relativeY)
{
	drawTexturedModalRect(windowX + relativeX, windowY + relativeY, 0, 166, 161, 53);
}
}

 

This is the GUI. As said before, it seems to work.

public class GuiExtractor extends GuiBasicContainer
{
    public GuiExtractor(ContainerExtractor inventorySlotsIn)
    {
        super(inventorySlotsIn);
    }

    @Override
    protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY)
    {
        super.drawGuiContainerBackgroundLayer(partialTicks, mouseX, mouseY);
        drawPlayerInventory(7, 83);
    }
}

 

Bellow is a class that is supposed to implement basic behaviours to be used by its derived classes.

 

public abstract class ContainerBasic extends Container
{	
    protected final EntityPlayer player;
    protected int inventorySize;
    
    public ContainerBasic(EntityPlayer player, int inventorySize)
    {
        this.inventorySize = inventorySize;
        this.player = player;
    }

    public EntityPlayer getPlayer()
    {
        return player;
    }
    
    protected void addHotBar(int x, int y)
    {
        for(int i = 0; i < 9; ++i)
        {
            this.addSlotToContainer(new Slot(player.inventory, i, x + i * 18, y));
        }
    }
    
    protected void addPlayerInventory(int x, int y)
    {
        for(int line = 0; line < 3; ++line)
        {
            for(int row = 0; row < 9; ++row)
            {
                int slotID = 9 + line * 9 + row;
                this.addSlotToContainer(new Slot(player.inventory, slotID, x + row * 18, y + line * 18));
            }
        }
    }
    
    //I believe this is the problem. I don't understand the new set of arguments of this method.
    @Override
    public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, EntityPlayer player)
    {
    	Slot slot;
    	if(slotId > 0)
    	{
    	    slot = (Slot) this.inventorySlots.get(slotId);
    	}
    	else
    	{
    	    slot = null;
    	}
if (slot instanceof SlotFake) 
{
    return slotClickFake(slot, dragType, clickTypeIn, player);
}
        return super.slotClick(slotId, dragType, clickTypeIn, player);
    }

    private ItemStack slotClickFake(Slot slot, int mouseButton, ClickType clickTypeIn, EntityPlayer player)
    {
        System.out.println("Clicked Fake Slot");
    	return null;
    }
}

 

I don't think this class is the problem:

public class ContainerExtractor extends ContainerBasic
{
private final TileExtractor extractor;
private final InventoryFake filter;

public ContainerExtractor(EntityPlayer player, TileExtractor extractor)
{
	super(player, 5);
	this.extractor = extractor;
	filter = extractor.getFilter();

	addHotBar(8, 142);
	addPlayerInventory(8, 84);

	this.addSlotToContainer(new SlotItemHandler(filter, 0, 44, 53));
	this.addSlotToContainer(new SlotItemHandler(filter, 1, 44 + 16, 53));
	this.addSlotToContainer(new SlotItemHandler(filter, 2, 44 + 32, 53));
	this.addSlotToContainer(new SlotItemHandler(filter, 3, 44 + 48, 53));
	this.addSlotToContainer(new SlotItemHandler(filter, 4, 44 + 64, 53));
}

@Override
public boolean canInteractWith(EntityPlayer playerIn)
{
	return extractor.isUsableByPlayer(playerIn);
}
}

 

The whole GUI is a mess, things disapear, things get dupped, the game crashes, things can't be moved. It's all broken.

Link to comment
Share on other sites

You have literally overwritten the slotClick method. Do super.slotClick() before you do anything else i, so it's like this:'s like this:

//I believe this is the problem. I don't understand the new set of arguments of this method.
    @Override
    public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, EntityPlayer player)
    {
        super.slotClick(int slotId, int dragType, ClickType clickTypeIn, EntityPlayer player);
    	Slot slot;
    	if(slotId > 0)
    	{
    	    slot = (Slot) this.inventorySlots.get(slotId);
    	}
    	else
    	{
    	    slot = null;
    	}
if (slot instanceof SlotFake) 
{
    return slotClickFake(slot, dragType, clickTypeIn, player);
}
        return super.slotClick(slotId, dragType, clickTypeIn, player);
    }

Link to comment
Share on other sites

You have literally overwritten the slotClick method. Do super.slotClick() before you do anything else i, so it's like this:'s like this:

//I believe this is the problem. I don't understand the new set of arguments of this method.
    @Override
    public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, EntityPlayer player)
    {
        super.slotClick(int slotId, int dragType, ClickType clickTypeIn, EntityPlayer player);
    	Slot slot;
    	if(slotId > 0)
    	{
    	    slot = (Slot) this.inventorySlots.get(slotId);
    	}
    	else
    	{
    	    slot = null;
    	}
if (slot instanceof SlotFake) 
{
    return slotClickFake(slot, dragType, clickTypeIn, player);
}
        return super.slotClick(slotId, dragType, clickTypeIn, player);
    }

 

That didn't help.

Link to comment
Share on other sites

I learned a lot since I asked this question a couple of days ago. My GUI is almost working 100%. But I still feel I need to know exactly what each

dragMode

and

clickType

means and when

[s]Slot.slotClick[/s]

Container.slotClick

is invoked with what parameters.

 

For example, I notice the middle mouse buttom gives a

dragMode

of 2 and a

clickType

of

CLONE

, if you middle click a slot, but it gives a

dragMode

of 9 if you click and drag (with the same

clickType

of

CLONE

.

 

Right clicking:

dragMode

of 1 and

clickType

of

PICKUP

, but sometimes

dragMode

of 5 and

clickType

of

QUICK_CRAFT

.

 

I feel that if I knew what's going on with these parameters I would be able to implement my GUIs free of bugs. I can't be sure if my GUIs will always work as intended if I don't know this method's contract.

Link to comment
Share on other sites

I learned a lot since I asked this question a couple of days ago. My GUI is almost working 100%. But I still feel I need to know exactly what each

dragMode

and

clickType

means and when

Slot.slotClick

is invoked with what parameters.

 

For example, I notice the middle mouse buttom gives a

dragMode

of 2 and a

clickType

of

CLONE

, if you middle click a slot, but it gives a

dragMode

of 9 if you click and drag (with the same

clickType

of

CLONE

.

 

Right clicking:

dragMode

of 1 and

clickType

of

PICKUP

, but sometimes

dragMode

of 5 and

clickType

of

QUICK_CRAFT

.

 

I feel that if I knew what's going on with these parameters I would be able to implement my GUIs free of bugs. I can't be sure if my GUIs will always work as intended if I don't know this method contract.

Look at Container#slotaclick(...) if you understand that code it will lead you to what they mean exactly. If you have some check you need to do like for a backpack. You shouldnt be able to pickup the backpack in the backpacks inventory, to do that you would just check which slotIndex you are clicking and if it is return null otherwise return super.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Look at Container#slotaclick(...) if you understand that code it will lead you to what they mean exactly. If you have some check you need to do like for a backpack. You shouldnt be able to pickup the backpack in the backpacks inventory, to do that you would just check which slotIndex you are clicking and if it is return null otherwise return super.

 

Container.slotClick

was what I meant to say. The method is too long and it has too many conditionals. I want to know the method's contract, meaning, what arguments the method expects and what are the results the caller can expect from the method: if the arguments set is A, invoking the method will have R as return and will cause S as a set of side effects.

 

If anyone could tell me what is

Container.slotClick

contract I would really appreciate it.

Link to comment
Share on other sites

Look at Container#slotaclick(...) if you understand that code it will lead you to what they mean exactly. If you have some check you need to do like for a backpack. You shouldnt be able to pickup the backpack in the backpacks inventory, to do that you would just check which slotIndex you are clicking and if it is return null otherwise return super.

 

Container.slotClick

was what I meant to say. The method is too long and it has too many conditionals. I want to know the method's contract, meaning, what arguments the method expects and what are the results the caller can expect from the method: if the arguments set is A, invoking the method will have R as return and will cause S as a set of side effects.

 

If anyone could tell me what is

Container.slotClick

contract I would really appreciate it.

It is obviously called when a slot in the container is clicked. It expects the return to be an ItemStack. Correct me if I am wrong but I believe the returned stack is the Stack that is bound to the mouse? ClickType.CLONE is used for creative mode when you middle click a slot it returns a new ItemStack of the Item but with the stacksize of 64(or the max stacksize). Drag mode is if the player is binding it to the mouse or not(again subject to correction). ClickType.QUICK_CRAFT is clicking and dragging the item through slots. Any more questions do ask.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

I was hoping for something way more exact than that...

 

Anyway, I have a somewhat satisfactory Container, but it still has an issue (look at the comment on top of

slotClickFake

method):

    @Override
    public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, EntityPlayer player)
    {
    	Slot slot= null;
    	ItemStack stack = null;
    	if(slotId > 0)
    	{
            slot = (Slot) this.inventorySlots.get(slotId);
            stack = slot.getStack();
    	}
    	else
    	{
            slot = null;
    	}
if (slot instanceof SlotFake) 
{
            return slotClickFake((SlotFake)slot, dragType, clickTypeIn, player);
}
        return super.slotClick(slotId, dragType, clickTypeIn, player);
    }

    //A SlotFake is basically a slot to mark things like filters (e.g only consider ItemStacks that are equal to the ItemStack in the fake slot).
    //when you are holding an ItemStack with your mouse, you set the fake slot to have a stack of 0 size equal to that item,
    //without affecting the ItemStack being held (You don't actually put anything in a SlotFake).
    //when you are not holding an ItemStack with your mouse, you pick up the zero sized ItemStack in the SlotFake (if the slot has one).
    //this 0 sized ItemStack is supposed to be valid for other SlotFakes, but, as it is, there is a minor nuissance:
    //you can put these 0 sized ItemStacks in your normal inventory. They disappear when clicked, but I wish this behaviour wouldn't exist.
    private ItemStack slotClickFake(SlotFake slot, int dragType, ClickType clickTypeIn, EntityPlayer player)
    {
        InventoryPlayer playerInv = player.inventory;
ItemStack itemInHand = playerInv.getItemStack();
ItemStack itemInSlot = slot.getStack();

ItemStack result = itemInSlot != null ? itemInSlot.copy() : null;

switch(clickTypeIn)
        {
            case CLONE:
	if(itemInSlot != null)
	{
	    if(player.capabilities.isCreativeMode)
                    {
                        if(itemInHand != null
		    && itemInHand.stackSize < itemInHand.getMaxStackSize()
		    && ItemHandlerHelper.canItemStacksStack(itemInHand, itemInHand))
		{
		    itemInHand.stackSize = itemInHand.getMaxStackSize();
		}
		else
		{
		    slot.putStack(null);
		}			
	    }
	    else
	    {
		slot.putStack(null);
                    }
                }
                break;
            case PICKUP:
            case PICKUP_ALL:
            case QUICK_CRAFT:
            case QUICK_MOVE:
                if(itemInHand != null && slot.isItemValid(itemInHand))
	{
                    ItemStack copy = itemInHand.copy();
                    slot.putStack(copy);
                    result = copy;
	}
	else if(itemInSlot != null)
	{
                    playerInv.setItemStack(itemInSlot);
                    slot.putStack(null);
                }
                break;
            case SWAP://I don't know what to do in these cases
	break;
            case THROW:
	break;
            default:
	break;
        }
        return result;
    }

Link to comment
Share on other sites

I was hoping for something way more exact than that...

 

Anyway, I have a somewhat satisfactory Container, but it still has an issue (look at the comment on top of

slotClickFake

method):

    @Override
    public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, EntityPlayer player)
    {
    	Slot slot= null;
    	ItemStack stack = null;
    	if(slotId > 0)
    	{
            slot = (Slot) this.inventorySlots.get(slotId);
            stack = slot.getStack();
    	}
    	else
    	{
            slot = null;
    	}
if (slot instanceof SlotFake) 
{
            return slotClickFake((SlotFake)slot, dragType, clickTypeIn, player);
}
        return super.slotClick(slotId, dragType, clickTypeIn, player);
    }

    //A SlotFake is basically a slot to mark things like filters (e.g only consider ItemStacks that are equal to the ItemStack in the fake slot).
    //when you are holding an ItemStack with your mouse, you set the fake slot to have a stack of 0 size equal to that item,
    //without affecting the ItemStack being held (You don't actually put anything in a SlotFake).
    //when you are not holding an ItemStack with your mouse, you pick up the zero sized ItemStack in the SlotFake (if the slot has one).
    //this 0 sized ItemStack is supposed to be valid for other SlotFakes, but, as it is, there is a minor nuissance:
    //you can put these 0 sized ItemStacks in your normal inventory. They disappear when clicked, but I wish this behaviour wouldn't exist.
    private ItemStack slotClickFake(SlotFake slot, int dragType, ClickType clickTypeIn, EntityPlayer player)
    {
        InventoryPlayer playerInv = player.inventory;
ItemStack itemInHand = playerInv.getItemStack();
ItemStack itemInSlot = slot.getStack();

ItemStack result = itemInSlot != null ? itemInSlot.copy() : null;

switch(clickTypeIn)
        {
            case CLONE:
	if(itemInSlot != null)
	{
	    if(player.capabilities.isCreativeMode)
                    {
                        if(itemInHand != null
		    && itemInHand.stackSize < itemInHand.getMaxStackSize()
		    && ItemHandlerHelper.canItemStacksStack(itemInHand, itemInHand))
		{
		    itemInHand.stackSize = itemInHand.getMaxStackSize();
		}
		else
		{
		    slot.putStack(null);
		}			
	    }
	    else
	    {
		slot.putStack(null);
                    }
                }
                break;
            case PICKUP:
            case PICKUP_ALL:
            case QUICK_CRAFT:
            case QUICK_MOVE:
                if(itemInHand != null && slot.isItemValid(itemInHand))
	{
                    ItemStack copy = itemInHand.copy();
                    slot.putStack(copy);
                    result = copy;
	}
	else if(itemInSlot != null)
	{
                    playerInv.setItemStack(itemInSlot);
                    slot.putStack(null);
                }
                break;
            case SWAP://I don't know what to do in these cases
	break;
            case THROW:
	break;
            default:
	break;
        }
        return result;
    }

Instead return null.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

I want to be able to grab the 0 sized stacks, I just don't want to be able to put them anywhere other than in a SlotFake.

Have every other slot that is not a SlotFake be a custom slot that overrides onSlotChanged and check if par2's stackSize is <= 0 if so set this slots ItemStack = null. (This may work I am not sure when this method is called. Be sure to check what happens when you click on a slot with another ItemStack in it).

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.