[SPIGOT-5485] Support for spawn eggs with different spawned mob type Created: 27/Dec/19  Updated: 29/Jul/24  Resolved: 29/Jul/24

Status: Resolved
Project: Spigot
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Minor
Reporter: blablubbabc Assignee: Unassigned
Resolution: Fixed Votes: 2
Labels: deserialization, serialization, spawnegg

Issue Links:
Duplicate
is duplicated by SPIGOT-6975 Spawnegg serialization tries to conve... Resolved
Relates
relates to SPIGOT-6975 Spawnegg serialization tries to conve... Resolved
Version: This server is running CraftBukkit version git-Spigot-05bb8bc-7d677e7 (MC: 1.15.1) (Implementing API version 1.15.1-R0.1-SNAPSHOT)
Guidelines Read: Yes

 Description   

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



 Comments   
Comment by blablubbabc [ 29/Jul/24 ]

Fixed with https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/c6b4d5a87fa1293e40ca0f3c56a687d7025839a5

Comment by blablubbabc [ 29/Jul/24 ]

With the removal of the legacy spawn egg conversion during item deserialization (https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/c6b4d5a87fa1293e40ca0f3c56a687d7025839a5) during 1.20.6, this issue seems to be resolved. Briefly tested this with this command: /give blablubbabc minecraft:pig_spawn_egg[minecraft:entity_data=\{id:"minecraft:creeper"}]

Comment by Proto Type [ 14/May/24 ]

Why is this still not fixed?

One use case I was trying to use in my server is to have a Vex spawn egg which spawns a lightning bolt. Turns into a Turtle spawn egg because this isn't supported yet ;_;

Comment by blablubbabc [ 28/Dec/19 ]

The ItemMonsterEgg takes into account the optionally existing "id" field in the "EntityTag". I just tested these spawn eggs again on 1.15.1 and they seem to work fine so far (they spawn the expected internally stored mob type and don't get converted by minecraft across server restarts, chunk loads, etc.). Can't comment on whether or not its supposed to work.
I haven't actually tested this, but from looking at DataConverterFlattenSpawnEgg I assume it might only affect items matching the legacy type "minecraft:spawn_egg". Can't determine from that yet whether it removes the "id" tag after conversion. Spigot on the other hand always triggers the conversion if it finds an internally stored mob type id, and it removes that id field afterwards (see CraftMetaSpawnEgg).

Comment by md_5 [ 28/Dec/19 ]

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

Fairly certain this is no longer possible or meant to be possible in vanilla.
I don't think Spigot's conversion behaviour differs from the way Vanilla converts.

Generated at Fri Mar 14 17:31:33 UTC 2025 using Jira 10.3.3#10030003-sha1:d220e3fefc8dfc6d47f522d3b9a20c1455e12b7b.