Jump to content

Entity NBT Data Problem


WeaselNinja

Recommended Posts

I'm making a mod that replaces the standard villager mob with one that allows the player to give/take items to/from villagers. So far the player can give a villager an item and it will render in it's hands. The problem comes when you give a villager an item and log out. When you log back in the item will still be in the villager's inventory (since you can still take the item from it) but it will not render in it's hands. I think it might be a client/server issue and I've tried using packets but nothing seems to work. Here are the affected classes:

 

EntityBaseVillager class:

public class EntityBaseVillager extends EntityVillager{

//Global Variable Declarations
private int profession;
public InventoryVillager inventory;

public EntityBaseVillager(){
	super(null);
}//end default constructor

public EntityBaseVillager(World world){
	super(world);
	profession = 0;	
	inventory = new InventoryVillager(this);
}//end constructor

        @Override
public boolean interact(EntityPlayer player){

	//Local Variable Declarations
	ItemStack itemStack = player.inventory.getCurrentItem();
	int profID;
	boolean takeItemFlag = true;

	if(itemStack != null){
		if (itemStack.getItem().itemID == Item.emerald.itemID && getRecipes(player) != null){
			super.interact(player);
		}else if(itemStack.getItem() instanceof ItemPickaxe){
			profID = 1;
		}else if(itemStack.getItem() instanceof ItemAxe){
			profID = 2;
		}else if(itemStack.getItem() instanceof ItemHoe){
			profID = 3;
		}else if(itemStack.getItem() instanceof ItemSpade){
			profID = 4;
		}else if(itemStack.getItem() instanceof ItemShears){
			profID = 5;
		}else if(itemStack.getItem().itemID == Block.enchantmentTable.blockID){
			profID = 6;
		}else if(itemStack.getItem().itemID == Item.compass.itemID){		
			profID = 7;
		}else if(itemStack.getItem() instanceof ItemAnvilBlock){
			profID = 8;
		}else if(itemStack.getItem() instanceof ItemSword){
			profID = 9;
		}else if (itemStack.getItem() instanceof ItemBow){
			profID = 10;
		}else if(itemStack.getItem().itemID == Item.brewingStand.itemID){	
			profID = 11;
		}else if(itemStack.getItem().itemID == Item.fishingRod.itemID){ 	
			profID = 12;
		}else if(itemStack.getItem().itemID == Item.pocketSundial.itemID){	
			profID = 13;
		}else{
			takeItemFlag = false;
		}//end if-else

		if(takeItemFlag){
			takeItemFromPlayer(player);
		}//end if

	}else{
		giveItemToPlayer(player);
	}//end if-else

	return false;
}//end interact method

        public void takeItemFromPlayer(EntityPlayer player){

	inventory.setHeldItem(player.inventory.getCurrentItem());
	player.destroyCurrentEquippedItem();

}//end takeItemFromPlayer method

public void giveItemToPlayer(EntityPlayer player){
	if(inventory.getHeldItem() != null){
		player.inventory.addItemStackToInventory(inventory.getHeldItem());
		inventory.setHeldItem(null);
	}//end if
}//end giveItemToPlayer method

@Override
public ItemStack getHeldItem(){
	return inventory.getHeldItem();
}//end getHeldItems method

@Override
public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound){
	super.writeEntityToNBT(par1NBTTagCompound);
	par1NBTTagCompound.setTag("Inventory", this.inventory.writeToNBT(new NBTTagList()));
}//end writeEntityToNBT method

@Override
public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound){
	super.readEntityFromNBT(par1NBTTagCompound);
	NBTTagList nbttaglist = par1NBTTagCompound.getTagList("Inventory");
        this.inventory.readFromNBT(nbttaglist);
}//end readEntityFromNBT
}//end EntityBaseVillager

 

InventoryVillager class:

public class InventoryVillager implements IInventory, Serializable{

//Global Variable Declarations
private ItemStack[] mainInventory;	//[0] is held item, last 4 are armor
private ItemStack[] armorInventory;
String inventoryTitle;
public EntityBaseVillager owner;

InventoryVillager(EntityBaseVillager villager){
//	inventoryTitle = title;
	mainInventory = new ItemStack[getSizeInventory()];
	armorInventory = new ItemStack[4];
	owner = villager;
}//end constructor

@Override
public int getSizeInventory(){
        return 32;
    }//end getSizeInventory method

@Override
public void onInventoryChanged(){
	if (!owner.worldObj.isRemote){
		PacketDispatcher.sendPacketToAllPlayers(PacketCreator.createInventoryPacket(owner.entityId, this));
	}//end while loop

        }//end onInventoryChanged method

    public ItemStack getHeldItem(){
    	return mainInventory[0];
    }//end getHeldItem
    
