[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 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. 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 |