--- a/net/minecraft/server/BlockCauldron.java
+++ b/net/minecraft/server/BlockCauldron.java
@@ -1,5 +1,7 @@
 package net.minecraft.server;
 
+import org.bukkit.event.block.CauldronLevelChangeEvent; // CraftBukkit
+
 public class BlockCauldron extends Block {
 
     public static final BlockStateInteger LEVEL = BlockProperties.al;
@@ -27,8 +29,13 @@
         float f = (float) blockposition.getY() + (6.0F + (float) (3 * i)) / 16.0F;
 
         if (!world.isClientSide && entity.isBurning() && i > 0 && entity.locY() <= (double) f) {
+            // CraftBukkit start
+            if (!this.changeLevel(world, blockposition, iblockdata, i - 1, entity, CauldronLevelChangeEvent.ChangeReason.EXTINGUISH)) {
+                return;
+            }
             entity.extinguish();
-            this.a(world, blockposition, iblockdata, i - 1);
+            // this.a(world, blockposition, iblockdata, i - 1);
+            // CraftBukkit end
         }
 
     }
@@ -45,18 +52,27 @@
 
             if (item == Items.WATER_BUCKET) {
                 if (i < 3 && !world.isClientSide) {
+                    // CraftBukkit start
+                    if (!this.changeLevel(world, blockposition, iblockdata, 3, entityhuman, CauldronLevelChangeEvent.ChangeReason.BUCKET_EMPTY)) {
+                        return EnumInteractionResult.SUCCESS;
+                    }
                     if (!entityhuman.abilities.canInstantlyBuild) {
                         entityhuman.a(enumhand, new ItemStack(Items.BUCKET));
                     }
 
                     entityhuman.a(StatisticList.FILL_CAULDRON);
-                    this.a(world, blockposition, iblockdata, 3);
+                    // this.a(world, blockposition, iblockdata, 3);
+                    // CraftBukkit end
                     world.playSound((EntityHuman) null, blockposition, SoundEffects.ITEM_BUCKET_EMPTY, SoundCategory.BLOCKS, 1.0F, 1.0F);
                 }
 
                 return EnumInteractionResult.SUCCESS;
             } else if (item == Items.BUCKET) {
                 if (i == 3 && !world.isClientSide) {
+                    // CraftBukkit start
+                    if (!this.changeLevel(world, blockposition, iblockdata, 0, entityhuman, CauldronLevelChangeEvent.ChangeReason.BUCKET_FILL)) {
+                        return EnumInteractionResult.SUCCESS;
+                    }
                     if (!entityhuman.abilities.canInstantlyBuild) {
                         itemstack.subtract(1);
                         if (itemstack.isEmpty()) {
@@ -67,7 +83,8 @@
                     }
 
                     entityhuman.a(StatisticList.USE_CAULDRON);
-                    this.a(world, blockposition, iblockdata, 0);
+                    // this.a(world, blockposition, iblockdata, 0);
+                    // CraftBukkit end
                     world.playSound((EntityHuman) null, blockposition, SoundEffects.ITEM_BUCKET_FILL, SoundCategory.BLOCKS, 1.0F, 1.0F);
                 }
 
@@ -77,6 +94,10 @@
 
                 if (item == Items.GLASS_BOTTLE) {
                     if (i > 0 && !world.isClientSide) {
+                        // CraftBukkit start
+                        if (!this.changeLevel(world, blockposition, iblockdata, i - 1, entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_FILL)) {
+                            return EnumInteractionResult.SUCCESS;
+                        }
                         if (!entityhuman.abilities.canInstantlyBuild) {
                             itemstack1 = PotionUtil.a(new ItemStack(Items.POTION), Potions.WATER);
                             entityhuman.a(StatisticList.USE_CAULDRON);
@@ -91,12 +112,17 @@
                         }
 
                         world.playSound((EntityHuman) null, blockposition, SoundEffects.ITEM_BOTTLE_FILL, SoundCategory.BLOCKS, 1.0F, 1.0F);
-                        this.a(world, blockposition, iblockdata, i - 1);
+                        // this.a(world, blockposition, iblockdata, i - 1);
+                        // CraftBukkit end
                     }
 
                     return EnumInteractionResult.SUCCESS;
                 } else if (item == Items.POTION && PotionUtil.d(itemstack) == Potions.WATER) {
                     if (i < 3 && !world.isClientSide) {
+                        // CraftBukkit start
+                        if (!this.changeLevel(world, blockposition, iblockdata, i + 1, entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_EMPTY)) {
+                            return EnumInteractionResult.SUCCESS;
+                        }
                         if (!entityhuman.abilities.canInstantlyBuild) {
                             itemstack1 = new ItemStack(Items.GLASS_BOTTLE);
                             entityhuman.a(StatisticList.USE_CAULDRON);
@@ -107,7 +133,8 @@
                         }
 
                         world.playSound((EntityHuman) null, blockposition, SoundEffects.ITEM_BOTTLE_EMPTY, SoundCategory.BLOCKS, 1.0F, 1.0F);
-                        this.a(world, blockposition, iblockdata, i + 1);
+                        // this.a(world, blockposition, iblockdata, i + 1);
+                        // CraftBukkit end
                     }
 
                     return EnumInteractionResult.SUCCESS;
@@ -116,8 +143,13 @@
                         IDyeable idyeable = (IDyeable) item;
 
                         if (idyeable.a(itemstack) && !world.isClientSide) {
+                            // CraftBukkit start
+                            if (!this.changeLevel(world, blockposition, iblockdata, i - 1, entityhuman, CauldronLevelChangeEvent.ChangeReason.ARMOR_WASH)) {
+                                return EnumInteractionResult.SUCCESS;
+                            }
                             idyeable.c(itemstack);
-                            this.a(world, blockposition, iblockdata, i - 1);
+                            // this.a(world, blockposition, iblockdata, i - 1);
+                            // CraftBukkit end
                             entityhuman.a(StatisticList.CLEAN_ARMOR);
                             return EnumInteractionResult.SUCCESS;
                         }
@@ -125,13 +157,18 @@
 
                     if (i > 0 && item instanceof ItemBanner) {
                         if (TileEntityBanner.b(itemstack) > 0 && !world.isClientSide) {
+                            // CraftBukkit start
+                            if (!this.changeLevel(world, blockposition, iblockdata, i - 1, entityhuman, CauldronLevelChangeEvent.ChangeReason.BANNER_WASH)) {
+                                return EnumInteractionResult.SUCCESS;
+                            }
                             itemstack1 = itemstack.cloneItemStack();
                             itemstack1.setCount(1);
                             TileEntityBanner.c(itemstack1);
                             entityhuman.a(StatisticList.CLEAN_BANNER);
                             if (!entityhuman.abilities.canInstantlyBuild) {
                                 itemstack.subtract(1);
-                                this.a(world, blockposition, iblockdata, i - 1);
+                                // this.a(world, blockposition, iblockdata, i - 1);
+                                // CraftBukkit end
                             }
 
                             if (itemstack.isEmpty()) {
@@ -169,9 +206,25 @@
         }
     }
 
+    // CraftBukkit start
     public void a(World world, BlockPosition blockposition, IBlockData iblockdata, int i) {
-        world.setTypeAndData(blockposition, (IBlockData) iblockdata.set(BlockCauldron.LEVEL, MathHelper.clamp(i, 0, 3)), 2);
+        this.changeLevel(world, blockposition, iblockdata, i, null, CauldronLevelChangeEvent.ChangeReason.UNKNOWN);
+    }
+
+    private boolean changeLevel(World world, BlockPosition blockposition, IBlockData iblockdata, int i, Entity entity, CauldronLevelChangeEvent.ChangeReason reason) {
+        int newLevel = Integer.valueOf(MathHelper.clamp(i, 0, 3));
+        CauldronLevelChangeEvent event = new CauldronLevelChangeEvent(
+                world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()),
+                (entity == null) ? null : entity.getBukkitEntity(), reason, iblockdata.get(BlockCauldron.LEVEL), newLevel
+        );
+        world.getServer().getPluginManager().callEvent(event);
+        if (event.isCancelled()) {
+            return false;
+        }
+        world.setTypeAndData(blockposition, (IBlockData) iblockdata.set(BlockCauldron.LEVEL, event.getNewLevel()), 2);
         world.updateAdjacentComparators(blockposition, this);
+        return true;
+        // CraftBukkit end
     }
 
     @Override
@@ -183,7 +236,7 @@
                 IBlockData iblockdata = world.getType(blockposition);
 
                 if ((Integer) iblockdata.get(BlockCauldron.LEVEL) < 3) {
-                    world.setTypeAndData(blockposition, (IBlockData) iblockdata.a((IBlockState) BlockCauldron.LEVEL), 2);
+                    this.a(world, blockposition, (IBlockData) iblockdata.a((IBlockState) BlockCauldron.LEVEL), 2); // CraftBukkit
                 }
 
             }
