From ba817be945012b21331f5c150c72877991cb6ffd Mon Sep 17 00:00:00 2001 From: CraftBukkit/Spigot Date: Wed, 3 May 2023 20:46:43 +1000 Subject: [PATCH] SPIGOT-519: Add TNTPrimeEvent Thanks to Pokechu22 for an earlier implementation By: Jishuna --- .../core/dispenser/IDispenseBehavior.patch | 7 ++- .../net/minecraft/world/level/Explosion.patch | 23 ++++++-- .../world/level/block/BlockFire.patch | 6 +- .../world/level/block/BlockTNT.patch | 55 ++++++++++++++++++- .../craftbukkit/event/CraftEventFactory.java | 11 ++++ 5 files changed, 93 insertions(+), 9 deletions(-) diff --git a/paper-server/nms-patches/net/minecraft/core/dispenser/IDispenseBehavior.patch b/paper-server/nms-patches/net/minecraft/core/dispenser/IDispenseBehavior.patch index e81a10d269..4ab7edfcee 100644 --- a/paper-server/nms-patches/net/minecraft/core/dispenser/IDispenseBehavior.patch +++ b/paper-server/nms-patches/net/minecraft/core/dispenser/IDispenseBehavior.patch @@ -408,7 +408,7 @@ itemstack.shrink(1); if (itemstack.isEmpty()) { return new ItemStack(item); -@@ -463,14 +742,42 @@ +@@ -463,16 +742,44 @@ protected ItemStack execute(ISourceBlock isourceblock, ItemStack itemstack) { WorldServer worldserver = isourceblock.getLevel(); @@ -451,8 +451,11 @@ + } + // CraftBukkit end } else if (!BlockCampfire.canLight(iblockdata) && !CandleBlock.canLight(iblockdata) && !CandleCakeBlock.canLight(iblockdata)) { - if (iblockdata.getBlock() instanceof BlockTNT) { +- if (iblockdata.getBlock() instanceof BlockTNT) { ++ if (iblockdata.getBlock() instanceof BlockTNT && org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(worldserver, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.DISPENSER, null, isourceblock.getPos())) { // CraftBukkit - TNTPrimeEvent BlockTNT.explode(worldserver, blockposition); + worldserver.removeBlock(blockposition, false); + } else { @@ -496,12 +803,62 @@ this.setSuccess(true); WorldServer worldserver = isourceblock.getLevel(); diff --git a/paper-server/nms-patches/net/minecraft/world/level/Explosion.patch b/paper-server/nms-patches/net/minecraft/world/level/Explosion.patch index 89b88655ea..e0d192b8b9 100644 --- a/paper-server/nms-patches/net/minecraft/world/level/Explosion.patch +++ b/paper-server/nms-patches/net/minecraft/world/level/Explosion.patch @@ -86,7 +86,7 @@ double d14; if (entity instanceof EntityLiving) { -@@ -263,6 +310,51 @@ +@@ -263,11 +310,66 @@ SystemUtils.shuffle(this.toBlow, this.level.random); ObjectListIterator objectlistiterator = this.toBlow.iterator(); @@ -138,7 +138,22 @@ while (objectlistiterator.hasNext()) { BlockPosition blockposition = (BlockPosition) objectlistiterator.next(); -@@ -281,8 +373,8 @@ + IBlockData iblockdata = this.level.getBlockState(blockposition); + Block block = iblockdata.getBlock(); ++ // CraftBukkit start - TNTPrimeEvent ++ if (block instanceof net.minecraft.world.level.block.BlockTNT) { ++ Entity sourceEntity = source == null ? null : source; ++ BlockPosition sourceBlock = sourceEntity == null ? BlockPosition.containing(this.x, this.y, this.z) : null; ++ if (!CraftEventFactory.callTNTPrimeEvent(this.level, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.EXPLOSION, sourceEntity, sourceBlock)) { ++ this.level.sendBlockUpdated(blockposition, Blocks.AIR.defaultBlockState(), iblockdata, 3); // Update the block on the client ++ continue; ++ } ++ } ++ // CraftBukkit end + + if (!iblockdata.isAir()) { + BlockPosition blockposition1 = blockposition.immutable(); +@@ -281,8 +383,8 @@ TileEntity tileentity = iblockdata.hasBlockEntity() ? this.level.getBlockEntity(blockposition) : null; LootTableInfo.Builder loottableinfo_builder = (new LootTableInfo.Builder(worldserver)).withRandom(this.level.random).withParameter(LootContextParameters.ORIGIN, Vec3D.atCenterOf(blockposition)).withParameter(LootContextParameters.TOOL, ItemStack.EMPTY).withOptionalParameter(LootContextParameters.BLOCK_ENTITY, tileentity).withOptionalParameter(LootContextParameters.THIS_ENTITY, this.source); @@ -149,7 +164,7 @@ } iblockdata.spawnAfterBreak(worldserver, blockposition, ItemStack.EMPTY, flag2); -@@ -314,7 +406,11 @@ +@@ -314,7 +416,11 @@ BlockPosition blockposition2 = (BlockPosition) objectlistiterator1.next(); if (this.random.nextInt(3) == 0 && this.level.getBlockState(blockposition2).isAir() && this.level.getBlockState(blockposition2.below()).isSolidRender(this.level, blockposition2.below())) { @@ -162,7 +177,7 @@ } } } -@@ -326,6 +422,7 @@ +@@ -326,6 +432,7 @@ } private static void addBlockDrops(ObjectArrayList> objectarraylist, ItemStack itemstack, BlockPosition blockposition) { diff --git a/paper-server/nms-patches/net/minecraft/world/level/block/BlockFire.patch b/paper-server/nms-patches/net/minecraft/world/level/block/BlockFire.patch index d7e3dc9048..f59cdbff6a 100644 --- a/paper-server/nms-patches/net/minecraft/world/level/block/BlockFire.patch +++ b/paper-server/nms-patches/net/minecraft/world/level/block/BlockFire.patch @@ -114,7 +114,7 @@ } } } -@@ -234,12 +269,24 @@ +@@ -234,12 +269,28 @@ return iblockdata.hasProperty(BlockProperties.WATERLOGGED) && (Boolean) iblockdata.getValue(BlockProperties.WATERLOGGED) ? 0 : this.igniteOdds.getInt(iblockdata.getBlock()); } @@ -135,6 +135,10 @@ + if (event.isCancelled()) { + return; + } ++ ++ if (iblockdata.getBlock() instanceof BlockTNT && !CraftEventFactory.callTNTPrimeEvent(world, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.FIRE, null, sourceposition)) { ++ return; ++ } + // CraftBukkit end + if (randomsource.nextInt(j + 10) < 5 && !world.isRainingAt(blockposition)) { diff --git a/paper-server/nms-patches/net/minecraft/world/level/block/BlockTNT.patch b/paper-server/nms-patches/net/minecraft/world/level/block/BlockTNT.patch index c4f7b41b80..6cc68bb4fa 100644 --- a/paper-server/nms-patches/net/minecraft/world/level/block/BlockTNT.patch +++ b/paper-server/nms-patches/net/minecraft/world/level/block/BlockTNT.patch @@ -1,11 +1,62 @@ --- a/net/minecraft/world/level/block/BlockTNT.java +++ b/net/minecraft/world/level/block/BlockTNT.java -@@ -121,6 +121,11 @@ +@@ -25,6 +25,11 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.MovingObjectPositionBlock; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.block.TNTPrimeEvent.PrimeCause; ++// CraftBukkit end ++ + public class BlockTNT extends Block { + + public static final BlockStateBoolean UNSTABLE = BlockProperties.UNSTABLE; +@@ -37,7 +42,7 @@ + @Override + public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { + if (!iblockdata1.is(iblockdata.getBlock())) { +- if (world.hasNeighborSignal(blockposition)) { ++ if (world.hasNeighborSignal(blockposition) && CraftEventFactory.callTNTPrimeEvent(world, blockposition, PrimeCause.REDSTONE, null, null)) { // CraftBukkit - TNTPrimeEvent + explode(world, blockposition); + world.removeBlock(blockposition, false); + } +@@ -47,7 +52,7 @@ + + @Override + public void neighborChanged(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { +- if (world.hasNeighborSignal(blockposition)) { ++ if (world.hasNeighborSignal(blockposition) && CraftEventFactory.callTNTPrimeEvent(world, blockposition, PrimeCause.REDSTONE, null, blockposition1)) { // CraftBukkit - TNTPrimeEvent + explode(world, blockposition); + world.removeBlock(blockposition, false); + } +@@ -56,7 +61,7 @@ + + @Override + public void playerWillDestroy(World world, BlockPosition blockposition, IBlockData iblockdata, EntityHuman entityhuman) { +- if (!world.isClientSide() && !entityhuman.isCreative() && (Boolean) iblockdata.getValue(BlockTNT.UNSTABLE)) { ++ if (!world.isClientSide() && !entityhuman.isCreative() && (Boolean) iblockdata.getValue(BlockTNT.UNSTABLE) && CraftEventFactory.callTNTPrimeEvent(world, blockposition, PrimeCause.BLOCK_BREAK, entityhuman, null)) { // CraftBukkit - TNTPrimeEvent + explode(world, blockposition); + } + +@@ -95,6 +100,11 @@ + if (!itemstack.is(Items.FLINT_AND_STEEL) && !itemstack.is(Items.FIRE_CHARGE)) { + return super.use(iblockdata, world, blockposition, entityhuman, enumhand, movingobjectpositionblock); + } else { ++ // CraftBukkit start - TNTPrimeEvent ++ if (!CraftEventFactory.callTNTPrimeEvent(world, blockposition, PrimeCause.PLAYER, entityhuman, null)) { ++ return EnumInteractionResult.CONSUME; ++ } ++ // CraftBukkit end + explode(world, blockposition, entityhuman); + world.setBlock(blockposition, Blocks.AIR.defaultBlockState(), 11); + Item item = itemstack.getItem(); +@@ -121,6 +131,11 @@ Entity entity = iprojectile.getOwner(); if (iprojectile.isOnFire() && iprojectile.mayInteract(world, blockposition)) { + // CraftBukkit start -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(iprojectile, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(iprojectile, blockposition, Blocks.AIR.defaultBlockState()).isCancelled() || !CraftEventFactory.callTNTPrimeEvent(world, blockposition, PrimeCause.PROJECTILE, iprojectile, null)) { + return; + } + // CraftBukkit end diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java index 93bd7c6ac8..14a429cf45 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -150,6 +150,7 @@ import org.bukkit.event.block.EntityBlockFormEvent; import org.bukkit.event.block.FluidLevelChangeEvent; import org.bukkit.event.block.MoistureChangeEvent; import org.bukkit.event.block.NotePlayEvent; +import org.bukkit.event.block.TNTPrimeEvent; import org.bukkit.event.entity.AreaEffectCloudApplyEvent; import org.bukkit.event.entity.ArrowBodyCountChangeEvent; import org.bukkit.event.entity.BatToggleSleepEvent; @@ -1734,4 +1735,14 @@ public class CraftEventFactory { EntitiesUnloadEvent event = new EntitiesUnloadEvent(new CraftChunk((WorldServer) world, coords.x, coords.z), bukkitEntities); Bukkit.getPluginManager().callEvent(event); } + + public static boolean callTNTPrimeEvent(World world, BlockPosition pos, TNTPrimeEvent.PrimeCause cause, Entity causingEntity, BlockPosition causePosition) { + org.bukkit.entity.Entity bukkitEntity = (causingEntity == null) ? null : causingEntity.getBukkitEntity(); + org.bukkit.block.Block bukkitBlock = (causePosition == null) ? null : CraftBlock.at(world, causePosition); + + TNTPrimeEvent event = new TNTPrimeEvent(CraftBlock.at(world, pos), cause, bukkitEntity, bukkitBlock); + Bukkit.getPluginManager().callEvent(event); + + return !event.isCancelled(); + } }