Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

[SOLVED] GUI Items in player inventory behaving awkwardly


Recommended Posts

I have a very simple block.  When you right-click that block, there appears a very simple GUI that, currently, only has one placeholder button and the player's inventory.  The items in the player's inventory appear to be placed correctly, but when clicked, they hop to the cursor then immediately drop back into the inventory.  Sometimes I can pick up an item but it doesn't appear to *actually* be happening when I click again; or the item disappears entirely; or the item is dropped into the world.

 

Edit: added the tile entity and my proxies, for reference.

 

MerchantBlock.java

package x.thealphaelement.block;

import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import x.thealphaelement.TheAlphaElement;
import x.thealphaelement.tileentity.TileEntityMerchantBlock;

public class MerchantBlock extends BlockContainer {

private InventoryPlayer playerInventory;

        public MerchantBlock (int id, int texture, Material material) {
                super(id, material);
                
                setHardness(0.3F);
        		setStepSound(soundWoodFootstep);
        		setUnlocalizedName("merchantBlock");
        		setCreativeTab(CreativeTabs.tabDecorations);
        }
        
        public void registerIcons(IconRegister iconRegister) {
        	blockIcon = iconRegister.registerIcon("TheAlphaElement:blocktest");
        }
        
        public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
        {
        	TileEntityMerchantBlock merchantBlock = (TileEntityMerchantBlock)par1World.getBlockTileEntity(par2, par3, par4);
            par5EntityPlayer.openGui(TheAlphaElement.instance, 0, par1World, par2, par3, par4);
            return true;
        }

	@Override
	public TileEntity createNewTileEntity(World world) {
		return new TileEntityMerchantBlock();
	}

 

GuiMerchantBlock.java

package x.thealphaelement.client.gui;

import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.entity.player.EntityPlayer;

import org.lwjgl.opengl.GL11;

import x.thealphaelement.tileentity.TileEntityMerchantBlock;

public class GuiMerchantBlock extends GuiContainer {

public final int xSizeOfTexture = 176;
public final int ySizeOfTexture = 207;
private int inventoryRows = 0;

private EntityPlayer player; 

public GuiMerchantBlock(EntityPlayer player, TileEntityMerchantBlock te) {
	super(new ContainerMerchantBlock(player.inventory, te));
	this.player = player;
	short short1 = 223;
        int i = short1 - 108;
        this.inventoryRows = player.inventory.getSizeInventory() / 9;
        this.ySize = i + this.inventoryRows * 18;
       

}

public void initGui()
{
	super.initGui();
	int posX = (this.width - xSizeOfTexture) / 2;
	int posY = (this.height - ySizeOfTexture) / 2;
	this.buttonList.clear();
	this.buttonList.add(new GuiButton(0, posX+ 40, posY + 40, 100, 20, "no use"));
}

@Override
public boolean doesGuiPauseGame()
{
return false;
}

@Override
protected void keyTyped(char par1, int par2) {
	if (par2 == 1 || par2 == this.mc.gameSettings.keyBindInventory.keyCode) {
		this.mc.thePlayer.closeScreen();
	}
}

public void actionPerformed(GuiButton button) {
	switch(button.id) {
		case 0: player.addChatMessage("Good job!");

		break;
		default:	
	}
}

@Override
protected void drawGuiContainerBackgroundLayer(float f, int i, int j) {
	GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
	this.mc.renderEngine.bindTexture("/mods/TheAlphaElement/textures/gui/generalMerchant.png");

	int posX = (this.width - xSizeOfTexture) / 2;
	int posY = (this.height - ySizeOfTexture) / 2;


	drawTexturedModalRect(posX, posY, 0, 0, this.xSize, ySizeOfTexture);

}


}

 

ContainerMerchantBlock.java

package x.thealphaelement.client.gui;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import x.thealphaelement.tileentity.TileEntityMerchantBlock;

public class ContainerMerchantBlock extends Container {

private TileEntityMerchantBlock tileEntity;
    private int numRows;
    protected IInventory playerInventory;

public ContainerMerchantBlock(InventoryPlayer playerInv, TileEntityMerchantBlock te) {
	tileEntity = te;
	playerInventory = playerInv;
	playerInv.openChest();
        this.numRows = playerInv.getSizeInventory() / 9;
        int i = (this.numRows - 4) * 18;
        int j;
        int k;

        for (j = 0; j < 3; ++j)
        {
            for (k = 0; k < 9; ++k)
            {
                this.addSlotToContainer(new Slot(playerInv, k + j * 9 + 9, 8 + k * 18, 115 + j * 18 + i));
            }  
        }
        
        for (j = 0; j < 9; ++j)
        {
            this.addSlotToContainer(new Slot(playerInv, j, 8 + j * 18, 173 + i));
        }
        
}

@Override
public boolean canInteractWith(EntityPlayer entityplayer) {
	return playerInventory.isUseableByPlayer(entityplayer);
}

public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) {
        return null;
    }

}

 

TileEntityMerchantBlock.java

package x.thealphaelement.tileentity;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;

public class TileEntityMerchantBlock extends TileEntity implements IInventory {

public TileEntityMerchantBlock() {

}

public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer)
{
         if (worldObj.getBlockTileEntity(xCoord, yCoord, zCoord) != this)
         {
                 return false;
         }

         return par1EntityPlayer.getDistanceSq((double)xCoord + 0.5D, (double)yCoord + 0.5D, (double)zCoord + 0.5D) <= 64D;
}

