--- a/net/minecraft/world/level/block/ChorusFlowerBlock.java
+++ b/net/minecraft/world/level/block/ChorusFlowerBlock.java
@@ -2,6 +2,7 @@
 
 import com.mojang.serialization.MapCodec;
 import com.mojang.serialization.codecs.RecordCodecBuilder;
+import java.util.Iterator;
 import javax.annotation.Nullable;
 import net.minecraft.core.BlockPos;
 import net.minecraft.core.Direction;
@@ -21,25 +22,29 @@
 import net.minecraft.world.phys.BlockHitResult;
 import net.minecraft.world.phys.shapes.VoxelShape;
 
+import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
+
 public class ChorusFlowerBlock extends Block {
-    public static final MapCodec<ChorusFlowerBlock> CODEC = RecordCodecBuilder.mapCodec(
-        instance -> instance.group(BuiltInRegistries.BLOCK.byNameCodec().fieldOf("plant").forGetter(block -> block.plant), propertiesCodec())
-                .apply(instance, ChorusFlowerBlock::new)
-    );
+
+    public static final MapCodec<ChorusFlowerBlock> CODEC = RecordCodecBuilder.mapCodec((instance) -> {
+        return instance.group(BuiltInRegistries.BLOCK.byNameCodec().fieldOf("plant").forGetter((blockchorusflower) -> {
+            return blockchorusflower.plant;
+        }), propertiesCodec()).apply(instance, ChorusFlowerBlock::new);
+    });
     public static final int DEAD_AGE = 5;
     public static final IntegerProperty AGE = BlockStateProperties.AGE_5;
-    protected static final VoxelShape BLOCK_SUPPORT_SHAPE = Block.box(1.0, 0.0, 1.0, 15.0, 15.0, 15.0);
+    protected static final VoxelShape BLOCK_SUPPORT_SHAPE = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 15.0D, 15.0D);
     private final Block plant;
 
     @Override
     public MapCodec<ChorusFlowerBlock> codec() {
-        return CODEC;
+        return ChorusFlowerBlock.CODEC;
     }
 
     protected ChorusFlowerBlock(Block plantBlock, BlockBehaviour.Properties settings) {
         super(settings);
         this.plant = plantBlock;
-        this.registerDefaultState(this.stateDefinition.any().setValue(AGE, Integer.valueOf(0)));
+        this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(ChorusFlowerBlock.AGE, 0));
     }
 
     @Override
@@ -47,109 +52,137 @@
         if (!state.canSurvive(world, pos)) {
             world.destroyBlock(pos, true);
         }
+
     }
 
     @Override
     protected boolean isRandomlyTicking(BlockState state) {
-        return state.getValue(AGE) < 5;
+        return (Integer) state.getValue(ChorusFlowerBlock.AGE) < 5;
     }
 
     @Override
     public VoxelShape getBlockSupportShape(BlockState state, BlockGetter world, BlockPos pos) {
-        return BLOCK_SUPPORT_SHAPE;
+        return ChorusFlowerBlock.BLOCK_SUPPORT_SHAPE;
     }
 
     @Override
     protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
