[SPIGOT-2980] ItemStack Deserialization Issues Created: 02/Jan/17  Updated: 02/Jan/17  Resolved: 02/Jan/17

Status: Resolved
Project: Spigot
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Daniel Ennis Assignee: Unassigned
Resolution: Fixed Votes: 0
Labels: craftbukkit, deserialization, itemstack


 Description   

The way ItemStack conversion was handled in CraftBukkit is faulty and still has issues in regards to old Spawn Eggs. There are honestly numerous flaws with the implementation.

 

1st, ItemStack conversion is occurring before and after item meta apply process.

This causes the damage value on a spawn egg to be converted, then the item meta applies.

 

For an old itemstack that was serialized before Bukkit added Support for Spawn Egg Item Meta, it will be type UNSPECIFIC.

 

So Vanilla converts say Damage Value 100 to a Horse Egg. Then Item Meta applies, and erases the type data that Vanilla just added.

 

This can be fixed with the following patch: https://github.com/PaperMC/Paper/blob/master/Spigot-Server-Patches/0198-Fix-ItemStack-Data-Conversion.patch

 

Following up, embedded ID's in Spawn Eggs are not being ran through the NMS Converters, resulting in any old spawn egg before 1.11.2 from being valid, as it uses invalid spawn ID's.

 

The following patch also resolves this issue

https://github.com/starlis/empirecraft/blob/5b17e8fac1e6f1cb8f2bbe288a6c60676532669d/patches/server/0099-Convert-Horse-Eggs-in-Meta-Deserialization.patch

However this patch identifies a serious flaw in the Item Meta's deserialization system. Spawn Eggs may not be the only thing affected by this.

Item Meta handlers needs to try to load the data from the loaded NBT in internal tag if it cant find it in its expected field.

New Item Meta handlers (such as an expected Shulker Box to come) really must handle both cases, of serialization data that is in and not in the "simplified format".

Servers are losing data due to this bug.

I am not expecting you to copy my patches exactly (But they are MIT licensed if you wish to copy it), but to fix this properly on the implementation of Item Meta itself ideally.



 Comments   
Comment by Daniel Ennis [ 02/Jan/17 ]

Sorry seems we posted at same time before seeing response.

 

Looks good to me. 

Comment by Daniel Ennis [ 02/Jan/17 ]

I don't have example data on hand, but take your first code example and add lore to it, should reproduce the issue.

Comment by md_5 [ 02/Jan/17 ]
test:
  ==: org.bukkit.inventory.ItemStack
  type: MONSTER_EGG
  damage: 100
  meta:
    ==: ItemMeta
    meta-type: UNSPECIFIC
    display-name: Test

I think both of these issues are resolved now.

Comment by md_5 [ 02/Jan/17 ]

So can you please provide an example of a problematic egg?

Comment by Daniel Ennis [ 02/Jan/17 ]

I believe its different eggs from different points of time.

 

But as for the first issue that you couldn't reproduce, I believe its because you did not have any item meta at all.

 

The stacks I encountered the problem all had lore. Since your test did not have lore, it was not running that 2nd convertItemStack()

Comment by md_5 [ 02/Jan/17 ]

I also tried saving an egg spawned via creative 1.9. This produced:

test:
  ==: org.bukkit.inventory.ItemStack
  type: MONSTER_EGG
  meta:
    ==: ItemMeta
    meta-type: UNSPECIFIC
    internal: H4sIAAAAAAAAAONiYOBi4HTNK8ksqQxJTOdgYMpMYeCG8D3yi4pTGRgA104FmCMAAAA=

Which did not deserialize properly (but still doesn't have any damage value that you suggest). The conversion of that into entity meta has been implemented and tested in a recent commit.

Comment by md_5 [ 02/Jan/17 ]

First of all - I literally do not look at patches that are not submitted via Stash - this is to ensure that all contributions follow the CLA - the MIT license is not equivalent to the CLA.
Second of all you haven't provided any sample pre serialized data so I had to try and understand what you have done.
I ran the following code on a CraftBukkit 1.9 server:

        ItemStack egg = new ItemStack( Material.MONSTER_EGG, 1, EntityType.HORSE.getTypeId() );
        getConfig().set( "test", egg);
        saveConfig();

This produced a result as follows:

test:
  ==: org.bukkit.inventory.ItemStack
  type: MONSTER_EGG
  damage: 100

I then ran the following code on a 1.11 CraftBukkit server:

    @EventHandler
    public void command(final PlayerCommandPreprocessEvent event)
    {
        if ( event.getMessage().equals( "/test" ) )
        {
            ItemStack stack = getConfig().getItemStack( "test" );
            event.getPlayer().getInventory().addItem( stack );
            event.setCancelled( true );
        }
    }

As expected, when issuing the command /test there was indeed a horse egg in my inventory.

As for the second issue described (the convention is generally one ticket per issue), that sounds like something that should be reported to Vanilla - bugs.mojang.com

Generated at Tue Apr 22 06:49:52 UTC 2025 using Jira 10.3.5#10030005-sha1:190c783f2bd6c69cd5accdb70f97e48812a78d14.