@Override
public int getSizeInventory() {
	// TODO Auto-generated method stub
	return 0;
}

@Override
public ItemStack getStackInSlot(int i) {
	// TODO Auto-generated method stub
	return null;
}

@Override
public ItemStack decrStackSize(int i, int j) {
	// TODO Auto-generated method stub
	return null;
}

@Override
public ItemStack getStackInSlotOnClosing(int i) {
	// TODO Auto-generated method stub
	return null;
}

@Override
public void setInventorySlotContents(int i, ItemStack itemstack) {
	// TODO Auto-generated method stub

}

@Override
public String getInvName() {
	// TODO Auto-generated method stub
	return null;
}

@Override
public boolean isInvNameLocalized() {
	// TODO Auto-generated method stub
	return false;
}

@Override
public int getInventoryStackLimit() {
	// TODO Auto-generated method stub
	return 0;
}

@Override
public void openChest() {
	// TODO Auto-generated method stub

}

@Override
public void closeChest() {
	// TODO Auto-generated method stub

}

@Override
public boolean isStackValidForSlot(int i, ItemStack itemstack) {
	// TODO Auto-generated method stub
	return false;
}

}

 

ClientProxy.java

package x.thealphaelement.client;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import x.thealphaelement.CommonProxy;
import x.thealphaelement.client.gui.GuiMerchantBlock;
import x.thealphaelement.client.renderer.RenderBlazeModded;
import x.thealphaelement.client.renderer.RenderCreeperModded;
import x.thealphaelement.client.renderer.RenderEndermanModded;
import x.thealphaelement.client.renderer.RenderGhastModded;
import x.thealphaelement.client.renderer.RenderSkeletonModded;
import x.thealphaelement.client.renderer.RenderSpiderModded;
import x.thealphaelement.client.renderer.RenderWitchModded;
import x.thealphaelement.client.renderer.RenderZombieModded;
import x.thealphaelement.entity.monster.EntityBlazeModded;
import x.thealphaelement.entity.monster.EntityBlueSkeleton;
import x.thealphaelement.entity.monster.EntityBlueSpider;
import x.thealphaelement.entity.monster.EntityBlueZombie;
import x.thealphaelement.entity.monster.EntityCaveSpiderModded;
import x.thealphaelement.entity.monster.EntityCreeperModded;
import x.thealphaelement.entity.monster.EntityEndermanModded;
import x.thealphaelement.entity.monster.EntityGhastModded;
import x.thealphaelement.entity.monster.EntityPigZombieModded;
import x.thealphaelement.entity.monster.EntityRedSkeleton;
import x.thealphaelement.entity.monster.EntityRedSpider;
import x.thealphaelement.entity.monster.EntityRedZombie;
import x.thealphaelement.entity.monster.EntitySkeletonModded;
import x.thealphaelement.entity.monster.EntitySpiderModded;
import x.thealphaelement.entity.monster.EntitySpiderling;
import x.thealphaelement.entity.monster.EntityWitchModded;
import x.thealphaelement.entity.monster.EntityZombieModded;
import x.thealphaelement.tileentity.TileEntityMerchantBlock;
import cpw.mods.fml.client.registry.RenderingRegistry;
import cpw.mods.fml.common.registry.EntityRegistry;

public class ClientProxy extends CommonProxy {
        
        @Override
        public void registerRenderers() {
        	RenderingRegistry.registerEntityRenderingHandler(EntitySkeletonModded.class, new RenderSkeletonModded());
            EntityRegistry.registerGlobalEntityID(EntitySkeletonModded.class, "NormalSkeleton", EntityRegistry.findGlobalUniqueEntityId(), 3515848, 12102);
            
            RenderingRegistry.registerEntityRenderingHandler(EntityZombieModded.class, new RenderZombieModded());
            EntityRegistry.registerGlobalEntityID(EntityZombieModded.class, "NormalZombie", EntityRegistry.findGlobalUniqueEntityId(), 3515848, 12102);
            
            RenderingRegistry.registerEntityRenderingHandler(EntitySpiderModded.class, new RenderSpiderModded());
            EntityRegistry.registerGlobalEntityID(EntitySpiderModded.class, "NormalSpider", EntityRegistry.findGlobalUniqueEntityId(), 3515848, 12102);
            
            RenderingRegistry.registerEntityRenderingHandler(EntityCreeperModded.class, new RenderCreeperModded());
            EntityRegistry.registerGlobalEntityID(EntityCreeperModded.class, "NormalCreeper", EntityRegistry.findGlobalUniqueEntityId(), 3515848, 12102);
            
            RenderingRegistry.registerEntityRenderingHandler(EntityEndermanModded.class, new RenderEndermanModded());
            EntityRegistry.registerGlobalEntityID(EntityEndermanModded.class, "NormalEnderman", EntityRegistry.findGlobalUniqueEntityId(), 3515848, 12102);
            
            RenderingRegistry.registerEntityRenderingHandler(EntityCaveSpiderModded.class, new RenderSpiderModded());
            EntityRegistry.registerGlobalEntityID(EntityCaveSpiderModded.class, "NormalCaveSpider", EntityRegistry.findGlobalUniqueEntityId(), 3515848, 12102);
            
            RenderingRegistry.registerEntityRenderingHandler(EntityWitchModded.class, new RenderWitchModded());
            EntityRegistry.registerGlobalEntityID(EntityWitchModded.class, "NormalWitch", EntityRegistry.findGlobalUniqueEntityId(), 3515848, 12102);
            
            RenderingRegistry.registerEntityRenderingHandler(EntityBlazeModded.class, new RenderBlazeModded());
            EntityRegistry.registerGlobalEntityID(EntityBlazeModded.class, "NormalBlaze", EntityRegistry.findGlobalUniqueEntityId(), 3515848, 12102);
            
            RenderingRegistry.registerEntityRenderingHandler(EntityGhastModded.class, new RenderGhastModded());
            EntityRegistry.registerGlobalEntityID(EntityGhastModded.class, "NormalGhast", EntityRegistry.findGlobalUniqueEntityId(), 3515848, 12102);
            
            RenderingRegistry.registerEntityRenderingHandler(EntityPigZombieModded.class, new RenderZombieModded());
            EntityRegistry.registerGlobalEntityID(EntityPigZombieModded.class, "NormalPigZombie", EntityRegistry.findGlobalUniqueEntityId(), 3515848, 12102);
            
            RenderingRegistry.registerEntityRenderingHandler(EntityRedZombie.class, new RenderZombieModded());
            EntityRegistry.registerGlobalEntityID(EntityRedZombie.class, "RedZombie", EntityRegistry.findGlobalUniqueEntityId(), 3515848, 12102);
            
            RenderingRegistry.registerEntityRenderingHandler(EntityBlueZombie.class, new RenderZombieModded());
            EntityRegistry.registerGlobalEntityID(EntityBlueZombie.class, "BlueZombie", EntityRegistry.findGlobalUniqueEntityId(), 3515848, 12102);
            
            RenderingRegistry.registerEntityRenderingHandler(EntityRedSkeleton.class, new RenderSkeletonModded());
            EntityRegistry.registerGlobalEntityID(EntityRedSkeleton.class, "RedSkeleton", EntityRegistry.findGlobalUniqueEntityId(), 3515848, 12102);
            
            RenderingRegistry.registerEntityRenderingHandler(EntityBlueSkeleton.class, new RenderSkeletonModded());
            EntityRegistry.registerGlobalEntityID(EntityBlueSkeleton.class, "BlueSkeleton", EntityRegistry.findGlobalUniqueEntityId(), 3515848, 12102);
            
            RenderingRegistry.registerEntityRenderingHandler(EntityRedSpider.class, new RenderSpiderModded());
            EntityRegistry.registerGlobalEntityID(EntityRedSpider.class, "RedSpider", EntityRegistry.findGlobalUniqueEntityId(), 3515848, 12102);
            
            RenderingRegistry.registerEntityRenderingHandler(EntityBlueSpider.class, new RenderSpiderModded());
            EntityRegistry.registerGlobalEntityID(EntityBlueSpider.class, "BlueSpider", EntityRegistry.findGlobalUniqueEntityId(), 3515848, 12102);
            
            RenderingRegistry.registerEntityRenderingHandler(EntitySpiderling.class, new RenderSpiderModded());
            EntityRegistry.registerGlobalEntityID(EntitySpiderling.class, "Spiderling", EntityRegistry.findGlobalUniqueEntityId(), 3515848, 12102);
            
            
       }
        
        public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
        	TileEntity tileEntity = world.getBlockTileEntity(x, y, z);
        	if (tileEntity != null) {
        		switch(ID) {
        			case 0: return new GuiMerchantBlock(player, (TileEntityMerchantBlock)tileEntity); // your GUIs go here
        		}
        	}
        	return null;
        }
        
}

 

 

CommonProxy.java

package x.thealphaelement;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.world.World;
import cpw.mods.fml.common.network.IGuiHandler;

public class CommonProxy implements IGuiHandler {
        
	// Client stuff
        public void registerRenderers() {
                // Nothing here as the server doesn't render graphics!
        }

	@Override
	public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
		return null;
	}

	@Override
	public Object getServerGuiElement(int ID, EntityPlayer player,
			World world, int x, int y, int z) {
		// TODO Auto-generated method stub
		return null;
	}

        
}

 

I feel like I'm really close here.  Any ideas?

Link to post
Share on other sites

public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
        {
        	TileEntityMerchantBlock merchantBlock = (TileEntityMerchantBlock)par1World.getBlockTileEntity(par2, par3, par4);
            par5EntityPlayer.openGui(TheAlphaElement.instance, 0, par1World, par2, par3, par4);
            return true;
        }

Here is your problem.Just change it to:

public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
        {
           if(!par1World.isRemote){
        	TileEntityMerchantBlock merchantBlock =    (TileEntityMerchantBlock)par1World.getBlockTileEntity(par2, par3, par4);
            par5EntityPlayer.openGui(TheAlphaElement.instance, 0, par1World, par2, par3, par4);
            }
            return true;
        }

Link to post
Share on other sites

public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
        {
        	TileEntityMerchantBlock merchantBlock = (TileEntityMerchantBlock)par1World.getBlockTileEntity(par2, par3, par4);
            par5EntityPlayer.openGui(TheAlphaElement.instance, 0, par1World, par2, par3, par4);
            return true;
        }

Here is your problem.Just change it to:

