--- a/net/minecraft/world/level/block/CakeBlock.java
+++ b/net/minecraft/world/level/block/CakeBlock.java
@@ -67,6 +_,12 @@
     ) {
         Item item = stack.getItem();
         if (stack.is(ItemTags.CANDLES) && state.getValue(BITES) == 0 && Block.byItem(item) instanceof CandleBlock candleBlock) {
+            // Paper start - call change block event
+            if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, pos, CandleCakeBlock.byCandle(candleBlock))) {
+                player.containerMenu.sendAllDataToRemote(); // update inv because candle could decrease
+                return InteractionResult.TRY_WITH_EMPTY_HAND;
+            }
+            // Paper end - call change block event
             stack.consume(1, player);
             level.playSound(null, pos, SoundEvents.CAKE_ADD_CANDLE, SoundSource.BLOCKS, 1.0F, 1.0F);
             level.setBlockAndUpdate(pos, CandleCakeBlock.byCandle(candleBlock));
@@ -97,9 +_,28 @@
         if (!player.canEat(false)) {
             return InteractionResult.PASS;
         } else {
+            // Paper start - call change block event
+            int bitesValue = state.getValue(CakeBlock.BITES);
+            final BlockState newState = bitesValue < MAX_BITES ? state.setValue(CakeBlock.BITES, bitesValue + 1) : level.getFluidState(pos).createLegacyBlock();
+            if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, pos, newState)) {
+                ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().sendHealthUpdate();
+                return InteractionResult.PASS; // return a non-consume result to cake blocks don't drop their candles
+            }
+            // Paper end - call change block event
             player.awardStat(Stats.EAT_CAKE_SLICE);
-            player.getFoodData().eat(2, 0.1F);
-            int bitesValue = state.getValue(BITES);
+            // CraftBukkit start
+            // player.getFoodData().eat(2, 0.1F);
+            int oldFoodLevel = player.getFoodData().foodLevel;
+
+            org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, 2 + oldFoodLevel);
+
+            if (!event.isCancelled()) {
+                player.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 0.1F);
+            }
+
+            ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().sendHealthUpdate();
+            // CraftBukkit end
+            // Paper - move up
             level.gameEvent(player, GameEvent.EAT, pos);
             if (bitesValue < 6) {
                 level.setBlock(pos, state.setValue(BITES, Integer.valueOf(bitesValue + 1)), 3);
