-
Bug
-
Resolution: Fixed
-
Minecraft 1.9, Minecraft 1.9.1 Pre-Release 3, Minecraft 1.9.2, Minecraft 16w14a, Minecraft 16w15a
-
None
-
OS: Windows 10 and Debian Jessie
Java: 1.8.0_73
-
Community Consensus
Example:
All dropped items will display as stone. DataWatcher ID bug.
https://www.youtube.com/watch?v=788153dV8Hk
Reproduce bug:
You just have to throw a splash potion before viewing any ground item (since your Minecraft was started) !
Then, go on a Minecraft Server (Vanilla, Spigot 1.9 or servers with 1.8/1.9 support) and drop an item on ground or throw a potion.
The item will be stone and the potion will display as water without real potion color.
In logs you will see:
- "Item entity XXX has no item?!"
- "ThrownPotion entity XXX has no item?!"
Cause:
This bug append when EntityPotion class was loaded before EntityItem class (so, when you see throwed potion before item on ground).
That's because DataWatcher/EntityMetadata ID was based on class load order in some cases.
Code is from Spigot 1.9, but it's the same on 1.9 client :
private static final DataWatcherObject<Optional<ItemStack>> c = DataWatcher.a(EntityItem.class, DataWatcherRegistry.f);
private static final DataWatcherObject<Optional<ItemStack>> d = DataWatcher.a(EntityItem.class, DataWatcherRegistry.f);
This two codes call 'DataWatcher.a(EntityItem.class, DataWatcherRegistry.f);':
public static <T> DataWatcherObject<T> a(Class<? extends Entity> oclass, DataWatcherSerializer<T> datawatcherserializer) { int i; int i; if (a.containsKey(oclass)) { i = ((Integer)a.get(oclass)).intValue() + 1; } else { int j = 0; Class oclass1 = oclass; while (oclass1 != Entity.class) { oclass1 = oclass1.getSuperclass(); if (a.containsKey(oclass1)) { j = ((Integer)a.get(oclass1)).intValue() + 1; break; } } i = j; } if (i > 254) { throw new IllegalArgumentException("Data value id is too big with " + i + "! (Max is " + 254 + ")"); } a.put(oclass, Integer.valueOf(i)); return datawatcherserializer.a(i); }
As you can see, variable i (the datawatcher index) is based on previous oclass value + 1.
So, if EntityItem load first, the id will be 5 and then when EntityPotion load the id will be 6.
But when EntityPotion load first the inverse occurs !
And when the inverse occurs the datawatcher ID was inverse and can't be synchronized with Minecraft servers.