public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
        {
           if(!par1World.isRemote){
        	TileEntityMerchantBlock merchantBlock =    (TileEntityMerchantBlock)par1World.getBlockTileEntity(par2, par3, par4);
            par5EntityPlayer.openGui(TheAlphaElement.instance, 0, par1World, par2, par3, par4);
            }
            return true;
        }

 

Thank you so much for the response.  I've honestly been working on this sole issue for about 3 days.  When I make your change, though, the block simply doesn't activate anymore, lol.  This is really confusing.

Link to post
Share on other sites

I forgot. Make the canInteractWith() method in your container aleays return true.

 

I've done that; it has no effect.  I tried making canInteractWith() always return true again with your code from above too, and the block still does not activate with the proposed change, so I simply changed it back.

Link to post
Share on other sites

I posted my code here as per your PM. I'm not sure what your problem is, but I think it might be with your TileEntity.

 

Thanks for the help.  The problem persists quite stubbornly... as for my tile entity, I've updated the original post with it.  But it's mostly empty; I didn't think the tile entity had anything to do with the player's inventory.  The gui and block aren't calling for the block's inventory at all; for now, it's just trying to properly bind the player's inventory to the gui/container.

 

But, if you can see something in the mostly barebones tile entity, please let me know.

Link to post
Share on other sites

I posted my code here as per your PM. I'm not sure what your problem is, but I think it might be with your TileEntity.

 

Thanks for the help.  The problem persists quite stubbornly... as for my tile entity, I've updated the original post with it.  But it's mostly empty; I didn't think the tile entity had anything to do with the player's inventory.  The gui and block aren't calling for the block's inventory at all; for now, it's just trying to properly bind the player's inventory to the gui/container.

 

But, if you can see something in the mostly barebones tile entity, please let me know.

The TileEntity is just as important as the Container. Perhaps more so. You need to add an ItemStack[] field and fix all those auto-generated IInventory functions. Look at my code for an example.

BEWARE OF GOD

---

Co-author of Pentachoron Labs' SBFP Tech.

Link to post
Share on other sites

The TileEntity is just as important as the Container. Perhaps more so. You need to add an ItemStack[] field and fix all those auto-generated IInventory functions. Look at my code for an example.

 

I thought that might be the case, so before updating my original post I did change my tile entity to this, but it had no effect:

 

package x.thealphaelement.tileentity;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.StringTranslate;

public class TileEntityMerchantBlock extends TileEntity implements IInventory {

private ItemStack[] inventory = new ItemStack[8];
private boolean hasItem = false;

public TileEntityMerchantBlock() {

}

public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer)
{
         if (worldObj.getBlockTileEntity(xCoord, yCoord, zCoord) != this)
         {
                 return false;
         }

         return par1EntityPlayer.getDistanceSq((double)xCoord + 0.5D, (double)yCoord + 0.5D, (double)zCoord + 0.5D) <= 64D;
}

@Override
public int getSizeInventory(){
	return this.inventory.length;
}

@Override
public ItemStack getStackInSlot(int index){
	return this.inventory[index];
}

@Override
public ItemStack decrStackSize(int slot, int num){
	if(this.inventory[slot]!=null){
		ItemStack stack;
		if(this.inventory[slot].stackSize<=num){
			stack = this.inventory[slot];
			this.inventory[slot] = null;
			return stack;
		}else{
			stack = this.inventory[slot].splitStack(num);
			if(this.inventory[slot].stackSize==0){
				this.inventory[slot] = null;
			}
			return stack;
		}
	}else return null;
}

@Override
public ItemStack getStackInSlotOnClosing(int index){
	if(this.inventory[index]!=null){
		ItemStack var2 = this.inventory[index];
		this.inventory[index] = null;
		return var2;
	}else return null;
}

@Override
public void setInventorySlotContents(int index, ItemStack stack){
	this.inventory[index] = stack;
	if(stack!=null&&stack.stackSize>this.getInventoryStackLimit()){
		stack.stackSize = this.getInventoryStackLimit();
	}
}

@Override
public String getInvName(){
	return StringTranslate.getInstance().translateKey("merchantBlock.name");
}

@Override
public boolean isInvNameLocalized(){
	return true;
}

@Override
public int getInventoryStackLimit(){
	return 64;
}

@Override
public void openChest() {
	// TODO Auto-generated method stub

}

@Override
public void closeChest() {
	// TODO Auto-generated method stub

}

@Override
public boolean isStackValidForSlot(int i, ItemStack itemstack) {
	// TODO Auto-generated method stub
	return true;
}



}

 

Then I reverted back to my original, barebones tile entity, seeing that the change didn't seem significant.  Am I editing the wrong methods in the tile entity?  Also, I suppose I'm confused as to how the tile entity can affect this because although the tile entity is called in the block's constructor, the tile entity is never actually used in the code.

Link to post
Share on other sites

Considering that I am having the same problem, and that my tile entity does have the read and write functions (as well as simple packet code), and that their container doesn't actually create any slots for the tile, I would be quite surprised if that were the root of the problem.

 

here is my tile code to be clear:

package com.quargos.am.blocks.tiles;

import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.INetworkManager;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.Packet132TileEntityData;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.liquids.ILiquidTank;
import net.minecraftforge.liquids.LiquidContainerRegistry;
import net.minecraftforge.liquids.LiquidStack;

