144 lines
8.9 KiB
Diff
144 lines
8.9 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Cryptite <cryptite@gmail.com>
|
|
Date: Mon, 10 Apr 2023 07:30:29 -0500
|
|
Subject: [PATCH] Add BlockDestroyedByNeighborEvent
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
|
index 34ecfb89372f459117db99d57a7edd6f681bbe8a..35d83c8ebfbf968943d103b520e0f3a83ed0ebe9 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
|
@@ -419,6 +419,7 @@ public class ServerPlayerGameMode {
|
|
org.bukkit.block.BlockState state = bblock.getState();
|
|
level.captureDrops = new ArrayList<>();
|
|
// CraftBukkit end
|
|
+ level.pendingPlayerBlockEvents.put(pos, new Level.PendingBlockEvent(pos, this.player)); // Paper
|
|
block.playerWillDestroy(this.level, pos, iblockdata, this.player);
|
|
boolean flag = this.level.removeBlock(pos, false);
|
|
|
|
@@ -447,6 +448,7 @@ public class ServerPlayerGameMode {
|
|
// CraftBukkit start
|
|
java.util.List<net.minecraft.world.entity.item.ItemEntity> itemsToDrop = level.captureDrops; // Paper - store current list
|
|
level.captureDrops = null; // Paper - Remove this earlier so that we can actually drop stuff
|
|
+ level.pendingPlayerBlockEvents.remove(pos); // Paper
|
|
if (event.isDropItems()) {
|
|
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - use stored ref
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
|
|
index ae9b821d71d2868ba4eb3c73558fdcd6caf264e3..14c04a8b9b772dc4167261edfb736407b0b867a9 100644
|
|
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
|
|
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
|
|
@@ -360,6 +360,7 @@ public final class ItemStack {
|
|
}
|
|
}
|
|
Item item = this.getItem();
|
|
+ if (entityhuman != null) world.pendingPlayerBlockEvents.put(blockposition, new Level.PendingBlockEvent(blockposition, entityhuman)); // Paper
|
|
InteractionResult enuminteractionresult = item.useOn(context);
|
|
CompoundTag newData = this.getTagClone();
|
|
int newCount = this.getCount();
|
|
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
|
index 22558f4d5ae2eba71e2392729c2c2d931741483c..a601d5b40d3556c688832fd5f392003c2aac5cef 100644
|
|
--- a/src/main/java/net/minecraft/world/level/Level.java
|
|
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
|
@@ -184,6 +184,27 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
|
public final Map<Explosion.CacheKey, Float> explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions
|
|
public java.util.ArrayDeque<net.minecraft.world.level.block.RedstoneTorchBlock.Toggle> redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here
|
|
|
|
+ // Paper start - Holder class used to track what Player is responsible the last block event
|
|
+ public static class PendingBlockEvent {
|
|
+
|
|
+ public final BlockPos block;
|
|
+ public final Player player;
|
|
+ public @Nullable BlockPos sourceBlock;
|
|
+
|
|
+ public PendingBlockEvent(BlockPos block, Player player) {
|
|
+ this(block, player, null);
|
|
+ }
|
|
+
|
|
+ public PendingBlockEvent(BlockPos block, Player player, @Nullable BlockPos sourceBlock) {
|
|
+ this.block = block;
|
|
+ this.player = player;
|
|
+ this.sourceBlock = sourceBlock;
|
|
+ }
|
|
+
|
|
+ }
|
|
+ public final Map<BlockPos, PendingBlockEvent> pendingPlayerBlockEvents = new HashMap<>();
|
|
+ // Paper end
|
|
+
|
|
// Paper start - fix and optimise world upgrading
|
|
// copied from below
|
|
public static ResourceKey<DimensionType> getDimensionKey(DimensionType manager) {
|
|
@@ -663,6 +684,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
|
if (!this.preventPoiUpdated) {
|
|
this.onBlockStateChange(blockposition, iblockdata1, iblockdata2);
|
|
}
|
|
+ pendingPlayerBlockEvents.remove(blockposition); // Paper
|
|
// CraftBukkit end
|
|
}
|
|
}
|
|
@@ -684,6 +706,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
|
if (iblockdata.isAir()) {
|
|
return false;
|
|
} else {
|
|
+ // Paper start
|
|
+ PendingBlockEvent blockEvent = pendingPlayerBlockEvents.get(pos);
|
|
+ if (blockEvent != null && blockEvent.sourceBlock != null) {
|
|
+ io.papermc.paper.event.block.BlockDestroyedByNeighborEvent event =
|
|
+ new io.papermc.paper.event.block.BlockDestroyedByNeighborEvent(org.bukkit.craftbukkit.block.CraftBlock.at(this, pos),
|
|
+ (org.bukkit.entity.Player) blockEvent.player.getBukkitEntity(),
|
|
+ org.bukkit.craftbukkit.block.CraftBlock.at(this, blockEvent.sourceBlock));
|
|
+ event.callEvent();
|
|
+ }
|
|
+ // Paper end
|
|
+
|
|
FluidState fluid = this.getFluidState(pos);
|
|
// Paper start - while the above setAir method is named same and looks very similar
|
|
// they are NOT used with same intent and the above should not fire this event. The above method is more of a BlockSetToAirEvent,
|
|
diff --git a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
|
|
index 9db66b393e057d93a8025b803ae0ad2a1bca61f6..4c7cd93daa2d4fcbf444fe7fceca9e779f883603 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
|
|
@@ -105,6 +105,15 @@ public class DoublePlantBlock extends BushBlock {
|
|
BlockPos blockposition1 = pos.below();
|
|
BlockState iblockdata1 = world.getBlockState(blockposition1);
|
|
|
|
+ Level.PendingBlockEvent blockEvent = world.pendingPlayerBlockEvents.remove(pos);
|
|
+ if (blockEvent != null) {
|
|
+ io.papermc.paper.event.block.BlockDestroyedByNeighborEvent event =
|
|
+ new io.papermc.paper.event.block.BlockDestroyedByNeighborEvent(org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition1),
|
|
+ (org.bukkit.entity.Player) blockEvent.player.getBukkitEntity(),
|
|
+ org.bukkit.craftbukkit.block.CraftBlock.at(world, pos));
|
|
+ if (!event.callEvent()) return;
|
|
+ }
|
|
+
|
|
if (iblockdata1.is(state.getBlock()) && iblockdata1.getValue(DoublePlantBlock.HALF) == DoubleBlockHalf.LOWER) {
|
|
BlockState iblockdata2 = iblockdata1.getFluidState().is((Fluid) Fluids.WATER) ? Blocks.WATER.defaultBlockState() : Blocks.AIR.defaultBlockState();
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
|
index de4c1e4701236e7d5ec77339c51ad6a9d8288bb6..4beb56de55d5584ce7f6e04ae30f7c3cffc1440e 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
|
@@ -1127,11 +1127,22 @@ public abstract class BlockBehaviour implements FeatureElement {
|
|
BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos();
|
|
Direction[] aenumdirection = BlockBehaviour.UPDATE_SHAPE_ORDER;
|
|
int k = aenumdirection.length;
|
|
+ BlockState blockState = world.getBlockState(pos); // Slice
|
|
|
|
for (int l = 0; l < k; ++l) {
|
|
Direction enumdirection = aenumdirection[l];
|
|
|
|
blockposition_mutableblockposition.setWithOffset(pos, enumdirection);
|
|
+ // Paper start - Propagate the PendingBlockEvent from the current blockPos to the next block
|
|
+ // if it will break (!canSurvive)
|
|
+ if (blockState.getBukkitMaterial() == org.bukkit.Material.AIR && !world.getBlockState(blockposition_mutableblockposition).canSurvive(world, blockposition_mutableblockposition)) {
|
|
+ Level.PendingBlockEvent blockEvent = ((Level) world).pendingPlayerBlockEvents.get(pos);
|
|
+ if (blockEvent != null) {
|
|
+ BlockPos blockPosCopy = blockposition_mutableblockposition.immutable();
|
|
+ ((Level) world).pendingPlayerBlockEvents.put(blockPosCopy, new Level.PendingBlockEvent(blockPosCopy, blockEvent.player, pos));
|
|
+ }
|
|
+ }
|
|
+ // Paper end
|
|
world.neighborShapeChanged(enumdirection.getOpposite(), this.asState(), blockposition_mutableblockposition, pos, flags, maxUpdateDepth);
|
|
}
|
|
|