140 lines
8.6 KiB
Diff
140 lines
8.6 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Cryptite <cryptite@gmail.com>
|
|
Date: Thu, 23 Sep 2021 08:27:21 -0500
|
|
Subject: [PATCH] Track Player throughout entire block destroy
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
|
index 12998d0e9ae0e148a155faa4468b0f78b8462cc9..b03eacbef3cf15b70ec012af0870975d3e8e8cba 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
|
@@ -441,6 +441,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((Level) this.level, pos, iblockdata, (Player) this.player);
|
|
boolean flag = this.level.removeBlock(pos, false);
|
|
|
|
@@ -465,6 +466,7 @@ public class ServerPlayerGameMode {
|
|
// CraftBukkit start
|
|
java.util.List<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 7695a5ec88023720d873f81fc36f78ad60fb9589..71d02915581326f5546b2f916259a1ec00e85961 100644
|
|
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
|
|
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
|
|
@@ -323,6 +323,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(itemactioncontext);
|
|
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 8420d615867faa717266d1edfa5a469df1b1e43f..71fca6c915f90a771e6139b985ebc51c7923778c 100644
|
|
--- a/src/main/java/net/minecraft/world/level/Level.java
|
|
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
|
@@ -176,6 +176,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) {
|
|
@@ -695,6 +716,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
|
if (!this.preventPoiUpdated) {
|
|
this.onBlockStateChange(blockposition, iblockdata1, iblockdata2);
|
|
}
|
|
+ pendingPlayerBlockEvents.remove(blockposition); // Paper
|
|
// CraftBukkit end
|
|
}
|
|
}
|
|
@@ -800,8 +822,20 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
|
public void neighborChanged(BlockPos pos, Block sourceBlock, BlockPos neighborPos) {
|
|
if (!this.isClientSide) {
|
|
BlockState iblockdata = this.getBlockState(pos);
|
|
+ org.bukkit.block.Block blockAt = world.getBlockAt(pos.getX(), pos.getY(), pos.getZ()); // Paper
|
|
|
|
try {
|
|
+ // Paper start - If this is a non-air block being set to an air block, get (remove, if exists)
|
|
+ // our PendingBlockEvent
|
|
+ if (blockAt.getType() != org.bukkit.Material.AIR && iblockdata.getMaterial() == net.minecraft.world.level.material.Material.AIR) {
|
|
+ PendingBlockEvent blockEvent = pendingPlayerBlockEvents.remove(pos);
|
|
+ if (blockEvent != null) {
|
|
+ //Would fire a future BlockDestroyedByNeighborEvent here, but must have this conditional block
|
|
+ //because it's important to remove from pendingPlayerBlockEvents
|
|
+ }
|
|
+ }
|
|
+ // Paper end
|
|
+
|
|
// CraftBukkit start
|
|
CraftWorld world = ((ServerLevel) this).getWorld();
|
|
if (world != null && ((ServerLevel)this).hasPhysicsEvent) { // Paper
|
|
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 65a163d93a293e1e0a12a300d6335a700099cac2..b1b6072ffff0e1cc2e9e1a585ad882bc70697d92 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
|
|
@@ -104,6 +104,12 @@ public class DoublePlantBlock extends BushBlock {
|
|
BlockPos blockposition1 = pos.below();
|
|
BlockState iblockdata1 = world.getBlockState(blockposition1);
|
|
|
|
+ Level.PendingBlockEvent blockEvent = world.pendingPlayerBlockEvents.remove(pos);
|
|
+ if (blockEvent != null) {
|
|
+ //Would fire a future BlockDestroyedByNeighborEvent here, but must have this conditional block
|
|
+ //because it's important to remove from pendingPlayerBlockEvents
|
|
+ }
|
|
+
|
|
if (iblockdata1.is(state.getBlock()) && iblockdata1.getValue(DoublePlantBlock.HALF) == DoubleBlockHalf.LOWER) {
|
|
BlockState iblockdata2 = iblockdata1.hasProperty(BlockStateProperties.WATERLOGGED) && (Boolean) iblockdata1.getValue(BlockStateProperties.WATERLOGGED) ? 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 83d813025efca5846538e36508a5d4fe38b02108..e1eed33f75c3118826ccd0c994325b327e20f83f 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
|
|
@@ -890,6 +890,18 @@ public abstract class BlockBehaviour {
|
|
|
|
blockposition_mutableblockposition.setWithOffset((Vec3i) pos, enumdirection);
|
|
BlockState iblockdata = world.getBlockState(blockposition_mutableblockposition);
|
|
+
|
|
+ // Paper start - Propagate the PendingBlockEvent from the current blockPos to the next block
|
|
+ // if it will break (!canSurvive)
|
|
+ if (this.getMaterial() == Material.AIR && !iblockdata.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
|
|
+
|
|
BlockState iblockdata1 = iblockdata.updateShape(enumdirection.getOpposite(), this.asState(), world, blockposition_mutableblockposition, pos);
|
|
|
|
Block.updateOrDestroy(iblockdata, iblockdata1, world, blockposition_mutableblockposition, flags, maxUpdateDepth);
|