public class TileCrystaliser extends TileEntity implements IInventory,
        ILiquidTank
{
    public LiquidStack liquid = new LiquidStack(Block.waterStill, 0);
    
    public ItemStack[] contents = new ItemStack[3];
    
    @Override
    public void updateEntity()
    {
        super.updateEntity();
    }
    
    public Packet getDescriptionPacket()
    {
        NBTTagCompound nbtTag = new NBTTagCompound();
        this.writeToNBT(nbtTag);
        return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, 1, nbtTag);
    }

    public void onDataPacket(INetworkManager net, Packet132TileEntityData packet) {
        readFromNBT(packet.customParam1);
    }
    
    @Override
    public void readFromNBT(NBTTagCompound nbt)
    {
        for(int i = 0; i < contents.length; i++)
        {
            contents[i] = ItemStack.loadItemStackFromNBT(nbt.getCompoundTag("content_" + i));
        }
        liquid.amount = nbt.getInteger("waterLevel");
        
        super.readFromNBT(nbt);
    }
    
    @Override
    public void writeToNBT(NBTTagCompound nbt)
    {
        for(int i = 0; i < contents.length; i++)
        {
            if(contents[i] != null)
                contents[i].writeToNBT(nbt.getCompoundTag("content_" + i)); //Ensure works!
        }
        nbt.setInteger("waterLevel", liquid.amount);
        
        super.writeToNBT(nbt);
    }
    
    
    //ILiquidTank
    @Override
    public LiquidStack getLiquid()
    {
        return liquid;
    }
    
    @Override
    public int getCapacity()
    {
        return 8*LiquidContainerRegistry.BUCKET_VOLUME;
    }
    
    @Override
    public int fill(LiquidStack resource, boolean doFill)
    {
        if(doFill)
        {
            if(resource.itemID == Block.waterStill.blockID)
            {
                int amount = liquid.amount + resource.amount;
                if(amount > getCapacity())
                {
                    amount -= getCapacity();
                    liquid.amount = getCapacity();
                    return resource.amount - amount;
                }
                liquid.amount += resource.amount;
                return resource.amount;
            }
        }
        return 0;
    }
    
    @Override
    public LiquidStack drain(int maxDrain, boolean doDrain)
    {
        if(doDrain)
        {
            liquid.amount -= maxDrain;
            if(liquid.amount < 0)
            {
                LiquidStack out = new LiquidStack(liquid.itemID, -liquid.amount);
                liquid.amount = 0;
                return out;
            }
            return new LiquidStack(liquid.itemID, maxDrain);
        }
        return null;
    }
    
    @Override
    public int getTankPressure()
    {
        return 0;
    }
    
    
    //IInventory
    
    
    @Override
    public int getSizeInventory()
    {
        return contents.length;
    }
    
    @Override
    public ItemStack getStackInSlot(int i)
    {
        if(i >= 0 && i < contents.length)
            return contents[i];
        return null;
    }
    
    @Override
    public ItemStack decrStackSize(int i, int j)
    {
        if(i >= 0 && i < contents.length)
        {
            if(contents[i].stackSize > j)
            {
                contents[i].stackSize -= j;
                return new ItemStack(contents[i].itemID,j,contents[i].getItemDamage());
            }
            ItemStack out = contents[i];
            contents[i] = null;
            return out;
        }
        return null;
    }
    
    @Override
    public ItemStack getStackInSlotOnClosing(int i)
    {
        return null;
    }
    
    @Override
    public void setInventorySlotContents(int i, ItemStack itemstack)
    {
        contents[i] = itemstack;
    }
    
    @Override
    public String getInvName()
    {
        return "Soul Crystaliser";
    }
    
    @Override
    public boolean isInvNameLocalized()
    {
        return true; //should change when implementing localisation stuff.
    }
    
    @Override
    public int getInventoryStackLimit()
    {
        return 64;
    }
    
    @Override
    public boolean isUseableByPlayer(EntityPlayer entityplayer)
    {
        return true;
    }
    
    @Override
    public void openChest()
    {
        
    }
    
    @Override
    public void closeChest()
    {
        
    }
    
    @Override
    public boolean isStackValidForSlot(int i, ItemStack itemstack)
    {
        return true;
    }
    
}

Link to post
Share on other sites

You also need the NBT read/write functions. Actually, I think that is at the root of the problem.

 

I just added them, but am I mistaken to think the NBT stuff is for storing and loading the tile entity's inventory?  We're only dealing with player inventory here; the tile entity doesn't have an inventory (well, now it might, with the NBT stuff added).  New code here, though the problem is unaffected:

 

package x.thealphaelement.tileentity;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.StringTranslate;

public class TileEntityMerchantBlock extends TileEntity implements IInventory {

private ItemStack[] inventory = new ItemStack[8];
private boolean hasItem = false;

public TileEntityMerchantBlock() {

}

public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer)
{
         if (worldObj.getBlockTileEntity(xCoord, yCoord, zCoord) != this)
         {
                 return false;
         }

         return par1EntityPlayer.getDistanceSq((double)xCoord + 0.5D, (double)yCoord + 0.5D, (double)zCoord + 0.5D) <= 64D;
}

@Override
public int getSizeInventory(){
	return this.inventory.length;
}

@Override
public ItemStack getStackInSlot(int index){
	return this.inventory[index];
}

