Jump to content

Problems removing items from player's inventory


WildBamaBoy

Recommended Posts

I'm trying to remove one of whatever item the player is holding when they right click one of my entities. Everything works fine until you only have one of that item left, then, about 50% of the time, as soon as the item is removed it is placed back in your inventory. This item that is placed back in the inventory has a stackSize of 0, and crashes the game when you place it. It also causes items in the inventory to duplicate or disappear.

 

Here's various bits of code having to do with interaction with my entity. If I'm handling inventories completely wrong please correct me.

 

interact()

	if (itemStack != null)
	{
		//Only process gifts on the client.
		if (this.worldObj.isRemote)
		{
			doGift(itemStack);
		}
	}

                super.interact(player);

 

doGift()

        @SideOnly(Side.CLIENT)
protected void doGift(ItemStack itemStack)
{
	//Check the acceptable gifts for the item stack's item ID.
	if (DataStore.acceptableGifts.containsKey(itemStack.itemID))
	{
		int heartIncrease = DataStore.acceptableGifts.get(itemStack.itemID);
		hearts += heartIncrease;
		PacketDispatcher.sendPacketToServer(PacketCreator.createFieldValuePacket(entityId, "hearts", hearts));
		removeItemFromPlayer(itemStack);

		//Say the appropriate phrase based on hearts increase.
		if (heartIncrease <= 5)
		{
			say(Localization.getString(this, "gift.small"));
		}

		else if (heartIncrease > 5 && heartIncrease < 10)
		{
			say(Localization.getString(this, "gift.regular"));
		}

		else
		{
			say(Localization.getString(this, "gift.great"));
		}
	}

	//The gift wasn't contained in the acceptable gifts map.
	else
	{
		hearts -= new Random().nextInt(9) + 5;
		say(Localization.getString(this, "gift.bad"));
	}
}

 

removeItemFromPlayer()

public static void removeItemFromPlayer(ItemStack itemStack)
{
	EntityPlayer player = Minecraft.getMinecraft().thePlayer;
	itemStack.stackSize--;

	if (itemStack.stackSize <= 0)
	{
		player.inventory.setInventorySlotContents(player.inventory.currentItem, (ItemStack)null);
	}

	MCA.instance.syncPlayerInventory(player);
}

 

syncPlayerInventory()

public void syncPlayerInventory(EntityPlayer player)
{
	if (FMLCommonHandler.instance().getEffectiveSide() == Side.CLIENT)
	{
		EntityPlayer playerOnClient = player;
		EntityPlayer playerOnServer = (EntityPlayer) getServerSideEntity(player);

		playerOnServer.inventory = playerOnClient.inventory;
	}

	else
	{
		EntityPlayer playerOnServer = player;
		EntityPlayer playerOnClient = (EntityPlayer) getClientSideEntity(player);

		playerOnClient.inventory = playerOnServer.inventory;
	}
}

Link to comment
Share on other sites

I admit that I don't have that much experience with minecraft MP modding, but your insistence of modifying certain values the server should know about client-side only worries me.  There are few occasions where doing something serverside but not clientside can go wrong (because the server can update the client about changes), but many where doing something clientside but not serverside can (because the server, IIRC, overrides the client if entity location, block ID at location, etc. differ from one to the other).

 

Some combing of minecraft's ItemStack.java class makes me wonder if the entire removeItemFromPlayer method isn't redundant, and is actually the cause of the problem -- ItemStack's damageItem does something similar (make an itemstack null), but in a slightly different manner.  I suggest you check it out.

Link to comment
Share on other sites

Where the client changes a value, I send a "fieldValue" packet to the server, which assigns that field's value to the server-side entity.

 

As in:

		hearts += heartIncrease;
		PacketDispatcher.sendPacketToServer(PacketCreator.createFieldValuePacket(entityId, "hearts", hearts));

 

I played around with removeItemFromPlayer without any real progress, so I tried throwing out some more packets when the player's inventory changed. I believe I may have found a solution, currently testing it.

Link to comment
Share on other sites

Add this and have this method called when you want the items removed

 

 

public void removeItem(EntityPlayer ep, ItemStack removeitem) {
IInventory inv = ep.inventory;
for(int i=0; i < inv.getSizeInventory(); i++)
{
	if(inv.getStackInSlot(i) != null)
	{
		ItemStack j = inv.getStackInSlot(i);
		if(j.getItem() != null && j.getItem() == removeitem.getItem())
		{
			inv.setInventorySlotContents(i, null);
		}
	}
}
}

Just do a ctrl+shift+o to import everything needed and call this method when you want to use it

 

 

The Korecraft Mod

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.