Uploaded image for project: 'Spigot'
  1. Spigot
  2. SPIGOT-5485

Support for spawn eggs with different spawned mob type

XMLWordPrintable

    • This server is running CraftBukkit version git-Spigot-05bb8bc-7d677e7 (MC: 1.15.1) (Implementing API version 1.15.1-R0.1-SNAPSHOT)
    • Yes

      Since the update to MC 1.13 Spigot performs a legacy conversion of spawn egg items during ItemStack deserialization. This takes and then removes the stored spawned mob type from the item's nbt data, gets its numerical type id, maps it to a corresponding new spawn egg material via the SPAWN_EGGS map in CraftLegacy and changes the ItemStack's type via the updateMaterial call during ItemStack deserialization / when applying the deserialized ItemMeta to the deserialized ItemStack.

      There are currently 3 (minor) issues with this:

      • In vanilla minecraft via give command it is possible to create spawn eggs of one type which spawn a mob of a different type. Eg. have a spawn egg that looks like a pig spawn egg, but which actually spawns a creeper.

      The usecase of this could be to disguise a spawn egg and surprise the user when the spawn egg is used. Another use case is to create spawn eggs for mobs which currently don't have a corresponding spawn egg in vanilla minecraft, eg. create a vindicator spawn egg that actually spawns an illusioner (for which no own spawn egg item exists currently).

      From my basic testing so far these spawn eggs seem to work and behave fine in vanilla minecraft. However, once these spawn egg items go through Spigot's item deserialization they run through the legacy conversion which replaces their ItemStack material to the actual corresponding mob type.

      This either breaks the disguise in the first usecase, and completely destroys the item in the second usecase (since illusioners don't have a corresponding spawn egg material, resulting in the item type being cleared).

      • The second issue is that by removing the 'id' tag from the ItemStack's EntityTag during the legacy conversion the deserialized item will no longer match (isSimilar or equals check) any original items which did not go through this conversion / deserialization process and therefore still have this id tag.
      • The third issue involves spawn eggs with a stored mob type from MC 1.14 or later. These mobs (eg. fox, turtle, etc.) don't have an own numerical type id but use -1 instead (see Bukkit's EntityTypes enum). These numerical ids are used to map entity types to a corresponding spawn egg materials in CraftLegacy. Since all these later added mobs share the same type id of -1, they replace each other's entries in the SPAWN_EGGS map in CraftLegacy, resulting in all spawn eggs with these stored mob types to get mapped to turtle spawn egg (which is the last entry with that -1 id that gets added to the SPAWN_EGGS map).

       

      I have only very briefly looked into this, after a user of one of my plugins ran into this issue of his custom spawn eggs getting converted to turtle eggs. The 'fix' is to not specify any mob id when creating the spawn egg via minecraft's give command. But the above mentioned use cases for these custom spawn eggs seem valid to me. Would it be possible to support these custom spawn egg items, or is there a fundamental / vanilla minecraft issue with them?

      Maybe, if this is possible, a solution would be to only run the legacy conversion if the current item material is actually the legacy spawn egg material. And otherwise skip the legacy conversion. And then also don't remove the internal mob id from the item's data. Minecraft then handles the spawning of the explicitly specified mob type just fine as far as I can tell.

       

      I have tested this with the plugin Shopkeepers, which stores items via Bukkit's item serialization. If you want a minimal reproduction plugin, which simply serializes and deserializes a held item, let me know.

      The minecraft give command for creating such an item could look like this:

      /give blablubbabc minecraft:pig_spawn_egg{EntityTag:{id:"minecraft:creeper"}}
      

      Bukkit's serialized output looks like this:

      ==: org.bukkit.inventory.ItemStack
      v: 2227
      type: PIG_SPAWN_EGG
      meta:
        ==: ItemMeta
        meta-type: SPAWN_EGG
        internal: H4sIAAAAAAAAAONiYOBi4HTNK8ksqQxJTOdgYMpMYRDMzcxLTS5KTCuxSi5KTS1ILWJgAAB18udrKQAAAA==
      

      When deserialized this returns a spawn egg of type 'creeper_spawn_egg'.

            Unassigned Unassigned
            blablubbabc blablubbabc
            Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: