--- a/net/minecraft/world/entity/monster/Silverfish.java
+++ b/net/minecraft/world/entity/monster/Silverfish.java
@@ -29,8 +29,13 @@
 import net.minecraft.world.level.block.Block;
 import net.minecraft.world.level.block.InfestedBlock;
 import net.minecraft.world.level.block.state.BlockState;
+// CraftBukkit start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityRemoveEvent;
+// CraftBukkit end
 
 public class Silverfish extends Monster {
+
     @Nullable
     private Silverfish.SilverfishWakeUpFriendsGoal friendsGoal;
 
@@ -44,14 +49,14 @@
         this.goalSelector.addGoal(1, new FloatGoal(this));
         this.goalSelector.addGoal(1, new ClimbOnTopOfPowderSnowGoal(this, this.level()));
         this.goalSelector.addGoal(3, this.friendsGoal);
-        this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0, false));
+        this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0D, false));
         this.goalSelector.addGoal(5, new Silverfish.SilverfishMergeWithStoneGoal(this));
-        this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers());
+        this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers());
         this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
     }
 
     public static AttributeSupplier.Builder createAttributes() {
-        return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 8.0).add(Attributes.MOVEMENT_SPEED, 0.25).add(Attributes.ATTACK_DAMAGE, 1.0);
+        return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 8.0D).add(Attributes.MOVEMENT_SPEED, 0.25D).add(Attributes.ATTACK_DAMAGE, 1.0D);
     }
 
     @Override
@@ -109,24 +114,85 @@
         return InfestedBlock.isCompatibleHostBlock(world.getBlockState(pos.below())) ? 10.0F : super.getWalkTargetValue(pos, world);
     }
 
-    public static boolean checkSilverfishSpawnRules(
-        EntityType<Silverfish> type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, RandomSource random
-    ) {
+    public static boolean checkSilverfishSpawnRules(EntityType<Silverfish> type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
         if (checkAnyLightMonsterSpawnRules(type, world, spawnReason, pos, random)) {
-            Player player = world.getNearestPlayer((double)pos.getX() + 0.5, (double)pos.getY() + 0.5, (double)pos.getZ() + 0.5, 5.0, true);
-            return player == null;
+            Player entityhuman = world.getNearestPlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, 5.0D, true);
+
+            return !(entityhuman != null && !entityhuman.affectsSpawning) && entityhuman == null; // Paper - Affects Spawning API
         } else {
             return false;
         }
     }
 
