--- a/net/minecraft/world/level/block/MushroomBlock.java
+++ b/net/minecraft/world/level/block/MushroomBlock.java
@@ -2,6 +2,7 @@
 
 import com.mojang.serialization.MapCodec;
 import com.mojang.serialization.codecs.RecordCodecBuilder;
+import java.util.Iterator;
 import java.util.Optional;
 import net.minecraft.core.BlockPos;
 import net.minecraft.core.Holder;
@@ -18,19 +19,24 @@
 import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
 import net.minecraft.world.phys.shapes.CollisionContext;
 import net.minecraft.world.phys.shapes.VoxelShape;
+// CraftBukkit start
+import org.bukkit.TreeType;
+// CraftBukkit end
 
 public class MushroomBlock extends BushBlock implements BonemealableBlock {
-    public static final MapCodec<MushroomBlock> CODEC = RecordCodecBuilder.mapCodec(
-        instance -> instance.group(ResourceKey.codec(Registries.CONFIGURED_FEATURE).fieldOf("feature").forGetter(block -> block.feature), propertiesCodec())
-                .apply(instance, MushroomBlock::new)
-    );
+
+    public static final MapCodec<MushroomBlock> CODEC = RecordCodecBuilder.mapCodec((instance) -> {
+        return instance.group(ResourceKey.codec(Registries.CONFIGURED_FEATURE).fieldOf("feature").forGetter((blockmushroom) -> {
+            return blockmushroom.feature;
+        }), propertiesCodec()).apply(instance, MushroomBlock::new);
+    });
     protected static final float AABB_OFFSET = 3.0F;
-    protected static final VoxelShape SHAPE = Block.box(5.0, 0.0, 5.0, 11.0, 6.0, 11.0);
+    protected static final VoxelShape SHAPE = Block.box(5.0D, 0.0D, 5.0D, 11.0D, 6.0D, 11.0D);
     private final ResourceKey<ConfiguredFeature<?, ?>> feature;
 
     @Override
     public MapCodec<MushroomBlock> codec() {
-        return CODEC;
+        return MushroomBlock.CODEC;
     }
 
     public MushroomBlock(ResourceKey<ConfiguredFeature<?, ?>> featureKey, BlockBehaviour.Properties settings) {
@@ -40,37 +46,43 @@
 
     @Override
     protected VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
-        return SHAPE;
+        return MushroomBlock.SHAPE;
     }
 
     @Override
     protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
-        if (random.nextInt(25) == 0) {
+        if (random.nextFloat() < (world.spigotConfig.mushroomModifier / (100.0f * 25))) { // Spigot - SPIGOT-7159: Better modifier resolution
             int i = 5;
-            int j = 4;
+            boolean flag = true;
+            Iterator iterator = BlockPos.betweenClosed(pos.offset(-4, -1, -4), pos.offset(4, 1, 4)).iterator();
 
-            for (BlockPos blockPos : BlockPos.betweenClosed(pos.offset(-4, -1, -4), pos.offset(4, 1, 4))) {
-                if (world.getBlockState(blockPos).is(this)) {
-                    if (--i <= 0) {
+            while (iterator.hasNext()) {
+                BlockPos blockposition1 = (BlockPos) iterator.next();
+
+                if (world.getBlockState(blockposition1).is((Block) this)) {
+                    --i;
+                    if (i <= 0) {
                         return;
                     }
                 }
             }
 
-            BlockPos blockPos2 = pos.offset(random.nextInt(3) - 1, random.nextInt(2) - random.nextInt(2), random.nextInt(3) - 1);
+            BlockPos blockposition2 = pos.offset(random.nextInt(3) - 1, random.nextInt(2) - random.nextInt(2), random.nextInt(3) - 1);
+            final BlockPos sourcePos = pos; // Paper - Use correct source for mushroom block spread event
 
-            for (int k = 0; k < 4; k++) {
-                if (world.isEmptyBlock(blockPos2) && state.canSurvive(world, blockPos2)) {
-                    pos = blockPos2;
+            for (int j = 0; j < 4; ++j) {
+                if (world.isEmptyBlock(blockposition2) && state.canSurvive(world, blockposition2)) {
+                    pos = blockposition2;
                 }
 
-                blockPos2 = pos.offset(random.nextInt(3) - 1, random.nextInt(2) - random.nextInt(2), random.nextInt(3) - 1);
+                blockposition2 = pos.offset(random.nextInt(3) - 1, random.nextInt(2) - random.nextInt(2), random.nextInt(3) - 1);
             }
 
-            if (world.isEmptyBlock(blockPos2) && state.canSurvive(world, blockPos2)) {
-                world.setBlock(blockPos2, state, 2);
+            if (world.isEmptyBlock(blockposition2) && state.canSurvive(world, blockposition2)) {
+                org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, sourcePos, blockposition2, state, 2); // CraftBukkit // Paper - Use correct source for mushroom block spread event
             }
         }
+
     }
 
     @Override
@@ -80,20 +92,21 @@
 
     @Override
     protected boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
-        BlockPos blockPos = pos.below();
-        BlockState blockState = world.getBlockState(blockPos);
-        return blockState.is(BlockTags.MUSHROOM_GROW_BLOCK) || world.getRawBrightness(pos, 0) < 13 && this.mayPlaceOn(blockState, world, blockPos);
+        BlockPos blockposition1 = pos.below();
+        BlockState iblockdata1 = world.getBlockState(blockposition1);
+
+        return iblockdata1.is(BlockTags.MUSHROOM_GROW_BLOCK) ? true : world.getRawBrightness(pos, 0) < 13 && this.mayPlaceOn(iblockdata1, world, blockposition1);
     }
 
     public boolean growMushroom(ServerLevel world, BlockPos pos, BlockState state, RandomSource random) {
-        Optional<? extends Holder<ConfiguredFeature<?, ?>>> optional = world.registryAccess()
-            .registryOrThrow(Registries.CONFIGURED_FEATURE)
-            .getHolder(this.feature);
+        Optional<? extends Holder<ConfiguredFeature<?, ?>>> optional = world.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE).getHolder(this.feature);
+
         if (optional.isEmpty()) {
             return false;
         } else {
             world.removeBlock(pos, false);
-            if (optional.get().value().place(world, world.getChunkSource().getGenerator(), random, pos)) {
+            SaplingBlock.treeType = (this == Blocks.BROWN_MUSHROOM) ? TreeType.BROWN_MUSHROOM : TreeType.RED_MUSHROOM; // CraftBukkit
+            if (((ConfiguredFeature) ((Holder) optional.get()).value()).place(world, world.getChunkSource().getGenerator(), random, pos)) {
                 return true;
             } else {
                 world.setBlock(pos, state, 3);
@@ -109,7 +122,7 @@
 
     @Override
     public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) {
-        return (double)random.nextFloat() < 0.4;
+        return (double) random.nextFloat() < 0.4D;
     }
 
     @Override
