Uploaded image for project: 'Minecraft: Java Edition'
  1. Minecraft: Java Edition
  2. MC-112253

Primitive NBT Lists that are not of type int need a type suffix

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • None
    • Minecraft 1.11.2, Minecraft 1.12.2, Minecraft 17w50a, Minecraft 18w06a, Minecraft 1.13-pre5, 1.15.2, 20w10a, 1.16.3, 21w03a, 21w06a
    • None
    • Confirmed
    • (Unassigned)

      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.

            Unassigned Unassigned
            Adrodoc55 Adrodoc55
            Votes:
            9 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              CHK: