From d0c727bf60d633cb940a5f45f0d9e5dbb7897698 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Sat, 15 Nov 2025 01:35:13 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=89=B9=E6=AE=8A=E6=8C=96?= =?UTF-8?q?=E6=8E=98=E8=A1=A5=E5=81=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/network/BukkitNetworkManager.java | 1 - .../plugin/user/BukkitServerPlayer.java | 50 +++++++++++++++++-- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java index baad47fea..99cf38b5f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java @@ -1124,7 +1124,6 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes @Override public void onPacketReceive(NetWorkUser user, NMSPacketEvent event, Object packet) { BukkitServerPlayer player = (BukkitServerPlayer) user; - if (!player.isMiningBlock()) return; Object hand = FastNMS.INSTANCE.field$ServerboundSwingPacket$hand(packet); if (hand == CoreReflections.instance$InteractionHand$MAIN_HAND) { player.onSwingHand(); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java index 7137b22a5..3487d233f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java @@ -104,6 +104,7 @@ public class BukkitServerPlayer extends Player { private boolean isDestroyingBlock; private boolean isDestroyingCustomBlock; private boolean swingHandAck; + private int lastSwingHandTick; private float miningProgress; // for client visual sync private int resentSoundTick; @@ -131,6 +132,12 @@ public class BukkitServerPlayer extends Player { // selected client locale @Nullable private Locale selectedLocale; + // 存储客户端在发送停止破坏包前正在破坏的最后一个方块 + private BlockPos lastStopMiningPos; + // 修复连续挖掘的标志位 + private boolean isHackedBreak; + // 上一次停止挖掘包发出的时间 + private int lastStopMiningTick; public BukkitServerPlayer(BukkitCraftEngine plugin, @Nullable Channel channel) { this.channel = channel; @@ -518,8 +525,33 @@ public class BukkitServerPlayer extends Player { if (this.gameTicks % 20 == 0) { this.updateGUI(); } - if (this.isDestroyingBlock) { - this.tickBlockDestroy(); + if (hasSwingHand()) { + if (this.isDestroyingBlock) { + this.tickBlockDestroy(); + } else if (this.lastStopMiningPos != null && this.gameTicks - this.lastStopMiningTick <= 5) { + double range = getCachedInteractionRange(); + RayTraceResult result = platformPlayer().rayTraceBlocks(range, FluidCollisionMode.NEVER); + if (result != null) { + Block hitBlock = result.getHitBlock(); + if (hitBlock != null) { + Location location = hitBlock.getLocation(); + BlockPos hitPos = new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()); + if (hitPos.equals(this.lastStopMiningPos)) { + Object blockState = BlockStateUtils.getBlockState(hitBlock); + this.startMiningBlock(hitPos, blockState, BlockStateUtils.getOptionalCustomBlockState(blockState).orElse(null)); + this.lastStopMiningPos = null; + this.lastStopMiningTick = 0; + this.isHackedBreak = true; + } + } + } + } + this.swingHandAck = false; + } else { + if (this.isHackedBreak) { + this.abortMiningBlock(); + this.isHackedBreak = false; + } } if (Config.predictBreaking() && !this.isDestroyingCustomBlock) { // if it's not destroying blocks, we do predict @@ -607,6 +639,10 @@ public class BukkitServerPlayer extends Player { } public void startMiningBlock(BlockPos pos, Object state, @Nullable ImmutableBlockState immutableBlockState) { + if (this.isHackedBreak) { + this.isHackedBreak = false; + this.abortMiningBlock(); + } // instant break boolean custom = immutableBlockState != null; if (custom && getDestroyProgress(state, pos) >= 1f) { @@ -668,8 +704,11 @@ public class BukkitServerPlayer extends Player { } } + // 客户端觉得要停止破坏方块了 @Override public void stopMiningBlock() { + this.lastStopMiningPos = this.destroyPos; + this.lastStopMiningTick = gameTicks(); setClientSideCanBreakBlock(true); setIsDestroyingBlock(false, false); } @@ -705,8 +744,6 @@ public class BukkitServerPlayer extends Player { private void tickBlockDestroy() { // if player swings hand is this tick - if (!this.swingHandAck) return; - this.swingHandAck = false; int currentTick = gameTicks(); // optimize break speed, otherwise it would be too fast if (currentTick - this.lastSuccessfulBreak <= 5) return; @@ -863,6 +900,11 @@ public class BukkitServerPlayer extends Player { @Override public void onSwingHand() { this.swingHandAck = true; + this.lastSwingHandTick = gameTicks(); + } + + public boolean hasSwingHand() { + return this.swingHandAck && this.lastSwingHandTick + 2 > gameTicks(); } @Override