    public void setHeldItem(ItemStack itemStack){
    	mainInventory[0] = itemStack;
    	onInventoryChanged();
    }//end setHeldItem
    
    public NBTTagList writeToNBT(NBTTagList par1NBTTagList){
    	//Write Held Item to NBT
    	if(this.mainInventory[0] != null){
    		NBTTagCompound nbttagcompound = new NBTTagCompound();
            nbttagcompound.setByte("Slot", (byte)0);
            this.mainInventory[0].writeToNBT(nbttagcompound);
            par1NBTTagList.appendTag(nbttagcompound);
    	}//end if
    	
    	return par1NBTTagList;
    	
}//end writeInventoryToNBT
    
    public void readFromNBT(NBTTagList par1NBTTagList){
    	//Read Held Item from NBT
    	if(par1NBTTagList.tagCount() > 0){
    		NBTTagCompound nbttagcompound = (NBTTagCompound)par1NBTTagList.tagAt(0);
        	ItemStack itemstack = ItemStack.loadItemStackFromNBT(nbttagcompound);
            setHeldItem(itemstack);
    	}//end if
    	
}//end readInventoryFromNBT
    
    private void writeObject(ObjectOutputStream out) throws IOException{
    	
	for (int i = 0; i < getSizeInventory(); i++){
		try{
			ItemStack stack = mainInventory[i];
			out.writeObject(i + ":" + stack.itemID + ":" + stack.stackSize + ":" + stack.getItemDamage());
		}catch (NullPointerException e){
			out.writeObject(i + ":" + "null");
		}catch (ArrayIndexOutOfBoundsException e){
			out.writeObject(i + ":" + "null");
		}//end try-catch
	}//end for loop
}//end writeObject method

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
	mainInventory = new ItemStack[getSizeInventory()];
	armorInventory = new ItemStack[4];

	for (int i = 0; i < getSizeInventory(); i++){
		String data = in.readObject().toString();

		if (data.contains("null")){
			mainInventory[i] = null;
		}else{
			int itemID = Integer.parseInt(data.split(":")[1]);
			int stackSize = Integer.parseInt(data.split(":")[2]);
			int damage = Integer.parseInt(data.split(":")[3]);

			ItemStack inventoryStack = new ItemStack(itemID, stackSize, damage);
			mainInventory[i] = inventoryStack;
		}//end if-else
	}//end for loop
}//end readObject method

}//end InventoryVillager class

 

PacketHandler class:

public class PacketHandler implements IPacketHandler{

@Override
public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player senderPlayer){

	try
	{
		if (packet.channel.equals("HV_INVENTORY")){
			System.out.println("Packet Recieved");
			handleInventory(packet, senderPlayer);
		}//end if
	}catch(Throwable e){
		e.printStackTrace();
            return;
	}//end try-catch

}//end onPacketData method

private void handleInventory(Packet250CustomPayload packet, Player senderPlayer) throws NumberFormatException, IOException, ClassNotFoundException{
	byte[] data = packet.data;

	ByteArrayInputStream byteInput = new ByteArrayInputStream(data);
	ObjectInputStream objectInput = new ObjectInputStream(byteInput);

	World world = ((EntityPlayer)senderPlayer).worldObj;

	//Assign received data.
	int entityId = objectInput.readInt();
	InventoryVillager inventory = (InventoryVillager)objectInput.readObject();
	objectInput.close();

	EntityBaseVillager entity = (EntityBaseVillager)world.getEntityByID(entityId);
	inventory.owner = entity;
	entity.inventory = inventory;
}//end handleInventory method

}//end PacketHandler class

 

PacketCreator class:

public final class PacketCreator {

public static Packet createInventoryPacket(int entityId, InventoryVillager inventory){

	try{
		Packet250CustomPayload thePacket = new Packet250CustomPayload();
		thePacket.channel = "HV_INVENTORY";

		ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
		ObjectOutputStream objectOutput = new ObjectOutputStream(byteOutput);
		objectOutput.writeInt(entityId);
		objectOutput.writeObject(inventory);
		objectOutput.close();

		thePacket.data = byteOutput.toByteArray();
		thePacket.length = thePacket.data.length;
		System.out.println("Packet Sent");
		return thePacket;
	}catch (Throwable e){
		return null;
	}//end try-catch
}//end createInventoryPacket method

}//end PacketCreator class

Link to comment
Share on other sites

UPDATE:

The problem was a packet was sent before the player logged into the world and therefore it was never received. I was able to fix it by inserting the code below into the EntityBaseVillager class. It seems like a sloppy fix to me though, let me know if any of you have a more elegant solution.

 

	@Override
public void onUpdate(){
	super.onUpdate();

	if(!this.worldObj.isRemote){
		inventory.syncInventory();
	}//end if

}//end onUpdate

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.

Announcements



×
×
  • Create New...

Important Information

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