Jump to content

[FIXED]Weird NPE on opening a Tile Entity GUI


vroominator

Recommended Posts

Hi guys, I've been getting a strange problem recently. If you've ever made a block with a Gui/TileEntity/Container before, you're probably familiar with addCraftingToCrafters(), which keeps the Tile Entity and the Container in sync. I'm having problems there. Everything works fine right up until I open the Gui. Then I crash with this error.

 

java.lang.NullPointerException
at net.minecraft.src.Slot.getStack(Slot.java:82)
at net.minecraft.src.Container.getInventory(Container.java:63)
at net.minecraft.src.Container.addCraftingToCrafters(Container.java:47)
at vroominator.sorcery.common.ContainerRuneCrafting.addCraftingToCrafters(ContainerRuneCrafting.java:55)
at cpw.mods.fml.common.network.NetworkRegistry.openRemoteGui(NetworkRegistry.java:315)
at cpw.mods.fml.common.network.FMLNetworkHandler.openGui(FMLNetworkHandler.java:337)
at net.minecraft.src.EntityPlayer.openGui(EntityPlayer.java:2051)
at vroominator.sorcery.common.blocks.BlockRuneCraftingTable.onBlockActivated(BlockRuneCraftingTable.java:106)
at net.minecraft.src.ItemInWorldManager.activateBlockOrUseItem(ItemInWorldManager.java:390)
at net.minecraft.src.NetServerHandler.handlePlace(NetServerHandler.java:536)
at net.minecraft.src.Packet15Place.processPacket(Packet15Place.java:78)
at net.minecraft.src.MemoryConnection.processReadPackets(MemoryConnection.java:78)
at net.minecraft.src.NetServerHandler.networkTick(NetServerHandler.java:80)
at net.minecraft.src.NetworkListenThread.networkTick(NetworkListenThread.java:55)
at net.minecraft.src.IntegratedServerListenThread.networkTick(IntegratedServerListenThread.java:111)
at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:649)
at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:564)
at net.minecraft.src.IntegratedServer.tick(IntegratedServer.java:110)
at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:470)
at net.minecraft.src.ThreadServerApplication.run(ThreadServerApplication.java:18)

 

I realise it's traced back to getStack() on Line 82 of slot, but I just do not know why. I've made blocks like this before, and never run into this error. Any help would be greatly appreciated.

If you need to see code, just ask.

Link to comment
Share on other sites

  • 2 weeks later...

Sorry for the bump, but I just cannot figure out what's going on here.

I figure that when a thread just gets ignored like this, it's one of 2 things:

A: You're absolutely stumped

B: I'm missing something painfully obvious

 

I highly doubt it's A, so could someone please tell me what I've done wrong?

 

Link to comment
Share on other sites

Alrighty. Prepare for some messy code.

 

ContainerRuneCrafting

package sorcery.common;

import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.asm.SideOnly;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import sorcery.common.core.Sorcery;

import net.minecraft.src.*;

public class ContainerRuneCrafting extends Container
{
    private TileEntityRuneCrafting tile;
    private World worldObj;
    private int posX;
    private int posY;
    private int posZ;
    private int lastCookTime;
    private int lastRuneCookTime;
    private int lastFuelCookTime;
    private int lastRune;

    public ContainerRuneCrafting(InventoryPlayer player, TileEntityRuneCrafting tile, World world, int i, int j, int k)
    {
        this.tile = tile;
        this.worldObj = world;
        this.posX = i;
        this.posY = j;
        this.posZ = k;
        this.addSlotToContainer(new Slot(tile, 0, 24, 35));
        this.addSlotToContainer(new Slot(tile, 1, 48, 35));
        this.addSlotToContainer(new SlotFurnace(player.player, tile, 2, 124, 35));
        int var3;

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

        for (var3 = 0; var3 < 9; ++var3)
        {
            this.addSlotToContainer(new Slot(player, var3, 8 + var3 * 18, 142));
        }
    }