-        BlockPos blockPos = pos.above();
-        if (world.isEmptyBlock(blockPos) && blockPos.getY() < world.getMaxBuildHeight()) {
-            int i = state.getValue(AGE);
+        BlockPos blockposition1 = pos.above();
+
+        if (world.isEmptyBlock(blockposition1) && blockposition1.getY() < world.getMaxBuildHeight()) {
+            int i = (Integer) state.getValue(ChorusFlowerBlock.AGE);
+
             if (i < 5) {
-                boolean bl = false;
-                boolean bl2 = false;
-                BlockState blockState = world.getBlockState(pos.below());
-                if (blockState.is(Blocks.END_STONE)) {
-                    bl = true;
-                } else if (blockState.is(this.plant)) {
-                    int j = 1;
+                boolean flag = false;
+                boolean flag1 = false;
+                BlockState iblockdata1 = world.getBlockState(pos.below());
+                int j;
 
-                    for (int k = 0; k < 4; k++) {
-                        BlockState blockState2 = world.getBlockState(pos.below(j + 1));
-                        if (!blockState2.is(this.plant)) {
-                            if (blockState2.is(Blocks.END_STONE)) {
-                                bl2 = true;
+                if (iblockdata1.is(Blocks.END_STONE)) {
+                    flag = true;
+                } else if (iblockdata1.is(this.plant)) {
+                    j = 1;
+
+                    for (int k = 0; k < 4; ++k) {
+                        BlockState iblockdata2 = world.getBlockState(pos.below(j + 1));
+
+                        if (!iblockdata2.is(this.plant)) {
+                            if (iblockdata2.is(Blocks.END_STONE)) {
+                                flag1 = true;
                             }
                             break;
                         }
 
-                        j++;
+                        ++j;
                     }
 
-                    if (j < 2 || j <= random.nextInt(bl2 ? 5 : 4)) {
-                        bl = true;
+                    if (j < 2 || j <= random.nextInt(flag1 ? 5 : 4)) {
+                        flag = true;
                     }
-                } else if (blockState.isAir()) {
-                    bl = true;
+                } else if (iblockdata1.isAir()) {
+                    flag = true;
                 }
 
-                if (bl && allNeighborsEmpty(world, blockPos, null) && world.isEmptyBlock(pos.above(2))) {
-                    world.setBlock(pos, ChorusPlantBlock.getStateWithConnections(world, pos, this.plant.defaultBlockState()), 2);
-                    this.placeGrownFlower(world, blockPos, i);
+                if (flag && ChorusFlowerBlock.allNeighborsEmpty(world, blockposition1, (Direction) null) && world.isEmptyBlock(pos.above(2))) {
+                    // CraftBukkit start - add event
+                    if (CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition1, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(i)), 2)) {
+                        world.setBlock(pos, ChorusPlantBlock.getStateWithConnections(world, pos, this.plant.defaultBlockState()), 2);
+                        this.placeGrownFlower(world, blockposition1, i);
+                    }
+                    // CraftBukkit end
                 } else if (i < 4) {
-                    int l = random.nextInt(4);
-                    if (bl2) {
-                        l++;
+                    j = random.nextInt(4);
+                    if (flag1) {
+                        ++j;
                     }
 
-                    boolean bl3 = false;
+                    boolean flag2 = false;
 
-                    for (int m = 0; m < l; m++) {
-                        Direction direction = Direction.Plane.HORIZONTAL.getRandomDirection(random);
-                        BlockPos blockPos2 = pos.relative(direction);
-                        if (world.isEmptyBlock(blockPos2)
-                            && world.isEmptyBlock(blockPos2.below())
-                            && allNeighborsEmpty(world, blockPos2, direction.getOpposite())) {
-                            this.placeGrownFlower(world, blockPos2, i + 1);
-                            bl3 = true;
+                    for (int l = 0; l < j; ++l) {
+                        Direction enumdirection = Direction.Plane.HORIZONTAL.getRandomDirection(random);
+                        BlockPos blockposition2 = pos.relative(enumdirection);
+
+                        if (world.isEmptyBlock(blockposition2) && world.isEmptyBlock(blockposition2.below()) && ChorusFlowerBlock.allNeighborsEmpty(world, blockposition2, enumdirection.getOpposite())) {
+                            // CraftBukkit start - add event
+                            if (CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition2, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(i + 1)), 2)) {
+                                this.placeGrownFlower(world, blockposition2, i + 1);
+                                flag2 = true;
+                            }
+                            // CraftBukkit end
                         }
                     }
 
-                    if (bl3) {
+                    if (flag2) {
                         world.setBlock(pos, ChorusPlantBlock.getStateWithConnections(world, pos, this.plant.defaultBlockState()), 2);
                     } else {
-                        this.placeDeadFlower(world, pos);
+                        // CraftBukkit start - add event
+                        if (CraftEventFactory.handleBlockGrowEvent(world, pos, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(5)), 2)) {
+                            this.placeDeadFlower(world, pos);
+                        }
+                        // CraftBukkit end
                     }
                 } else {
-                    this.placeDeadFlower(world, pos);
+                    // CraftBukkit start - add event
+                    if (CraftEventFactory.handleBlockGrowEvent(world, pos, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(5)), 2)) {
+                        this.placeDeadFlower(world, pos);
+                    }
+                    // CraftBukkit end
                 }
+
             }
         }
     }
 
     private void placeGrownFlower(Level world, BlockPos pos, int age) {
-        world.setBlock(pos, this.defaultBlockState().setValue(AGE, Integer.valueOf(age)), 2);
+        world.setBlock(pos, (BlockState) this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, age), 2);
         world.levelEvent(1033, pos, 0);
     }
 
     private void placeDeadFlower(Level world, BlockPos pos) {
-        world.setBlock(pos, this.defaultBlockState().setValue(AGE, Integer.valueOf(5)), 2);
+        world.setBlock(pos, (BlockState) this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, 5), 2);
         world.levelEvent(1034, pos, 0);
     }
 
     private static boolean allNeighborsEmpty(LevelReader world, BlockPos pos, @Nullable Direction exceptDirection) {
-        for (Direction direction : Direction.Plane.HORIZONTAL) {
-            if (direction != exceptDirection && !world.isEmptyBlock(pos.relative(direction))) {
-                return false;
+        Iterator iterator = Direction.Plane.HORIZONTAL.iterator();
+
+        Direction enumdirection1;
+
+        do {
+            if (!iterator.hasNext()) {
+                return true;
             }
-        }
 
-        return true;
+            enumdirection1 = (Direction) iterator.next();
+        } while (enumdirection1 == exceptDirection || world.isEmptyBlock(pos.relative(enumdirection1)));
+
+        return false;
     }
 
     @Override
     protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
         if (direction != Direction.UP && !state.canSurvive(world, pos)) {
-            world.scheduleTick(pos, this, 1);
+            world.scheduleTick(pos, (Block) this, 1);
         }
 
         return super.updateShape(state, direction, neighborState, world, pos, neighborPos);
@@ -157,27 +190,31 @@
 
     @Override
     protected boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
-        BlockState blockState = world.getBlockState(pos.below());
-        if (!blockState.is(this.plant) && !blockState.is(Blocks.END_STONE)) {
-            if (!blockState.isAir()) {
+        BlockState iblockdata1 = world.getBlockState(pos.below());
+
+        if (!iblockdata1.is(this.plant) && !iblockdata1.is(Blocks.END_STONE)) {
+            if (!iblockdata1.isAir()) {
                 return false;
             } else {
-                boolean bl = false;
+                boolean flag = false;
+                Iterator iterator = Direction.Plane.HORIZONTAL.iterator();
 
-                for (Direction direction : Direction.Plane.HORIZONTAL) {
-                    BlockState blockState2 = world.getBlockState(pos.relative(direction));
-                    if (blockState2.is(this.plant)) {
-                        if (bl) {
+                while (iterator.hasNext()) {
+                    Direction enumdirection = (Direction) iterator.next();
+                    BlockState iblockdata2 = world.getBlockState(pos.relative(enumdirection));
+
+                    if (iblockdata2.is(this.plant)) {
+                        if (flag) {
                             return false;
                         }
 
-                        bl = true;
-                    } else if (!blockState2.isAir()) {
+                        flag = true;
+                    } else if (!iblockdata2.isAir()) {
                         return false;
                     }
                 }
 
-                return bl;
+                return flag;
             }
         } else {
             return true;
@@ -186,68 +223,73 @@
 
     @Override
     protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
-        builder.add(AGE);
+        builder.add(ChorusFlowerBlock.AGE);
     }
 
     public static void generatePlant(LevelAccessor world, BlockPos pos, RandomSource random, int size) {
         world.setBlock(pos, ChorusPlantBlock.getStateWithConnections(world, pos, Blocks.CHORUS_PLANT.defaultBlockState()), 2);
-        growTreeRecursive(world, pos, random, pos, size, 0);
+        ChorusFlowerBlock.growTreeRecursive(world, pos, random, pos, size, 0);
     }
 
     private static void growTreeRecursive(LevelAccessor world, BlockPos pos, RandomSource random, BlockPos rootPos, int size, int layer) {
         Block block = Blocks.CHORUS_PLANT;
-        int i = random.nextInt(4) + 1;
+        int k = random.nextInt(4) + 1;
+
         if (layer == 0) {
-            i++;
+            ++k;
         }
 
-        for (int j = 0; j < i; j++) {
-            BlockPos blockPos = pos.above(j + 1);
-            if (!allNeighborsEmpty(world, blockPos, null)) {
+        for (int l = 0; l < k; ++l) {
+            BlockPos blockposition2 = pos.above(l + 1);
+
+            if (!ChorusFlowerBlock.allNeighborsEmpty(world, blockposition2, (Direction) null)) {
                 return;
             }
 
-            world.setBlock(blockPos, ChorusPlantBlock.getStateWithConnections(world, blockPos, block.defaultBlockState()), 2);
-            world.setBlock(blockPos.below(), ChorusPlantBlock.getStateWithConnections(world, blockPos.below(), block.defaultBlockState()), 2);
+            world.setBlock(blockposition2, ChorusPlantBlock.getStateWithConnections(world, blockposition2, block.defaultBlockState()), 2);
+            world.setBlock(blockposition2.below(), ChorusPlantBlock.getStateWithConnections(world, blockposition2.below(), block.defaultBlockState()), 2);
         }
 
-        boolean bl = false;
+        boolean flag = false;
+
         if (layer < 4) {
-            int k = random.nextInt(4);
+            int i1 = random.nextInt(4);
+
             if (layer == 0) {
-                k++;
+                ++i1;
             }
 
-            for (int l = 0; l < k; l++) {
-                Direction direction = Direction.Plane.HORIZONTAL.getRandomDirection(random);
-                BlockPos blockPos2 = pos.above(i).relative(direction);
-                if (Math.abs(blockPos2.getX() - rootPos.getX()) < size
-                    && Math.abs(blockPos2.getZ() - rootPos.getZ()) < size
-                    && world.isEmptyBlock(blockPos2)
-                    && world.isEmptyBlock(blockPos2.below())
-                    && allNeighborsEmpty(world, blockPos2, direction.getOpposite())) {
-                    bl = true;
-                    world.setBlock(blockPos2, ChorusPlantBlock.getStateWithConnections(world, blockPos2, block.defaultBlockState()), 2);
-                    world.setBlock(
-                        blockPos2.relative(direction.getOpposite()),
-                        ChorusPlantBlock.getStateWithConnections(world, blockPos2.relative(direction.getOpposite()), block.defaultBlockState()),
-                        2
-                    );
-                    growTreeRecursive(world, blockPos2, random, rootPos, size, layer + 1);
+            for (int j1 = 0; j1 < i1; ++j1) {
+                Direction enumdirection = Direction.Plane.HORIZONTAL.getRandomDirection(random);
+                BlockPos blockposition3 = pos.above(k).relative(enumdirection);
+
+                if (Math.abs(blockposition3.getX() - rootPos.getX()) < size && Math.abs(blockposition3.getZ() - rootPos.getZ()) < size && world.isEmptyBlock(blockposition3) && world.isEmptyBlock(blockposition3.below()) && ChorusFlowerBlock.allNeighborsEmpty(world, blockposition3, enumdirection.getOpposite())) {
+                    flag = true;
+                    world.setBlock(blockposition3, ChorusPlantBlock.getStateWithConnections(world, blockposition3, block.defaultBlockState()), 2);
+                    world.setBlock(blockposition3.relative(enumdirection.getOpposite()), ChorusPlantBlock.getStateWithConnections(world, blockposition3.relative(enumdirection.getOpposite()), block.defaultBlockState()), 2);
+                    ChorusFlowerBlock.growTreeRecursive(world, blockposition3, random, rootPos, size, layer + 1);
                 }
             }
         }
 
-        if (!bl) {
-            world.setBlock(pos.above(i), Blocks.CHORUS_FLOWER.defaultBlockState().setValue(AGE, Integer.valueOf(5)), 2);
+        if (!flag) {
+            world.setBlock(pos.above(k), (BlockState) Blocks.CHORUS_FLOWER.defaultBlockState().setValue(ChorusFlowerBlock.AGE, 5), 2);
         }
+
     }
 
     @Override
     protected void onProjectileHit(Level world, BlockState state, BlockHitResult hit, Projectile projectile) {
-        BlockPos blockPos = hit.getBlockPos();
-        if (!world.isClientSide && projectile.mayInteract(world, blockPos) && projectile.mayBreak(world)) {
-            world.destroyBlock(blockPos, true, projectile);
+        BlockPos blockposition = hit.getBlockPos();
+
+        if (!world.isClientSide && projectile.mayInteract(world, blockposition) && projectile.mayBreak(world)) {
+            // CraftBukkit
+            if (!CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, state.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
+                return;
+            }
+            // CraftBukkit end
+            world.destroyBlock(blockposition, true, projectile);
         }
+
     }
 }