@Override
public ItemStack decrStackSize(int slot, int num){
	if(this.inventory[slot]!=null){
		ItemStack stack;
		if(this.inventory[slot].stackSize<=num){
			stack = this.inventory[slot];
			this.inventory[slot] = null;
			return stack;
		}else{
			stack = this.inventory[slot].splitStack(num);
			if(this.inventory[slot].stackSize==0){
				this.inventory[slot] = null;
			}
			return stack;
		}
	}else return null;
}

@Override
public ItemStack getStackInSlotOnClosing(int index){
	if(this.inventory[index]!=null){
		ItemStack var2 = this.inventory[index];
		this.inventory[index] = null;
		return var2;
	}else return null;
}

@Override
public void setInventorySlotContents(int index, ItemStack stack){
	this.inventory[index] = stack;
	if(stack!=null&&stack.stackSize>this.getInventoryStackLimit()){
		stack.stackSize = this.getInventoryStackLimit();
	}
}

@Override
public String getInvName(){
	return StringTranslate.getInstance().translateKey("merchantBlock.name");
}

@Override
public boolean isInvNameLocalized(){
	return true;
}

@Override
public int getInventoryStackLimit(){
	return 64;
}

@Override
public void openChest() {
	// TODO Auto-generated method stub

}

@Override
public void closeChest() {
	// TODO Auto-generated method stub

}

@Override
public boolean isStackValidForSlot(int i, ItemStack itemstack) {
	// TODO Auto-generated method stub
	return true;
}

@Override
public void writeToNBT(NBTTagCompound tagCompound){
	super.writeToNBT(tagCompound);
	NBTTagList tagList = new NBTTagList();
	for(int i = 0; i<this.inventory.length; ++i){
		if(this.inventory[i]!=null){
			NBTTagCompound ntc3 = new NBTTagCompound();
			ntc3.setByte("slot",(byte) i);
			this.inventory[i].writeToNBT(ntc3);
			tagList.appendTag(ntc3);
		}
	}
	tagCompound.setTag("items",tagList);
}

@Override
public void readFromNBT(NBTTagCompound tagCompound){
	super.readFromNBT(tagCompound);
	NBTTagList var2 = tagCompound.getTagList("items");
	for(int i = 0; i<var2.tagCount(); ++i){
		NBTTagCompound ntc3 = (NBTTagCompound) var2.tagAt(i);
		byte slot = ntc3.getByte("slot");
		if(slot>=0&&slot<this.inventory.length){
			this.inventory[slot] = ItemStack.loadItemStackFromNBT(ntc3);
		}
	}
}



}

Link to post
Share on other sites

You also need the NBT read/write functions. Actually, I think that is at the root of the problem.

 

I just added them, but am I mistaken to think the NBT stuff is for storing and loading the tile entity's inventory?  We're only dealing with player inventory here; the tile entity doesn't have an inventory (well, now it might, with the NBT stuff added).  New code here, though the problem is unaffected:

-snip-

*impersonates Dirk Gently*

"I believe in the fundamental interconnectedness of all things."

 

...Actually, I'm just trying various things and hoping something works. I can't find anything wrong.

BEWARE OF GOD

---

Co-author of Pentachoron Labs' SBFP Tech.

Link to post
Share on other sites

You also need the NBT read/write functions. Actually, I think that is at the root of the problem.

 

I just added them, but am I mistaken to think the NBT stuff is for storing and loading the tile entity's inventory?  We're only dealing with player inventory here; the tile entity doesn't have an inventory (well, now it might, with the NBT stuff added).  New code here, though the problem is unaffected:

-snip-

*impersonates Dirk Gently*

"I believe in the fundamental interconnectedness of all things."

 

...Actually, I'm just trying various things and hoping something works. I can't find anything wrong.

 

Hahaha alright then.  Well, at least I know it is most likely that my logic isn't flawed, and the issue probably has something more to do with Minecraft or Forge.

 

I really do appreciate you at least taking a look.

 

A bit more info that has come to light: it seems that when I click an item in the inventory, the item that gets picked up is the one from the slot above it.  I've run the process in a verbose manner, echoing the id's of the slots, and they seem to be placed in the correct order, but maybe this symptom of the problem tells of something you might know more about than a new modder does?

Link to post
Share on other sites

I had realised much the same thing, except adding additional slots *before* the inventory results in offsetting the slot taken from, (see my post here which goes into a bit more detail about it and some other odd behaviour.)

Link to post
Share on other sites

I had realised much the same thing, except adding additional slots *before* the inventory results in offsetting the slot taken from, (see my post here which goes into a bit more detail about it and some other odd behaviour.)

 

Yeah I'm following your post and reading your updates.  Thanks for posting here to let me know in case I wasn't, though.  :)  Here's something I just tried, and it's produced some interesting information.  In your Container class, try adding this method:

 

public ItemStack slotClick(int par1, int par2, int par3, EntityPlayer par4EntityPlayer) {
	par4EntityPlayer.addChatMessage("clicky " + par1 + " " + par2 + " " + par3);
	super.slotClick(par1, par2, par3, par4EntityPlayer);
	return new ItemStack(Item.wheat);
}

 

The wheat is just a placeholder ItemStack to satisfy the return requirement.  What this does is override (but still activate, because of the super method call) the slotClick method, and it outputs the parameters the slotClick method is using to the player's chat screen (though you could use System.out.println() instead of player.addChatMessage() to have the echo go only to the console if you wanted).

 