    public void addCraftingToCrafters(ICrafting par1ICrafting)
    {
    	System.out.println(((EntityPlayer)par1ICrafting).getEntityName());
        super.addCraftingToCrafters(par1ICrafting); <<--This is where the problem starts
        par1ICrafting.updateCraftingInventoryInfo(this, 0, this.tile.currentCookTime);
        par1ICrafting.updateCraftingInventoryInfo(this, 1, this.tile.runeCookTime);
        par1ICrafting.updateCraftingInventoryInfo(this, 2, this.tile.fuelCookTime);
        par1ICrafting.updateCraftingInventoryInfo(this, 3, this.tile.currentRune);
    }

    /**
     * Updates crafting matrix; called from onCraftMatrixChanged. Args: none
     */
    public void updateCraftingResults()
    {
        super.updateCraftingResults();
        Iterator i = this.crafters.iterator();

        while (i.hasNext())
        {
            ICrafting crafter = (ICrafting)i.next();

            if (this.lastCookTime != this.tile.currentCookTime)
            {
                crafter.updateCraftingInventoryInfo(this, 0, this.tile.currentCookTime);
            }

            if (this.lastRuneCookTime != this.tile.runeCookTime)
            {
                crafter.updateCraftingInventoryInfo(this, 1, this.tile.runeCookTime);
            }
            
            if (this.lastFuelCookTime != this.tile.fuelCookTime)
            {
                crafter.updateCraftingInventoryInfo(this, 2, this.tile.fuelCookTime);
            }
            
            if (this.lastRune != this.tile.currentRune)
            {
                crafter.updateCraftingInventoryInfo(this, 3, this.tile.currentRune);
            }
        }

        this.lastCookTime = this.tile.currentCookTime;
        this.lastRuneCookTime = this.tile.runeCookTime;
        this.lastFuelCookTime = this.tile.fuelCookTime;
        this.lastRune = this.tile.currentRune;
    }

    @SideOnly(Side.CLIENT)
    public void updateProgressBar(int progress)
    {
            this.tile.currentCookTime = progress;
    }

    public boolean canInteractWith(EntityPlayer player)
    {
        return this.worldObj.getBlockId(this.posX, this.posY, this.posZ) != Sorcery.runeCraftingTable.blockID ? false : player.getDistanceSq((double)this.posX + 0.5D, (double)this.posY + 0.5D, (double)this.posZ + 0.5D) <= 64.0D;
    }
}

 

TileEntityRuneCrafting

package sorcery.common;

import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams;

import sorcery.common.blocks.BlockHellFurnace;
import sorcery.common.core.Sorcery;
import sorcery.common.core.TileEntityBasic;
import sorcery.common.lib.ItemStackHelper;
import sorcery.common.lib.RuneCraftingHelper;
import sorcery.common.recipes.ForgeRecipes;
import net.minecraft.src.*;
import net.minecraftforge.common.ISidedInventory;
import net.minecraftforge.common.ForgeDirection;
import cpw.mods.fml.common.registry.GameRegistry;

import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.asm.SideOnly;

public class TileEntityRuneCrafting extends TileEntityBasic implements IInventory, ISidedInventory
{
    public ItemStack[] inventory = new ItemStack[3];
    
    public int tier;
    
    public int currentCookTime = 0;

    public int runeCookTime = 0;
    
    public int fuelCookTime = 0;
    
    public int currentRune = 1;
    
    @Override
    public void handlePacket(NetworkManager network, Packet pack, String playerName) 
    {
    	ByteArrayDataInput data = ByteStreams.newDataInput(((Packet250CustomPayload)pack).data);
    	if(data.readInt() == 1)
    	{
    		++this.currentRune;
    	}
    	else if(data.readInt() == 2)
    	{
    		--this.currentRune;
    	}
    	
    }
    
    public TileEntityRuneCrafting(int tier)
    {
    	this.tier = tier;
    }

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

    public ItemStack getStackInSlot(int slot)
    {
        return this.inventory[slot];
    }

    public ItemStack decrStackSize(int slot, int size)
    {
        if (this.inventory[slot] != null)
        {
            ItemStack var3;

            if (this.inventory[slot].stackSize <= size)
            {
                var3 = this.inventory[slot];
                this.inventory[slot] = null;
                return var3;
            }
            else
            {
                var3 = this.inventory[slot].splitStack(size);

                if (this.inventory[slot].stackSize == 0)
                {
                    this.inventory[slot] = null;
                }

                return var3;
            }
        }
        else
        {
            return null;
        }
    }

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

