--- a/net/minecraft/world/entity/EntityTypes.java
+++ b/net/minecraft/world/entity/EntityTypes.java
@@ -176,6 +176,7 @@
 import net.minecraft.world.phys.Vec3D;
 import net.minecraft.world.phys.shapes.VoxelShape;
 import net.minecraft.world.phys.shapes.VoxelShapes;
+import org.bukkit.event.entity.CreatureSpawnEvent;
 import org.slf4j.Logger;
 
 public class EntityTypes<T extends Entity> implements FeatureElement, EntityTypeTest<Entity, T> {
@@ -191,7 +192,7 @@
         return Items.ACACIA_CHEST_BOAT;
     }), EnumCreatureType.MISC).noLootTable().sized(1.375F, 0.5625F).eyeHeight(0.5625F).clientTrackingRange(10));
     public static final EntityTypes<Allay> ALLAY = register("allay", EntityTypes.Builder.of(Allay::new, EnumCreatureType.CREATURE).sized(0.35F, 0.6F).eyeHeight(0.36F).ridingOffset(0.04F).clientTrackingRange(8).updateInterval(2));
-    public static final EntityTypes<EntityAreaEffectCloud> AREA_EFFECT_CLOUD = register("area_effect_cloud", EntityTypes.Builder.of(EntityAreaEffectCloud::new, EnumCreatureType.MISC).noLootTable().fireImmune().sized(6.0F, 0.5F).clientTrackingRange(10).updateInterval(Integer.MAX_VALUE));
+    public static final EntityTypes<EntityAreaEffectCloud> AREA_EFFECT_CLOUD = register("area_effect_cloud", EntityTypes.Builder.of(EntityAreaEffectCloud::new, EnumCreatureType.MISC).noLootTable().fireImmune().sized(6.0F, 0.5F).clientTrackingRange(10).updateInterval(10)); // CraftBukkit - SPIGOT-3729: track area effect clouds
     public static final EntityTypes<Armadillo> ARMADILLO = register("armadillo", EntityTypes.Builder.of(Armadillo::new, EnumCreatureType.CREATURE).sized(0.7F, 0.65F).eyeHeight(0.26F).clientTrackingRange(10));
     public static final EntityTypes<EntityArmorStand> ARMOR_STAND = register("armor_stand", EntityTypes.Builder.of(EntityArmorStand::new, EnumCreatureType.MISC).sized(0.5F, 1.975F).eyeHeight(1.7775F).clientTrackingRange(10));
     public static final EntityTypes<EntityTippedArrow> ARROW = register("arrow", EntityTypes.Builder.of(EntityTippedArrow::new, EnumCreatureType.MISC).noLootTable().sized(0.5F, 0.5F).eyeHeight(0.13F).clientTrackingRange(4).updateInterval(20));
@@ -399,7 +400,7 @@
         return ResourceKey.create(Registries.ENTITY_TYPE, MinecraftKey.withDefaultNamespace(s));
     }
 
