Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ExplodeEvent and Improvement in Spigot Explode events #11840

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Original file line number Diff line number Diff line change
Expand Up @@ -30419,10 +30419,10 @@ index 2709803b9266ff4a2034d83321cd0ba4e30fc0aa..26c8c1e5598daf3550aef05b12218c47
ChunkAccess getChunk(int x, int z, ChunkStatus chunkStatus, boolean requireChunk);

diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java
index 3619509d51ebd2e5e36fe4b67e76c94a8d272d1b..7b132c55caf9d3c3df3b0a123f4b5bfc7ae35984 100644
index ee3a025dc10454e02d4d38f4010d566f506aff4e..cb41acc26040fae97373fb415925f6404e5ca031 100644
--- a/net/minecraft/world/level/ServerExplosion.java
+++ b/net/minecraft/world/level/ServerExplosion.java
@@ -63,6 +63,249 @@ public class ServerExplosion implements Explosion {
@@ -59,6 +59,249 @@ public class ServerExplosion implements Explosion {
public float yield;
// CraftBukkit end
public boolean excludeSourceFromDamage = true; // Paper - Allow explosions to damage source
Expand Down Expand Up @@ -30672,7 +30672,7 @@ index 3619509d51ebd2e5e36fe4b67e76c94a8d272d1b..7b132c55caf9d3c3df3b0a123f4b5bfc

public ServerExplosion(
ServerLevel level,
@@ -134,63 +377,102 @@ public class ServerExplosion implements Explosion {
@@ -130,63 +373,102 @@ public class ServerExplosion implements Explosion {
}

private List<BlockPos> calculateExplodedPositions() {
Expand Down Expand Up @@ -30822,7 +30822,7 @@ index 3619509d51ebd2e5e36fe4b67e76c94a8d272d1b..7b132c55caf9d3c3df3b0a123f4b5bfc
}

private void hurtEntities() {
@@ -371,6 +653,14 @@ public class ServerExplosion implements Explosion {
@@ -336,6 +618,14 @@ public class ServerExplosion implements Explosion {
return;
}
// CraftBukkit end
Expand All @@ -30837,7 +30837,7 @@ index 3619509d51ebd2e5e36fe4b67e76c94a8d272d1b..7b132c55caf9d3c3df3b0a123f4b5bfc
this.level.gameEvent(this.source, GameEvent.EXPLODE, this.center);
List<BlockPos> list = this.calculateExplodedPositions();
this.hurtEntities();
@@ -384,6 +674,13 @@ public class ServerExplosion implements Explosion {
@@ -357,6 +647,13 @@ public class ServerExplosion implements Explosion {
if (this.fire) {
this.createFire(list);
}
Expand All @@ -30851,7 +30851,7 @@ index 3619509d51ebd2e5e36fe4b67e76c94a8d272d1b..7b132c55caf9d3c3df3b0a123f4b5bfc
}

private static void addOrAppendStack(List<ServerExplosion.StackCollector> stackCollectors, ItemStack stack, BlockPos pos) {
@@ -474,12 +771,12 @@ public class ServerExplosion implements Explosion {
@@ -447,12 +744,12 @@ public class ServerExplosion implements Explosion {
// Paper start - Optimize explosions
private float getBlockDensity(Vec3 vec3d, Entity entity) {
if (!this.level.paperConfig().environment.optimizeExplosions) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--- a/net/minecraft/world/item/enchantment/effects/ExplodeEffect.java
+++ b/net/minecraft/world/item/enchantment/effects/ExplodeEffect.java
@@ -80,7 +_,7 @@
@Nullable
private DamageSource getDamageSource(Entity entity, Vec3 pos) {
if (this.damageType.isEmpty()) {
- return null;
+ return entity.level().damageSources().explosion(null).customEventDamager(entity); // Paper - copy null DamageSource behaviour from ServerExplosion::new to set causing entity
} else {
return this.attributeToUser ? new DamageSource(this.damageType.get(), entity) : new DamageSource(this.damageType.get(), pos);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/ServerExplosion.java
+++ b/net/minecraft/world/level/ServerExplosion.java
@@ -33,6 +_,17 @@
@@ -33,6 +_,13 @@
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;

Expand All @@ -9,10 +9,6 @@
+import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
+import net.minecraft.world.level.block.Blocks;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.craftbukkit.util.CraftLocation;
+import org.bukkit.event.entity.EntityExplodeEvent;
+import org.bukkit.Location;
+import org.bukkit.event.block.BlockExplodeEvent;
+// CraftBukkit end
+
public class ServerExplosion implements Explosion {
Expand Down Expand Up @@ -149,45 +145,14 @@
this.hitPlayers.put(player, vec3);
}
}
@@ -225,7 +_,61 @@
@@ -225,7 +_,30 @@
List<ServerExplosion.StackCollector> list = new ArrayList<>();
Util.shuffle(blocks, this.level.random);

+ // CraftBukkit start
+ org.bukkit.World bworld = this.level.getWorld();
+ Location location = CraftLocation.toBukkit(this.center, bworld);
+
+ List<org.bukkit.block.Block> blockList = new ObjectArrayList<>();
+ for (int i1 = blocks.size() - 1; i1 >= 0; i1--) {
+ BlockPos cpos = blocks.get(i1);
+ org.bukkit.block.Block bblock = bworld.getBlockAt(cpos.getX(), cpos.getY(), cpos.getZ());
+ if (!bblock.getType().isAir()) {
+ blockList.add(bblock);
+ }
+ }
+
+ List<org.bukkit.block.Block> bukkitBlocks;
+
+ if (this.source != null) {
+ EntityExplodeEvent event = CraftEventFactory.callEntityExplodeEvent(this.source, blockList, this.yield, this.getBlockInteraction());
+ this.wasCanceled = event.isCancelled();
+ bukkitBlocks = event.blockList();
+ this.yield = event.getYield();
+ } else {
+ org.bukkit.block.Block block = location.getBlock();
+ org.bukkit.block.BlockState blockState = (this.damageSource.getDirectBlockState() != null) ? this.damageSource.getDirectBlockState() : block.getState();
+ BlockExplodeEvent event = CraftEventFactory.callBlockExplodeEvent(block, blockState, blockList, this.yield, this.getBlockInteraction());
+ this.wasCanceled = event.isCancelled();
+ bukkitBlocks = event.blockList();
+ this.yield = event.getYield();
+ }
+
+ List<org.bukkit.block.Block> bukkitBlocks = CraftEventFactory.handleExplodeEvent(this, blocks);
+ blocks.clear();
+
+ for (org.bukkit.block.Block bblock : bukkitBlocks) {
+ BlockPos coords = new BlockPos(bblock.getX(), bblock.getY(), bblock.getZ());
+ blocks.add(coords);
+ }
+ blocks.addAll(bukkitBlocks.stream().map(bblock -> new BlockPos(bblock.getX(), bblock.getY(), bblock.getZ())).toList());
+
+ if (this.wasCanceled) {
+ return;
Expand Down Expand Up @@ -234,6 +199,21 @@
this.level.gameEvent(this.source, GameEvent.EXPLODE, this.center);
List<BlockPos> list = this.calculateExplodedPositions();
this.hurtEntities();
@@ -254,6 +_,14 @@
this.interactWithBlocks(list);
profilerFiller.pop();
}
+ // Paper start - handle not interacts in explosion events
+ else {
+ Util.shuffle(list, this.level.random); // CraftBukkit - Copy from calculateExplodedPositions
+ List<org.bukkit.block.Block> bukkitBlocks = CraftEventFactory.handleExplodeEvent(this, list);
+ list.clear();
+ list.addAll(bukkitBlocks.stream().map(bblock -> new BlockPos(bblock.getX(), bblock.getY(), bblock.getZ())).toList());
+ }
+ // Paper end

if (this.fire) {
this.createFire(list);
@@ -261,6 +_,7 @@
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.mojang.datafixers.util.Either;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.ArrayList;
Expand Down Expand Up @@ -53,6 +54,7 @@
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.ServerExplosion;
import net.minecraft.world.level.block.entity.SignBlockEntity;
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument;
import net.minecraft.world.level.storage.loot.LootContext;
Expand Down Expand Up @@ -93,6 +95,7 @@
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.inventory.CraftItemType;
import org.bukkit.craftbukkit.potion.CraftPotionUtil;
import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.craftbukkit.util.CraftVector;
import org.bukkit.entity.AbstractHorse;
Expand Down Expand Up @@ -2121,6 +2124,39 @@ public static boolean callEntityInteractEvent(Entity nmsEntity, Block block) {
return !event.isCancelled();
}

public static List<org.bukkit.block.Block> handleExplodeEvent(ServerExplosion serverExplosion, List<BlockPos> blockPositions) {
// First convert the blockPositionList related to explosion to Bukkit
org.bukkit.World bworld = serverExplosion.level().getWorld();

List<org.bukkit.block.Block> blockList = new ObjectArrayList<>();
for (int i1 = blockPositions.size() - 1; i1 >= 0; i1--) {
BlockPos cpos = blockPositions.get(i1);
org.bukkit.block.Block bblock = bworld.getBlockAt(cpos.getX(), cpos.getY(), cpos.getZ());
if (!bblock.getType().isAir()) {
blockList.add(bblock);
}
}

// Handle based in explosion if you need call EntityExplodeEvent or BlockExplodeEvent
List<org.bukkit.block.Block> blockListPostEvent = new ObjectArrayList<>();
if (serverExplosion.getDirectSourceEntity() != null || serverExplosion.getDamageSource().getCustomEventDamager() != null) {
EntityExplodeEvent event = CraftEventFactory.callEntityExplodeEvent((serverExplosion.getDirectSourceEntity() != null) ? serverExplosion.getDirectSourceEntity() : serverExplosion.getDamageSource().getCustomEventDamager(), blockList, serverExplosion.yield, serverExplosion.getBlockInteraction());
serverExplosion.wasCanceled = event.isCancelled();
serverExplosion.yield = event.getYield();
blockList.addAll(event.blockList());
} else {
Location location = CraftLocation.toBukkit(serverExplosion.center(), bworld);
org.bukkit.block.Block block = location.getBlock();
org.bukkit.block.BlockState blockState = (serverExplosion.getDamageSource().getDirectBlockState() != null) ? serverExplosion.getDamageSource().getDirectBlockState() : block.getState();
BlockExplodeEvent event = CraftEventFactory.callBlockExplodeEvent(block, blockState, blockList, serverExplosion.yield, serverExplosion.getBlockInteraction());
serverExplosion.wasCanceled = event.isCancelled();
serverExplosion.yield = event.getYield();
blockList.addAll(event.blockList());
}

return blockListPostEvent;
}

public static EntityExplodeEvent callEntityExplodeEvent(Entity entity, List<Block> blocks, float yield, Explosion.BlockInteraction effect) {
EntityExplodeEvent event = new EntityExplodeEvent(entity.getBukkitEntity(), entity.getBukkitEntity().getLocation(), blocks, yield, CraftExplosionResult.toBukkit(effect));
Bukkit.getPluginManager().callEvent(event);
Expand Down
Loading