    public void setInventorySlotContents(int slot, ItemStack item)
    {
        this.inventory[slot] = item;

        if (item != null && item.stackSize > this.getInventoryStackLimit())
        {
            item.stackSize = this.getInventoryStackLimit();
        }
    }

    public String getInvName()
    {
        return "container.runecrafting";
    }

    public void readFromNBT(NBTTagCompound tag)
    {
        super.readFromNBT(tag);
        NBTTagList var2 = tag.getTagList("Items");
        this.inventory = new ItemStack[this.getSizeInventory()];

        for (int var3 = 0; var3 < var2.tagCount(); ++var3)
        {
            NBTTagCompound var4 = (NBTTagCompound)var2.tagAt(var3);
            byte var5 = var4.getByte("Slot");

            if (var5 >= 0 && var5 < this.inventory.length)
            {
                this.inventory[var5] = ItemStack.loadItemStackFromNBT(var4);
            }
        }

        this.currentCookTime = tag.getShort("CookTime");
        this.runeCookTime = tag.getInteger("RuneCookTime");
        this.fuelCookTime = tag.getInteger("FuelCookTime");
        this.currentRune = tag.getInteger("CurrentRune");
    }

    public void writeToNBT(NBTTagCompound tag)
    {
        super.writeToNBT(tag);
        tag.setShort("CookTime", (short)this.currentCookTime);
        tag.setInteger("RuneCookTime", this.runeCookTime);
        tag.setInteger("FuelCookTime", this.fuelCookTime);
        tag.setInteger("CurrentRune", this.currentRune);
        NBTTagList var2 = new NBTTagList();

        for (int var3 = 0; var3 < this.inventory.length; ++var3)
        {
            if (this.inventory[var3] != null)
            {
                NBTTagCompound var4 = new NBTTagCompound();
                var4.setByte("Slot", (byte)var3);
                this.inventory[var3].writeToNBT(var4);
                var2.appendTag(var4);
            }
        }

        tag.setTag("Items", var2);
    }

    public int getInventoryStackLimit()
    {
        return 64;
    }
    
    public int getCurrentItemCookTime()
    {
    	if(this.inventory[1] != null && RuneCraftingHelper.getEnumFromMeta(this.inventory[1].getItemDamage()) != null)
    	{
    		System.out.println(((RuneCraftingHelper.EnumRuneTypes)RuneCraftingHelper.getEnumFromMeta(this.inventory[1].getItemDamage())).time);
    		return(((RuneCraftingHelper.EnumRuneTypes)RuneCraftingHelper.getEnumFromMeta(this.inventory[1].getItemDamage())).time);
    	}
    	return 0;
    }

    @SideOnly(Side.CLIENT)
    public int getCookProgressScaled(int scale)
    {
    	if(this.getCurrentItemCookTime() == 0)
    	{
    		return 0;
    	}
    	System.out.println(this.currentCookTime * scale / this.getCurrentItemCookTime());
        return this.currentCookTime * scale / this.getCurrentItemCookTime();
    }
    
    public boolean isCooking()
    {
    	return this.currentCookTime > 0;
    }
    
    public boolean hasFuel()
    {
    	return this.runeCookTime > 0;
    }
    
    @Override
    public void onInventoryChanged()
    {
    }

    public void updateEntity()
    {		
        if(this.fuelCookTime == 0 && this.isItemFuel(this.inventory[0]) > 0)
        {
        	this.fuelCookTime = this.isItemFuel(this.inventory[0]);
        	this.decrStackSize(0, 1);
        }
        
        if(this.canCook())
        {
        	++this.currentCookTime;
        	
        	if(this.currentCookTime == RuneCraftingHelper.getEnumFromMeta(this.currentRune).time)
        	{
        		this.smeltItem();
        		this.currentCookTime = 0;
        		this.runeCookTime -= RuneCraftingHelper.getEnumFromMeta(this.currentRune).fuelCost;
        		--this.inventory[1].stackSize; 
        	}
        }
    }