-    private static <T extends Entity> EntityTypes<T> register(String s, EntityTypes.Builder<T> entitytypes_builder) {
+    private static <T extends Entity> EntityTypes<T> register(String s, EntityTypes.Builder entitytypes_builder) { // CraftBukkit - decompile error
         return register(vanillaEntityId(s), entitytypes_builder);
     }
 
@@ -431,7 +432,14 @@
 
     @Nullable
     public T spawn(WorldServer worldserver, @Nullable ItemStack itemstack, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EntitySpawnReason entityspawnreason, boolean flag, boolean flag1) {
-        Consumer consumer;
+        // CraftBukkit start
+        return this.spawn(worldserver, itemstack, entityhuman, blockposition, entityspawnreason, flag, flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG);
+    }
+
+    @Nullable
+    public T spawn(WorldServer worldserver, @Nullable ItemStack itemstack, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EntitySpawnReason entityspawnreason, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
+        // CraftBukkit end
+        Consumer<T> consumer; // CraftBukkit - decompile error
 
         if (itemstack != null) {
             consumer = createDefaultStackConfig(worldserver, itemstack, entityhuman);
@@ -440,7 +448,7 @@
             };
         }
 
-        return this.spawn(worldserver, consumer, blockposition, entityspawnreason, flag, flag1);
+        return this.spawn(worldserver, consumer, blockposition, entityspawnreason, flag, flag1, spawnReason); // CraftBukkit
     }
 
     public static <T extends Entity> Consumer<T> createDefaultStackConfig(World world, ItemStack itemstack, @Nullable EntityHuman entityhuman) {
@@ -464,21 +472,40 @@
         CustomData customdata = (CustomData) itemstack.getOrDefault(DataComponents.ENTITY_DATA, CustomData.EMPTY);
 
         return !customdata.isEmpty() ? consumer.andThen((entity) -> {
-            updateCustomEntityTag(world, entityhuman, entity, customdata);
+            try { updateCustomEntityTag(world, entityhuman, entity, customdata); } catch (Throwable t) { LOGGER.warn("Error loading spawn egg NBT", t); } // CraftBukkit - SPIGOT-5665
         }) : consumer;
     }
 
     @Nullable
     public T spawn(WorldServer worldserver, BlockPosition blockposition, EntitySpawnReason entityspawnreason) {
-        return this.spawn(worldserver, (Consumer) null, blockposition, entityspawnreason, false, false);
+        // CraftBukkit start
+        return this.spawn(worldserver, blockposition, entityspawnreason, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
+    }
+
+    @Nullable
+    public T spawn(WorldServer worldserver, BlockPosition blockposition, EntitySpawnReason entityspawnreason, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
+        return this.spawn(worldserver, (Consumer<T>) null, blockposition, entityspawnreason, false, false, spawnReason); // CraftBukkit - decompile error
+        // CraftBukkit end
     }
 
     @Nullable
     public T spawn(WorldServer worldserver, @Nullable Consumer<T> consumer, BlockPosition blockposition, EntitySpawnReason entityspawnreason, boolean flag, boolean flag1) {
+        // CraftBukkit start
+        return this.spawn(worldserver, consumer, blockposition, entityspawnreason, flag, flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
+    }
+
+    @Nullable
+    public T spawn(WorldServer worldserver, @Nullable Consumer<T> consumer, BlockPosition blockposition, EntitySpawnReason entityspawnreason, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
+        // CraftBukkit end
         T t0 = this.create(worldserver, consumer, blockposition, entityspawnreason, flag, flag1);
 
         if (t0 != null) {
-            worldserver.addFreshEntityWithPassengers(t0);
+            // CraftBukkit start
+            worldserver.addFreshEntityWithPassengers(t0, spawnReason);
+            if (t0.isRemoved()) {
+                return null; // Don't return an entity when CreatureSpawnEvent is canceled
+            }
+            // CraftBukkit end
             if (t0 instanceof EntityInsentient) {
                 EntityInsentient entityinsentient = (EntityInsentient) t0;
 
@@ -657,7 +684,7 @@
             }
 
             return entity;
-        }).orElse((Object) null);
+        }).orElse(null); // CraftBukkit - decompile error
     }
 
     public static Stream<Entity> loadEntitiesRecursive(final List<? extends NBTBase> list, final World world, final EntitySpawnReason entityspawnreason) {
@@ -718,7 +745,7 @@
 
     @Nullable
     public T tryCast(Entity entity) {
-        return entity.getType() == this ? entity : null;
+        return entity.getType() == this ? (T) entity : null; // CraftBukkit - decompile error
     }
 
     @Override
@@ -791,7 +818,7 @@
             this.canSpawnFarFromPlayer = enumcreaturetype == EnumCreatureType.CREATURE || enumcreaturetype == EnumCreatureType.MISC;
         }
 
-        public static <T extends Entity> EntityTypes.Builder<T> of(EntityTypes.b<T> entitytypes_b, EnumCreatureType enumcreaturetype) {
+        public static <T extends Entity> EntityTypes.Builder<T> of(EntityTypes.b entitytypes_b, EnumCreatureType enumcreaturetype) { // CraftBukkit - decompile error
             return new EntityTypes.Builder<>(entitytypes_b, enumcreaturetype);
         }
 
