--- a/net/minecraft/world/level/block/TntBlock.java
+++ b/net/minecraft/world/level/block/TntBlock.java
@@ -3,6 +3,7 @@
 import com.mojang.serialization.MapCodec;
 import javax.annotation.Nullable;
 import net.minecraft.core.BlockPos;
+import net.minecraft.core.Holder;
 import net.minecraft.sounds.SoundEvents;
 import net.minecraft.sounds.SoundSource;
 import net.minecraft.stats.Stats;
@@ -25,43 +26,62 @@
 import net.minecraft.world.level.block.state.properties.BooleanProperty;
 import net.minecraft.world.level.gameevent.GameEvent;
 import net.minecraft.world.phys.BlockHitResult;
+// CraftBukkit start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.block.TNTPrimeEvent.PrimeCause;
+// CraftBukkit end
 
 public class TntBlock extends Block {
+
     public static final MapCodec<TntBlock> CODEC = simpleCodec(TntBlock::new);
     public static final BooleanProperty UNSTABLE = BlockStateProperties.UNSTABLE;
 
     @Override
     public MapCodec<TntBlock> codec() {
-        return CODEC;
+        return TntBlock.CODEC;
     }
 
     public TntBlock(BlockBehaviour.Properties settings) {
         super(settings);
-        this.registerDefaultState(this.defaultBlockState().setValue(UNSTABLE, Boolean.valueOf(false)));
+        this.registerDefaultState((BlockState) this.defaultBlockState().setValue(TntBlock.UNSTABLE, false));
     }
 
     @Override
     protected void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
         if (!oldState.is(state.getBlock())) {
-            if (world.hasNeighborSignal(pos)) {
-                explode(world, pos);
+            if (world.hasNeighborSignal(pos) && CraftEventFactory.callTNTPrimeEvent(world, pos, PrimeCause.REDSTONE, null, null)) { // CraftBukkit - TNTPrimeEvent
+                // Paper start - TNTPrimeEvent
+                org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
+                if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) {
+                    return;
+                }
+                // Paper end - TNTPrimeEvent
+                TntBlock.explode(world, pos);
                 world.removeBlock(pos, false);
             }
+
         }
     }
 
     @Override
     protected void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) {
-        if (world.hasNeighborSignal(pos)) {
-            explode(world, pos);
+        if (world.hasNeighborSignal(pos) && CraftEventFactory.callTNTPrimeEvent(world, pos, PrimeCause.REDSTONE, null, sourcePos)) { // CraftBukkit - TNTPrimeEvent
+            // Paper start - TNTPrimeEvent
+            org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
+            if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) {
+                return;
+            }
+            // Paper end - TNTPrimeEvent
+            TntBlock.explode(world, pos);
             world.removeBlock(pos, false);
         }
+
     }
 
     @Override
     public BlockState playerWillDestroy(Level world, BlockPos pos, BlockState state, Player player) {
-        if (!world.isClientSide() && !player.isCreative() && state.getValue(UNSTABLE)) {
-            explode(world, pos);
+        if (!world.isClientSide() && !player.isCreative() && (Boolean) state.getValue(TntBlock.UNSTABLE) && CraftEventFactory.callTNTPrimeEvent(world, pos, PrimeCause.BLOCK_BREAK, player, null)) { // CraftBukkit - TNTPrimeEvent
+            TntBlock.explode(world, pos);
         }
 
         return super.playerWillDestroy(world, pos, state, player);
@@ -70,38 +90,55 @@
     @Override
     public void wasExploded(Level world, BlockPos pos, Explosion explosion) {
         if (!world.isClientSide) {
-            PrimedTnt primedTnt = new PrimedTnt(
-                world, (double)pos.getX() + 0.5, (double)pos.getY(), (double)pos.getZ() + 0.5, explosion.getIndirectSourceEntity()
-            );
-            int i = primedTnt.getFuse();
-            primedTnt.setFuse((short)(world.random.nextInt(i / 4) + i / 8));
-            world.addFreshEntity(primedTnt);
+            // Paper start - TNTPrimeEvent
+            org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
+            org.bukkit.entity.Entity source = explosion.source != null ? explosion.source.getBukkitEntity() : null;
+            if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.EXPLOSION, source).callEvent()) {
+                return;
+            }
+            // Paper end - TNTPrimeEvent
+            PrimedTnt entitytntprimed = new PrimedTnt(world, (double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, explosion.getIndirectSourceEntity());
+            int i = entitytntprimed.getFuse();
+
+            entitytntprimed.setFuse((short) (world.random.nextInt(i / 4) + i / 8));
+            world.addFreshEntity(entitytntprimed);
         }
     }
 
     public static void explode(Level world, BlockPos pos) {
-        explode(world, pos, null);
+        TntBlock.explode(world, pos, (LivingEntity) null);
     }
 
     private static void explode(Level world, BlockPos pos, @Nullable LivingEntity igniter) {
         if (!world.isClientSide) {
-            PrimedTnt primedTnt = new PrimedTnt(world, (double)pos.getX() + 0.5, (double)pos.getY(), (double)pos.getZ() + 0.5, igniter);
-            world.addFreshEntity(primedTnt);
-            world.playSound(null, primedTnt.getX(), primedTnt.getY(), primedTnt.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F);
-            world.gameEvent(igniter, GameEvent.PRIME_FUSE, pos);
+            PrimedTnt entitytntprimed = new PrimedTnt(world, (double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, igniter);
+
+            world.addFreshEntity(entitytntprimed);
+            world.playSound((Player) null, entitytntprimed.getX(), entitytntprimed.getY(), entitytntprimed.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F);
+            world.gameEvent((Entity) igniter, (Holder) GameEvent.PRIME_FUSE, pos);
         }
     }
 
     @Override
-    protected ItemInteractionResult useItemOn(
-        ItemStack stack, BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit
-    ) {
+    protected ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
         if (!stack.is(Items.FLINT_AND_STEEL) && !stack.is(Items.FIRE_CHARGE)) {
             return super.useItemOn(stack, state, world, pos, player, hand, hit);
         } else {
-            explode(world, pos, player);
+            // CraftBukkit start - TNTPrimeEvent
+            if (!CraftEventFactory.callTNTPrimeEvent(world, pos, PrimeCause.PLAYER, player, null)) {
+                return ItemInteractionResult.CONSUME;
+            }
+            // CraftBukkit end
+            // Paper start - TNTPrimeEvent
+            org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
+            if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.ITEM, player.getBukkitEntity()).callEvent()) {
+                return ItemInteractionResult.FAIL;
+            }
+            // Paper end - TNTPrimeEvent
+            TntBlock.explode(world, pos, player);
             world.setBlock(pos, Blocks.AIR.defaultBlockState(), 11);
             Item item = stack.getItem();
+
             if (!player.isCreative()) {
                 if (stack.is(Items.FLINT_AND_STEEL)) {
                     stack.hurtAndBreak(1, player, LivingEntity.getSlotForHand(hand));
@@ -118,13 +155,26 @@
     @Override
     protected void onProjectileHit(Level world, BlockState state, BlockHitResult hit, Projectile projectile) {
         if (!world.isClientSide) {
-            BlockPos blockPos = hit.getBlockPos();
+            BlockPos blockposition = hit.getBlockPos();
             Entity entity = projectile.getOwner();
-            if (projectile.isOnFire() && projectile.mayInteract(world, blockPos)) {
-                explode(world, blockPos, entity instanceof LivingEntity ? (LivingEntity)entity : null);
-                world.removeBlock(blockPos, false);
+
+            if (projectile.isOnFire() && projectile.mayInteract(world, blockposition)) {
+                // CraftBukkit start
+                if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, state.getFluidState().createLegacyBlock()) || !CraftEventFactory.callTNTPrimeEvent(world, blockposition, PrimeCause.PROJECTILE, projectile, null)) { // Paper - fix wrong block state
+                    return;
+                }
+                // CraftBukkit end
+                // Paper start - TNTPrimeEvent
+                org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition);
+                if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.PROJECTILE, projectile.getBukkitEntity()).callEvent()) {
+                    return;
+                }
+                // Paper end - TNTPrimeEvent
+                TntBlock.explode(world, blockposition, entity instanceof LivingEntity ? (LivingEntity) entity : null);
+                world.removeBlock(blockposition, false);
             }
         }
+
     }
 
     @Override
@@ -134,6 +184,6 @@
 
     @Override
     protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
-        builder.add(UNSTABLE);
+        builder.add(TntBlock.UNSTABLE);
     }
 }