I'm finding the only thing that changes is the first int, par1 (everything else is 0's; I'm not sure if that should concern me yet).  But the result is what interests me; the par1 is always a number that's equal to the slot it should be clicking on, plus 9 (meaning the method always tries to use the slot directly above the slot actually clicked).

 

I'm trying to find out why the method is identifying each slot the way it is.

Link to post
Share on other sites

I just updated my latest post in the other thread, it appears that (with my mod at least) the server thinks that the player has their regular inventory open while the client thinks that the tile inventory is open. (which explains all of these oddities, since the player inventory has nine additional slots, 4 armour, 4 crafting, and the crafting output, and adding more slots in the custom container class will move the slots that the client closer to those the server uses)

 

As such; I guess there must be something we are both missing for the opening of the GUI.

 

EDIT: here is the code used for opening the GUI for me:

@Override
    public boolean onBlockActivated(World world, int i, int j, int k, EntityPlayer player, int a, float b, float c, float d)
    {
        TileEntity tileEntity = world.getBlockTileEntity(i, j, k);
        if (tileEntity == null || player.isSneaking()) 
        {
            return false;
        }
        player.openGui(Alchemagic.instance, 0, world, i, j, k);
        return true;
    }

Link to post
Share on other sites

I decided to use a few break points to see what actually happens when I open the gui, and I found that it wasn't opening the gui handler server-side because my @Mod file didn't have an @NetworkMod annotation, simply adding @NetworkMod after the @Mod annotation and it's parameters seems to have fixed it for me.

Link to post
Share on other sites

You also need the NBT read/write functions. Actually, I think that is at the root of the problem.

 

I just added them, but am I mistaken to think the NBT stuff is for storing and loading the tile entity's inventory?  We're only dealing with player inventory here; the tile entity doesn't have an inventory (well, now it might, with the NBT stuff added).  New code here, though the problem is unaffected:

-snip-

*impersonates Dirk Gently*

"I believe in the fundamental interconnectedness of all things."

 

...Actually, I'm just trying various things and hoping something works. I can't find anything wrong.

 

Hahaha alright then.  Well, at least I know it is most likely that my logic isn't flawed, and the issue probably has something more to do with Minecraft or Forge.

 

I really do appreciate you at least taking a look.

 

A bit more info that has come to light: it seems that when I click an item in the inventory, the item that gets picked up is the one from the slot above it.  I've run the process in a verbose manner, echoing the id's of the slots, and they seem to be placed in the correct order, but maybe this symptom of the problem tells of something you might know more about than a new modder does?

To be quite frank, I think it's more likely that you have a small typo somewhere; after all, I have a TE that works just fine. Maybe I can try doing an exhaustive compare... if I find the time.

BEWARE OF GOD

---

Co-author of Pentachoron Labs' SBFP Tech.

Link to post
Share on other sites

Alright, finally got it.  My CommonProxy class didn't have container information in it.  I added this to my CommonProxy class:

 

@Override
	public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
		TileEntity tileEntity = world.getBlockTileEntity(x, y, z);
		if (tileEntity != null) {
			switch(ID) {
				case 0: return new ContainerMerchantBlock(player.inventory, (TileEntityMerchantBlock)tileEntity); // your Containers go here
			}
		}
		return null;
	}

 

I was mistakenly under the impression that a "server GUI element" (as in the method's name) wouldn't be needed for what I was trying to do, as the block was only supposed to display the player's inventory, and thus wouldn't need any inventory information from the server.  I therefore omitted this code.

 

It was only after hours of tracking through Minecraft's code and adding verbosity through System.out.println() at key points was I able to discover that, when opening a normal chest or furnace, or anything of the sort, Minecraft was referring to the container by its container class name (so, something like ContainerChest or ContainerFurnace), but when activating my MerchantBlock the container object that Minecraft referenced was "ContainerPlayer", which is the same container used when a player opens their inventory normally.

 

So my block was actually trying to manipulate the player's inventory via what Minecraft thought was the player's normal inventory window (which has additional slots), and the slots my ContainerMerchantBlock class were using, were, of course, mismatched to that of the player's inventory window.

 

Once I discovered this, it still took me quite some time searching through the code and adding verbosity to realize I had to tell the server what container to use by adding the above code to the CommonProxy class.

 

Thanks a ton Quarg, Newt, and Dark for your replies!  This has been quite a learning experience.

Link to post
Share on other sites

Alright, finally got it.  My CommonProxy class didn't have container information in it.  I added this to my CommonProxy class:

 

@Override
	public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
		TileEntity tileEntity = world.getBlockTileEntity(x, y, z);
		if (tileEntity != null) {
			switch(ID) {
				case 0: return new ContainerMerchantBlock(player.inventory, (TileEntityMerchantBlock)tileEntity); // your Containers go here
			}
		}
		return null;
	}

 

I was mistakenly under the impression that a "server GUI element" (as in the method's name) wouldn't be needed for what I was trying to do, as the block was only supposed to display the player's inventory, and thus wouldn't need any inventory information from the server.  I therefore omitted this code.

 

It was only after hours of tracking through Minecraft's code and adding verbosity through System.out.println() at key points was I able to discover that, when opening a normal chest or furnace, or anything of the sort, Minecraft was referring to the container by its container class name (so, something like ContainerChest or ContainerFurnace), but when activating my MerchantBlock the container object that Minecraft referenced was "ContainerPlayer", which is the same container used when a player opens their inventory normally.

 

So my block was actually trying to manipulate the player's inventory via what Minecraft thought was the player's normal inventory window (which has additional slots), and the slots my ContainerMerchantBlock class were using, were, of course, mismatched to that of the player's inventory window.

 

Once I discovered this, it still took me quite some time searching through the code and adding verbosity to realize I had to tell the server what container to use by adding the above code to the CommonProxy class.

 

Thanks a ton Quarg, Newt, and Dark for your replies!  This has been quite a learning experience.

This is what programming is all about :)

 