    private boolean canCook()
    {
        if(this.inventory[1] == null || this.fuelCookTime == 0 || this.inventory[2].stackSize == 64)
        {
            return false;
        }
        else if(ItemStackHelper.getInstance().areItemsEqual(this.inventory[1], new ItemStack(Sorcery.rune, 1, 0)))
        {
        	return true;
        }
        else if(ItemStackHelper.getInstance().areItemsEqual(this.inventory[2], new ItemStack(Sorcery.rune, 1, this.currentRune)) || this.inventory[2] == null)
        {
        	return true;
        }
        return false;
    }

    private int isItemFuel(ItemStack item)
    {
    	if(item == null)
    	{
    		return 0;
    	}
    	else
    	{
    		if(item.getItem() == Item.redstone)
    		{
    			return 10;
    		}
    		else if(item.getItem() == Item.lightStoneDust)
    		{
    			return 12;
    		}
    		else if(item.getItem() == Item.gunpowder)
    		{
    			return 14;
    		}
    		else if(item.getItem() == Sorcery.enderdust)
    		{
    			return 14;
    		}
    		else if(item.getItem() == Item.blazePowder)
    		{
    			return 18;
    		}
    		else if(item.getItem() == Sorcery.ectoplasm)
    		{
    			return 20;
    		}
    		else if(item.getItem() == Sorcery.magicDust)
    		{
    			return 30;
    		}
    	}
	return 0;
}

public void smeltItem()
    {
        if(this.canCook())
        {
        	ItemStack result = new ItemStack(Sorcery.rune, 1, this.currentRune);

        	if(this.inventory[2] == null)
        	{
        		this.inventory[2] = result;
        	}
        	else
        	{
        		++this.inventory[2].stackSize;
        	}
        }
    }

    public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer)
    {
        return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false : par1EntityPlayer.getDistanceSq((double)this.xCoord + 0.5D, (double)this.yCoord + 0.5D, (double)this.zCoord + 0.5D) <= 64.0D;
    }

    public boolean canGoUpRune()
    {
    	if(this.currentRune == 4 && this.tier == 0)
    	{
    		return false;
    	}
    	else if(this.currentRune == 9 && this.tier == 1)
    	{
    		return false;
    	}
    	else if(this.currentRune == 13 && this.tier == 2)
    	{
    		return false;
    	}
    	else if(this.currentRune == 15)
    	{
    		return false;
    	}
    	return true;
    }
    
    public boolean canGoDownRune()
    {
    	if(this.currentRune == 1)
    	{
    		return false;
    	}
    	return true;
    }
    
    public void openChest()
    {
    }

    public void closeChest()
    {
    }

    @Override
    public int getStartInventorySide(ForgeDirection side)
    {
        if (side == ForgeDirection.DOWN) return 1;
        if (side == ForgeDirection.UP) return 0; 
        return 2;
    }

    @Override
    public int getSizeInventorySide(ForgeDirection side)
    {
        return 1;
    }

    public Packet getDescriptionPacket()
    {
        NBTTagCompound tag = new NBTTagCompound();
        this.writeToNBT(tag);
        return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, 1, tag);
    }
    
    public void onDataPacket(NetworkManager manager, Packet132TileEntityData pack)
    {
    	this.readFromNBT(pack.customParam1);
    }
}

Link to comment
Share on other sites

First thing I would make sure is that the slotIndex is proper. It's not obvious how you have the slotIndex's right now and I can't guarantee they're returning the right number.Make sure you're getting the right slotIndex. If you're not, fix that. If it's not fixed after that, return here and read below.

 

I can't personally see exactly (possibly missing @Overrides?) what the issue is if not the above, but I would try the following:

 

You need to figure out what is null. The line in Slot.java:

 

this.inventory.getStackInSlot(this.slotIndex);

 

I would trace this and this.inventory. Figure out which of those is null.

 

If it is "this" that is null, one of your slots is returning true for hasNext() but is returning null for the actual slot.

If "inventory" is null (which I can't see why it would be) you need to properly set the Slots inventory to the TileEntityRuneCrafting.

If "inventory" and "this" aren't null then the TileEntityRunCrafting's inventory may be null. (judging from the constructor it's probably not this)

 

Once you know what is null just work backwards.

 

There's probably someone who can read this and tell you your issue, but this is all I can offer.

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.