-    static class SilverfishMergeWithStoneGoal extends RandomStrollGoal {
+    private static class SilverfishWakeUpFriendsGoal extends Goal {
+
+        private final Silverfish silverfish;
+        private int lookForFriends;
+
+        public SilverfishWakeUpFriendsGoal(Silverfish silverfish) {
+            this.silverfish = silverfish;
+        }
+
+        public void notifyHurt() {
+            if (this.lookForFriends == 0) {
+                this.lookForFriends = this.adjustedTickDelay(20);
+            }
+
+        }
+
+        @Override
+        public boolean canUse() {
+            return this.lookForFriends > 0;
+        }
+
+        @Override
+        public void tick() {
+            --this.lookForFriends;
+            if (this.lookForFriends <= 0) {
+                Level world = this.silverfish.level();
+                RandomSource randomsource = this.silverfish.getRandom();
+                BlockPos blockposition = this.silverfish.blockPosition();
+
+                for (int i = 0; i <= 5 && i >= -5; i = (i <= 0 ? 1 : 0) - i) {
+                    for (int j = 0; j <= 10 && j >= -10; j = (j <= 0 ? 1 : 0) - j) {
+                        for (int k = 0; k <= 10 && k >= -10; k = (k <= 0 ? 1 : 0) - k) {
+                            BlockPos blockposition1 = blockposition.offset(j, i, k);
+                            BlockState iblockdata = world.getBlockState(blockposition1);
+                            Block block = iblockdata.getBlock();
+
+                            if (block instanceof InfestedBlock) {
+                                // CraftBukkit start
+                                BlockState afterState = world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? iblockdata.getFluidState().createLegacyBlock() : ((InfestedBlock) block).hostStateByInfested(world.getBlockState(blockposition1)); // Paper - fix wrong block state
+                                if (!CraftEventFactory.callEntityChangeBlockEvent(this.silverfish, blockposition1, afterState)) { // Paper - fix wrong block state
+                                    continue;
+                                }
+                                // CraftBukkit end
+                                if (world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
+                                    world.destroyBlock(blockposition1, true, this.silverfish);
+                                } else {
+                                    world.setBlock(blockposition1, ((InfestedBlock) block).hostStateByInfested(world.getBlockState(blockposition1)), 3);
+                                }
+
+                                if (randomsource.nextBoolean()) {
+                                    return;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+        }
+    }
+
+    private static class SilverfishMergeWithStoneGoal extends RandomStrollGoal {
+
         @Nullable
         private Direction selectedDirection;
         private boolean doMerge;
 
         public SilverfishMergeWithStoneGoal(Silverfish silverfish) {
-            super(silverfish, 1.0, 10);
+            super(silverfish, 1.0D, 10);
             this.setFlags(EnumSet.of(Goal.Flag.MOVE));
         }
 
@@ -137,12 +203,14 @@
             } else if (!this.mob.getNavigation().isDone()) {
                 return false;
             } else {
-                RandomSource randomSource = this.mob.getRandom();
-                if (this.mob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && randomSource.nextInt(reducedTickDelay(10)) == 0) {
-                    this.selectedDirection = Direction.getRandom(randomSource);
-                    BlockPos blockPos = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5, this.mob.getZ()).relative(this.selectedDirection);
-                    BlockState blockState = this.mob.level().getBlockState(blockPos);
-                    if (InfestedBlock.isCompatibleHostBlock(blockState)) {
+                RandomSource randomsource = this.mob.getRandom();
+
+                if (this.mob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && randomsource.nextInt(reducedTickDelay(10)) == 0) {
+                    this.selectedDirection = Direction.getRandom(randomsource);
+                    BlockPos blockposition = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5D, this.mob.getZ()).relative(this.selectedDirection);
+                    BlockState iblockdata = this.mob.level().getBlockState(blockposition);
+
+                    if (InfestedBlock.isCompatibleHostBlock(iblockdata)) {
                         this.doMerge = true;
                         return true;
                     }
@@ -155,7 +223,7 @@
 
         @Override
         public boolean canContinueToUse() {
-            return !this.doMerge && super.canContinueToUse();
+            return this.doMerge ? false : super.canContinueToUse();
         }
 
         @Override
@@ -163,65 +231,21 @@
             if (!this.doMerge) {
                 super.start();
             } else {
-                LevelAccessor levelAccessor = this.mob.level();
-                BlockPos blockPos = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5, this.mob.getZ()).relative(this.selectedDirection);
-                BlockState blockState = levelAccessor.getBlockState(blockPos);
-                if (InfestedBlock.isCompatibleHostBlock(blockState)) {
-                    levelAccessor.setBlock(blockPos, InfestedBlock.infestedStateByHost(blockState), 3);
-                    this.mob.spawnAnim();
-                    this.mob.discard();
-                }
-            }
-        }
-    }
-
-    static class SilverfishWakeUpFriendsGoal extends Goal {
-        private final Silverfish silverfish;
-        private int lookForFriends;
-
-        public SilverfishWakeUpFriendsGoal(Silverfish silverfish) {
-            this.silverfish = silverfish;
-        }
-
-        public void notifyHurt() {
-            if (this.lookForFriends == 0) {
-                this.lookForFriends = this.adjustedTickDelay(20);
-            }
-        }
-
-        @Override
-        public boolean canUse() {
-            return this.lookForFriends > 0;
-        }
-
-        @Override
-        public void tick() {
-            this.lookForFriends--;
-            if (this.lookForFriends <= 0) {
-                Level level = this.silverfish.level();
-                RandomSource randomSource = this.silverfish.getRandom();
-                BlockPos blockPos = this.silverfish.blockPosition();
-
-                for (int i = 0; i <= 5 && i >= -5; i = (i <= 0 ? 1 : 0) - i) {
-                    for (int j = 0; j <= 10 && j >= -10; j = (j <= 0 ? 1 : 0) - j) {
-                        for (int k = 0; k <= 10 && k >= -10; k = (k <= 0 ? 1 : 0) - k) {
-                            BlockPos blockPos2 = blockPos.offset(j, i, k);
-                            BlockState blockState = level.getBlockState(blockPos2);
-                            Block block = blockState.getBlock();
-                            if (block instanceof InfestedBlock) {
-                                if (level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
-                                    level.destroyBlock(blockPos2, true, this.silverfish);
-                                } else {
-                                    level.setBlock(blockPos2, ((InfestedBlock)block).hostStateByInfested(level.getBlockState(blockPos2)), 3);
-                                }
+                Level world = this.mob.level();
+                BlockPos blockposition = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5D, this.mob.getZ()).relative(this.selectedDirection);
+                BlockState iblockdata = world.getBlockState(blockposition);
 
-                                if (randomSource.nextBoolean()) {
-                                    return;
-                                }
-                            }
-                        }
+                if (InfestedBlock.isCompatibleHostBlock(iblockdata)) {
+                    // CraftBukkit start
+                    if (!CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, InfestedBlock.infestedStateByHost(iblockdata))) {
+                        return;
                     }
+                    // CraftBukkit end
+                    world.setBlock(blockposition, InfestedBlock.infestedStateByHost(iblockdata), 3);
+                    this.mob.spawnAnim();
+                    this.mob.discard(EntityRemoveEvent.Cause.ENTER_BLOCK); // CraftBukkit - add Bukkit remove cause
                 }
+
             }
         }
     }
