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.


  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • I have setup a 1.12.2 forge server  occasionally it throws a '[Server thread/WARN] [minecraft/MinecraftServer]: Can't keep up! Did the system time change, or is the server overloaded? Running 2316ms behind, skipping 46 tick(s)' and a ram usage spike  I have 32gb of ram installed in my pc and on a vanilla server l would normally just make a run.bat file but it is not working   When I launch the run.bat C:\Users\Max\Desktop\1.12.2 server>java -Xmx4G -Xms4G -jar minecraft_server.1.12.2.jar nogui C:\Users\Max\Desktop\1.12.2 server>PAUSE Press any key to continue . . .   The run.bat file contains java -Xmx4G -Xms4G -jar minecraft_server.1.12.2.jar nogui PAUSE Any advice would be appreciated
    • I'm opening the forge 1.8.9 installer properly I click install with the client option selected, it says it installs properly but when I go into my files and also when I go into the minecraft launcher, it's just not there.  JVM info: Oracle Corporation - 1.8.0_431 - 25.431-b10 java.net.preferIPv4Stack=true Found java version 1.8.0_431 Considering minecraft client jar Considering library net.minecraftforge:forge:1.8.9-11.15.1.2318-1.8.9: Not Downloading {Wrong Side} Considering library net.minecraft:launchwrapper:1.12: Not Downloading {Wrong Side} Considering library org.ow2.asm:asm-all:5.0.3: Not Downloading {Wrong Side} Considering library jline:jline:2.13: Not Downloading {Wrong Side} Considering library com.typesafe.akka:akka-actor_2.11:2.3.3 Considering library com.typesafe:config:1.2.1 Considering library org.scala-lang:scala-actors-migration_2.11:1.1.0 Considering library org.scala-lang:scala-compiler:2.11.1 Considering library org.scala-lang.plugins:scala-continuations-library_2.11:1.0.2 Considering library org.scala-lang.plugins:scala-continuations-plugin_2.11.1:1.0.2 Considering library org.scala-lang:scala-library:2.11.1 Considering library org.scala-lang:scala-parser-combinators_2.11:1.0.1 Considering library org.scala-lang:scala-reflect:2.11.1 Considering library org.scala-lang:scala-swing_2.11:1.0.1 Considering library org.scala-lang:scala-xml_2.11:1.0.2 Considering library lzma:lzma:0.0.1: Not Downloading {Wrong Side} Considering library net.sf.jopt-simple:jopt-simple:4.6: Not Downloading {Wrong Side} Considering library java3d:vecmath:1.5.2 Considering library net.sf.trove4j:trove4j:3.0.3 Extracting: /forge-1.8.9-11.15.1.2318-1.8.9-universal.jar To: C:\Users\Ian\AppData\Roaming\.minecraft\libraries\net\minecraftforge\forge\1.8.9-11.15.1.2318-1.8.9\forge-1.8.9-11.15.1.2318-1.8.9.jar That's the installer log and I have no idea if anything is wrong.
    • https://mclo.gs/NQ786zI   I don’t understand what I need to do.
    • I am wanting to give the armour in my mod special properties, but I have no idea how to do so.   For the first armour set I want it to be the case that when the full set is worn it has the properties of a carved pumpkin, making it so you won't aggravate endermen when you look at them.    The second, and presumably harder property is that for the second set I would like it to be the case that when the full set is worn, you can walk over the void without falling. (I was considering using the levitation to accomplish this but I wanted to check beforehand).   Would both of these specialities be achievable for each armour set and how exactly would they both be done? Help would be much appreciated. 
    • I finally got my Forge server up and running thanks to the help of the people on this forum and played fine for a day. Now since I started playing today, the server runs for 20-30 minutes then freezes and kicks everyone out but stays up and running but won't let anyone connect. Here is the latest debug log and crashlog from the server. Thank you for reading & helping   https://gist.github.com/Dwolfwoood/d0410e581c86772694f1d8007431c409   https://gist.github.com/Dwolfwoood/b5d521fd071dbfcc816949924757fef9
  • Topics

×
×
  • Create New...

Important Information

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