The bug
Primitive NBT lists that are not of type int need a type suffix. If the list is of type double the values must either have a suffix or be a floating point number.
For instance the command
/summon zombie ~ ~ ~ {Motion:[1d,1d,1d]}
will summon a zombie with motion, but
/summon zombie ~ ~ ~ {Motion:[1,1,1]}
will not.
Possible fix
I was looking at the decompiled source for 1.10.2 using forge and this seems to be caused by the primitive get methods in net.minecraft.nbt.NBTTagList
. For instance the Method getDoubleAt(int)
checks for an nbt id of 6 in line 223, but if the list is of type int ([1,1,1]) the method returns 0. If the method would work similar to net.minecraft.nbt.NBTTagCompound.getDouble(String)
and make use of the class net.minecraft.nbt.NBTPrimitive
instead of the concrete subclass net.minecraft.nbt.NBTTagDouble
, then it would return the correct value:
Current (1.10.2) implementation of net.minecraft.nbt.NBTTagList.getDoubleAt(int):217
public double getDoubleAt(int i)
{
if (i >= 0 && i < this.tagList.size())
{
NBTBase nbtbase = (NBTBase)this.tagList.get(i);
if (nbtbase.getId() == 6)
{
return ((NBTTagDouble)nbtbase).getDouble();
}
}
return 0.0D;
}
Fixed implementation of net.minecraft.nbt.NBTTagList.getDoubleAt(int)
public double getDoubleAt(int i)
{
if (i >= 0 && i < this.tagList.size())
{
NBTBase nbtbase = (NBTBase)this.tagList.get(i);
if (nbtbase.getId() >= 1 && nbtbase.getId() <= 6)
{
return ((NBTPrimitive)nbtbase).getDouble();
}
}
return 0.0D;
}
For this bug to be fixed you would also need to change the Method net.minecraft.nbt.NBTTagCompound.getTagList(String, int)
. This method is for instance called here:
net.minecraft.entity.Entity.readFromNBT(NBTTagCompound):1838
NBTTagList nbttaglist2 = compound.getTagList("Motion", 6);
NBTTagList nbttaglist3 = compound.getTagList("Rotation", 5);
this.motionX = nbttaglist2.getDoubleAt(0);
this.motionY = nbttaglist2.getDoubleAt(1);
this.motionZ = nbttaglist2.getDoubleAt(2);
Instead of calling getTagList
with type 6, the method should support the type 99, similar to net.minecraft.nbt.NBTTagCompound.getDouble(String)
wich calles hasKey(key, 99)
.
net.minecraft.nbt.NBTTagCompound.getDouble(String):324
/**
* Retrieves a double value using the specified key, or 0 if no such key was stored.
*/
public double getDouble(String key)
{
try
{
if (this.hasKey(key, 99))
{
return ((NBTPrimitive)this.tagMap.get(key)).getDouble();
}
}
catch (ClassCastException var3)
{
;
}
return 0.0D;
}
net.minecraft.nbt.NBTTagCompound.hasKey(String, int):215
/**
* Returns whether the given string has been previously stored as a key in this tag compound as a particular type,
* denoted by a parameter in the form of an ordinal. If the provided ordinal is 99, this method will match tag types
* representing numbers.
*/
public boolean hasKey(String key, int type)
{
int i = this.getTagId(key);
return i == type ? true : (type != 99 ? false : i == 1 || i == 2 || i == 3 || i == 4 || i == 5 || i == 6);
}
The same fix would work for the other primitive types: byte, float, int, long, short.
Can confirm in 21w03a.