--- a/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java
@@ -26,6 +26,7 @@
 import net.minecraft.world.phys.Vec3;
 
 public class SculkCatalystBlockEntity extends BlockEntity implements GameEventListener.Holder<SculkCatalystBlockEntity.CatalystListener> {
+
     private final SculkCatalystBlockEntity.CatalystListener catalystListener;
 
     public SculkCatalystBlockEntity(BlockPos pos, BlockState state) {
@@ -33,12 +34,23 @@
         this.catalystListener = new SculkCatalystBlockEntity.CatalystListener(state, new BlockPositionSource(pos));
     }
 
+    // Paper start
+    @Override
+    public void setLevel(Level level) {
+        super.setLevel(level);
+        this.catalystListener.sculkSpreader.level = level;
+    }
+    // Paper end
+
     public static void serverTick(Level world, BlockPos pos, BlockState state, SculkCatalystBlockEntity blockEntity) {
+        org.bukkit.craftbukkit.v1_20_R2.event.CraftEventFactory.sourceBlockOverride = blockEntity.getBlockPos(); // CraftBukkit - SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep.
         blockEntity.catalystListener.getSculkSpreader().updateCursors(world, pos, world.getRandom(), true);
+        org.bukkit.craftbukkit.v1_20_R2.event.CraftEventFactory.sourceBlockOverride = null; // CraftBukkit
     }
 
     @Override
     public void load(CompoundTag nbt) {
+        super.load(nbt); // CraftBukkit - SPIGOT-7393: Load super Bukkit data
         this.catalystListener.sculkSpreader.load(nbt);
     }
 
@@ -54,6 +66,7 @@
     }
 
     public static class CatalystListener implements GameEventListener {
+
         public static final int PULSE_TICKS = 8;
         final SculkSpreader sculkSpreader;
         private final BlockState blockState;
@@ -63,6 +76,7 @@
             this.blockState = state;
             this.positionSource = positionSource;
             this.sculkSpreader = SculkSpreader.createLevelSpreader();
+            // this.sculkSpreader.level = this.level; // CraftBukkit // Paper - bad fix
         }
 
         @Override
@@ -83,19 +97,22 @@
         @Override
         public boolean handleGameEvent(ServerLevel world, GameEvent event, GameEvent.Context emitter, Vec3 emitterPos) {
             if (event == GameEvent.ENTITY_DIE) {
-                Entity i = emitter.sourceEntity();
-                if (i instanceof LivingEntity) {
-                    LivingEntity livingEntity = (LivingEntity)i;
-                    if (!livingEntity.wasExperienceConsumed()) {
-                        int i = livingEntity.getExperienceReward();
-                        if (livingEntity.shouldDropExperience() && i > 0) {
+                Entity entity = emitter.sourceEntity();
+
+                if (entity instanceof LivingEntity) {
+                    LivingEntity entityliving = (LivingEntity) entity;
+
+                    if (!entityliving.wasExperienceConsumed()) {
+                        int i = entityliving.getExperienceReward();
+
+                        if (entityliving.shouldDropExperience() && i > 0) {
                             this.sculkSpreader.addCursors(BlockPos.containing(emitterPos.relative(Direction.UP, 0.5D)), i);
-                            this.tryAwardItSpreadsAdvancement(world, livingEntity);
+                            this.tryAwardItSpreadsAdvancement(world, entityliving);
                         }
 
-                        livingEntity.skipDropExperience();
-                        this.positionSource.getPosition(world).ifPresent((pos) -> {
-                            this.bloom(world, BlockPos.containing(pos), this.blockState, world.getRandom());
+                        entityliving.skipDropExperience();
+                        this.positionSource.getPosition(world).ifPresent((vec3d1) -> {
+                            this.bloom(world, BlockPos.containing(vec3d1), this.blockState, world.getRandom());
                         });
                     }
 
@@ -112,17 +129,20 @@
         }
 
         public void bloom(ServerLevel world, BlockPos pos, BlockState state, RandomSource random) {
-            world.setBlock(pos, state.setValue(SculkCatalystBlock.PULSE, Boolean.valueOf(true)), 3);
+            world.setBlock(pos, (BlockState) state.setValue(SculkCatalystBlock.PULSE, true), 3);
             world.scheduleTick(pos, state.getBlock(), 8);
-            world.sendParticles(ParticleTypes.SCULK_SOUL, (double)pos.getX() + 0.5D, (double)pos.getY() + 1.15D, (double)pos.getZ() + 0.5D, 2, 0.2D, 0.0D, 0.2D, 0.0D);
-            world.playSound((Player)null, pos, SoundEvents.SCULK_CATALYST_BLOOM, SoundSource.BLOCKS, 2.0F, 0.6F + random.nextFloat() * 0.4F);
+            world.sendParticles(ParticleTypes.SCULK_SOUL, (double) pos.getX() + 0.5D, (double) pos.getY() + 1.15D, (double) pos.getZ() + 0.5D, 2, 0.2D, 0.0D, 0.2D, 0.0D);
+            world.playSound((Player) null, pos, SoundEvents.SCULK_CATALYST_BLOOM, SoundSource.BLOCKS, 2.0F, 0.6F + random.nextFloat() * 0.4F);
         }
 
         private void tryAwardItSpreadsAdvancement(Level world, LivingEntity deadEntity) {
-            LivingEntity livingEntity = deadEntity.getLastHurtByMob();
-            if (livingEntity instanceof ServerPlayer serverPlayer) {
-                DamageSource damageSource = deadEntity.getLastDamageSource() == null ? world.damageSources().playerAttack(serverPlayer) : deadEntity.getLastDamageSource();
-                CriteriaTriggers.KILL_MOB_NEAR_SCULK_CATALYST.trigger(serverPlayer, deadEntity, damageSource);
+            LivingEntity entityliving1 = deadEntity.getLastHurtByMob();
+
+            if (entityliving1 instanceof ServerPlayer) {
+                ServerPlayer entityplayer = (ServerPlayer) entityliving1;
+                DamageSource damagesource = deadEntity.getLastDamageSource() == null ? world.damageSources().playerAttack(entityplayer) : deadEntity.getLastDamageSource();
+
+                CriteriaTriggers.KILL_MOB_NEAR_SCULK_CATALYST.trigger(entityplayer, deadEntity, damagesource);
             }
 
         }