I feel stupid to have missed that, though. I should have noticed that you were missing a common proxy function.

BEWARE OF GOD

---

Co-author of Pentachoron Labs' SBFP Tech.

Link to post
Share on other sites

Thank you Community, I finally have my inventory working correctly, I had looked everywhere about what was wrong with my container, tileentity and my GUI bit I couldn't find anything that related to/fixed my issue. 

 

It wasn't until I got to this thread when someone mentioned that @NetworkMod was missing from their base mod class.  I added that and boom, all working. (I am sure I had that at some stage)

 

Again I would like to say thanks and love this community and love Open source. (will publish my code to github when closer to public release.)

Neoublie

Author of Codename: Project Shadow

 

if you do models and textures pm me. looking for some assistance.

Link to post
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.

Guest
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.



  • Recently Browsing

    No registered users viewing this page.

  • Posts

    • I fixed the problem! It was just a simple mod that I added that was 1.12 and not 1.16 lol, I removed it and now its working like a charm. Thanks for the help btw!
    • I need to trigger a player's attack action. I copied the net.minecraft.client.Minecraft.clickMouse() method from the sources and changed it a bit, removing everything about the leftClickCounter private property:   public static void callAttackAction() { Minecraft instance = Minecraft.getMinecraft(); if (!instance.player.isRowingBoat()) { switch (instance.objectMouseOver.typeOfHit) { case ENTITY: if (instance.objectMouseOver.entityHit != null && instance.playerController != null) { try { instance.playerController.attackEntity(instance.player, instance.objectMouseOver.entityHit); } catch (Exception e) { e.printStackTrace(); } } break; case BLOCK: BlockPos blockpos = instance.objectMouseOver.getBlockPos(); if (!instance.world.isAirBlock(blockpos)) { instance.playerController.clickBlock(blockpos, instance.objectMouseOver.sideHit); break; } case MISS: instance.player.resetCooldown(); net.minecraftforge.common.ForgeHooks.onEmptyLeftClick(instance.player); } instance.player.swingArm(EnumHand.MAIN_HAND); } } It works, but sometimes times this error occurs on line 168 in the attackEntity method: [Netty Client IO #1/ERROR] [FML]: NetworkDispatcher exception io.netty.handler.codec.EncoderException: java.lang.NullPointerException at io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:125) ~[MessageToByteEncoder.class:4.1.9.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:738) ~[AbstractChannelHandlerContext.class:4.1.9.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:730) ~[AbstractChannelHandlerContext.class:4.1.9.Final] at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:816) ~[AbstractChannelHandlerContext.class:4.1.9.Final] at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:723) ~[AbstractChannelHandlerContext.class:4.1.9.Final] at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.write(NetworkDispatcher.java:548) ~[NetworkDispatcher.class:?] at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:738) ~[AbstractChannelHandlerContext.class:4.1.9.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:801) ~[AbstractChannelHandlerContext.class:4.1.9.Final] at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:814) ~[AbstractChannelHandlerContext.class:4.1.9.Final] at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:794) ~[AbstractChannelHandlerContext.class:4.1.9.Final] at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:831) ~[AbstractChannelHandlerContext.class:4.1.9.Final] at io.netty.channel.DefaultChannelPipeline.writeAndFlush(DefaultChannelPipeline.java:1032) ~[DefaultChannelPipeline.class:4.1.9.Final] at io.netty.channel.AbstractChannel.writeAndFlush(AbstractChannel.java:296) ~[AbstractChannel.class:4.1.9.Final] at net.minecraft.network.NetworkManager$4.run(NetworkManager.java:245) [NetworkManager$4.class:?] at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) [AbstractEventExecutor.class:4.1.9.Final] at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:403) [SingleThreadEventExecutor.class:4.1.9.Final] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:442) [NioEventLoop.class:4.1.9.Final] at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858) [SingleThreadEventExecutor$5.class:4.1.9.Final] at java.lang.Thread.run(Thread.java:748) [?:1.8.0_281] Caused by: java.lang.NullPointerException at net.minecraft.network.play.client.CPacketPlayerDigging.writePacketData(CPacketPlayerDigging.java:41) ~[CPacketPlayerDigging.class:?] at net.minecraft.network.NettyPacketEncoder.encode(NettyPacketEncoder.java:51) ~[NettyPacketEncoder.class:?] at net.minecraft.network.NettyPacketEncoder.encode(NettyPacketEncoder.java:12) ~[NettyPacketEncoder.class:?] at io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:107) ~[MessageToByteEncoder.class:4.1.9.Final] How can I fix it?
    • I just realized you are using a non-supported version of Forge based on the parameters of the render method as they are pre-1.15. The only versions supported are those in the blue banner at the top of the screen. Please update to one of the above versions to receive more support.
    • Should be able to search for class names or find a type hierarchy for MonsterEntity. I don't use IntelliJ so I'm not familiar with the keybinds.
  • Topics

  • Who's Online (See full list)

×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.