From f532baa5d3e796126e549088e4aaed1a60b1fc96 Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Thu, 8 Aug 2024 20:24:01 -0600 Subject: [PATCH 01/29] Add PositionBreak and rename BadPacketsZ to WrongBlock --- .../checks/impl/badpackets/BadPacketsZ.java | 105 ------------------ .../checks/impl/breaking/PositionBreak.java | 74 ++++++++++++ .../checks/impl/breaking/WrongBlock.java | 89 +++++++++++++++ .../grimac/checks/type/BlockBreakCheck.java | 13 +++ .../events/packets/CheckManagerListener.java | 67 ++++++----- .../ac/grim/grimac/manager/CheckManager.java | 17 ++- .../utils/anticheat/update/BlockBreak.java | 59 ++++++++++ 7 files changed, 290 insertions(+), 134 deletions(-) delete mode 100644 src/main/java/ac/grim/grimac/checks/impl/badpackets/BadPacketsZ.java create mode 100644 src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreak.java create mode 100644 src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBlock.java create mode 100644 src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java create mode 100644 src/main/java/ac/grim/grimac/utils/anticheat/update/BlockBreak.java diff --git a/src/main/java/ac/grim/grimac/checks/impl/badpackets/BadPacketsZ.java b/src/main/java/ac/grim/grimac/checks/impl/badpackets/BadPacketsZ.java deleted file mode 100644 index d8e401e8db..0000000000 --- a/src/main/java/ac/grim/grimac/checks/impl/badpackets/BadPacketsZ.java +++ /dev/null @@ -1,105 +0,0 @@ -package ac.grim.grimac.checks.impl.badpackets; - -import ac.grim.grimac.checks.Check; -import ac.grim.grimac.checks.CheckData; -import ac.grim.grimac.checks.type.PacketCheck; -import ac.grim.grimac.player.GrimPlayer; -import ac.grim.grimac.utils.anticheat.MessageUtil; -import com.github.retrooper.packetevents.PacketEvents; -import com.github.retrooper.packetevents.event.PacketReceiveEvent; -import com.github.retrooper.packetevents.manager.server.ServerVersion; -import com.github.retrooper.packetevents.protocol.player.ClientVersion; -import com.github.retrooper.packetevents.protocol.player.DiggingAction; -import com.github.retrooper.packetevents.util.Vector3i; -import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerDigging; - -import static ac.grim.grimac.events.packets.patch.ResyncWorldUtil.resyncPosition; -import static ac.grim.grimac.utils.nmsutil.BlockBreakSpeed.getBlockDamage; - -@CheckData(name = "BadPacketsZ", experimental = true) -public class BadPacketsZ extends Check implements PacketCheck { - public BadPacketsZ(final GrimPlayer player) { - super(player); - } - - private boolean lastBlockWasInstantBreak = false; - private Vector3i lastBlock, lastCancelledBlock, lastLastBlock = null; - private final int exemptedY = player.getClientVersion().isOlderThan(ClientVersion.V_1_8) ? 255 : (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_14) ? -1 : 4095); - - // The client sometimes sends a wierd cancel packet - private boolean shouldExempt(final Vector3i pos) { - // lastLastBlock is always null when this happens, and lastBlock isn't - if (lastLastBlock != null || lastBlock == null) - return false; - - // on pre 1.14.4 clients, the YPos of this packet is always the same - if (player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4) && pos.y != exemptedY) - return false; - - // and if this block is not an instant break - return player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4) || getBlockDamage(player, pos) < 1; - } - - public void handle(PacketReceiveEvent event, WrapperPlayClientPlayerDigging dig) { - if (dig.getAction() == DiggingAction.START_DIGGING) { - final Vector3i pos = dig.getBlockPosition(); - - lastBlockWasInstantBreak = getBlockDamage(player, pos) >= 1; - lastCancelledBlock = null; - lastLastBlock = lastBlock; - lastBlock = pos; - } - - if (dig.getAction() == DiggingAction.CANCELLED_DIGGING) { - final Vector3i pos = dig.getBlockPosition(); - - if (shouldExempt(pos)) { - lastCancelledBlock = pos; - lastLastBlock = null; - lastBlock = null; - return; - } - - if (!pos.equals(lastBlock)) { - // https://github.com/GrimAnticheat/Grim/issues/1512 - if (player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4) || (!lastBlockWasInstantBreak && pos.equals(lastCancelledBlock))) { - if (flagAndAlert("action=CANCELLED_DIGGING" + ", last=" + MessageUtil.toUnlabledString(lastBlock) + ", pos=" + MessageUtil.toUnlabledString(pos))) { - if (shouldModifyPackets()) { - event.setCancelled(true); - player.onPacketCancel(); - resyncPosition(player, pos); - } - } - } - } - - lastCancelledBlock = pos; - lastLastBlock = null; - lastBlock = null; - return; - } - - if (dig.getAction() == DiggingAction.FINISHED_DIGGING) { - final Vector3i pos = dig.getBlockPosition(); - - // when a player looks away from the mined block, they send a cancel, and if they look at it again, they don't send another start. (thanks mojang!) - if (!pos.equals(lastCancelledBlock) && (!lastBlockWasInstantBreak || player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4)) && !pos.equals(lastBlock)) { - if (flagAndAlert("action=FINISHED_DIGGING" + ", last=" + MessageUtil.toUnlabledString(lastBlock) + ", pos=" + MessageUtil.toUnlabledString(pos))) { - if (shouldModifyPackets()) { - event.setCancelled(true); - player.onPacketCancel(); - resyncPosition(player, pos); - } - } - } - - lastCancelledBlock = null; - - // 1.14.4+ clients don't send another start break in protected regions - if (player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4)) { - lastLastBlock = null; - lastBlock = null; - } - } - } -} diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreak.java new file mode 100644 index 0000000000..8f78122bcf --- /dev/null +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreak.java @@ -0,0 +1,74 @@ +package ac.grim.grimac.checks.impl.breaking; + +import ac.grim.grimac.checks.CheckData; +import ac.grim.grimac.checks.type.BlockBreakCheck; +import ac.grim.grimac.player.GrimPlayer; +import ac.grim.grimac.utils.anticheat.update.BlockBreak; +import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox; +import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.player.DiggingAction; + +import java.util.Collections; + +@CheckData(name = "PositionBreak") +public class PositionBreak extends BlockBreakCheck { + public PositionBreak(GrimPlayer player) { + super(player); + } + + @Override + public void onBlockBreak(BlockBreak blockBreak) { + if (blockBreak.action == DiggingAction.CANCELLED_DIGGING) { + return; // buggy + } + + SimpleCollisionBox combined = blockBreak.getCombinedBox(); + + // Alright, now that we have the most optimal positions for each place + // Please note that minY may be lower than maxY, this is INTENTIONAL! + // Each position represents the best case scenario to have clicked + // + // We will now calculate the most optimal position for the player's head to be in + double minEyeHeight = Collections.min(player.getPossibleEyeHeights()); + double maxEyeHeight = Collections.max(player.getPossibleEyeHeights()); + // I love the idle packet, why did you remove it mojang :( + // Don't give 0.03 lenience if the player is a 1.8 player and we know they couldn't have 0.03'd because idle packet + double movementThreshold = !player.packetStateData.didLastMovementIncludePosition || player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? player.getMovementThreshold() : 0; + + SimpleCollisionBox eyePositions = new SimpleCollisionBox(player.x, player.y + minEyeHeight, player.z, player.x, player.y + maxEyeHeight, player.z); + eyePositions.expand(movementThreshold); + + // If the player is inside a block, then they can ray trace through the block and hit the other side of the block + if (eyePositions.isIntersected(combined)) { + return; + } + + // So now we have the player's possible eye positions + // So then look at the face that the player has clicked + boolean flag = false; + switch (blockBreak.face) { + case NORTH: // Z- face + flag = eyePositions.minZ > combined.minZ; + break; + case SOUTH: // Z+ face + flag = eyePositions.maxZ < combined.maxZ; + break; + case EAST: // X+ face + flag = eyePositions.maxX < combined.maxX; + break; + case WEST: // X- face + flag = eyePositions.minX > combined.minX; + break; + case UP: // Y+ face + flag = eyePositions.maxY < combined.maxY; + break; + case DOWN: // Y- face + flag = eyePositions.minY > combined.minY; + break; + } + + if (flag && flagAndAlert("action=" + blockBreak.action) && shouldModifyPackets()) { + blockBreak.cancel(); + } + } +} diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBlock.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBlock.java new file mode 100644 index 0000000000..3eef717970 --- /dev/null +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBlock.java @@ -0,0 +1,89 @@ +package ac.grim.grimac.checks.impl.breaking; + +import ac.grim.grimac.checks.CheckData; +import ac.grim.grimac.checks.type.BlockBreakCheck; +import ac.grim.grimac.checks.type.PacketCheck; +import ac.grim.grimac.player.GrimPlayer; +import ac.grim.grimac.utils.anticheat.MessageUtil; +import ac.grim.grimac.utils.anticheat.update.BlockBreak; +import com.github.retrooper.packetevents.PacketEvents; +import com.github.retrooper.packetevents.manager.server.ServerVersion; +import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.player.DiggingAction; +import com.github.retrooper.packetevents.util.Vector3i; + +import static ac.grim.grimac.utils.nmsutil.BlockBreakSpeed.getBlockDamage; + +@CheckData(name = "WrongBlock", experimental = true) +public class WrongBlock extends BlockBreakCheck implements PacketCheck { + public WrongBlock(final GrimPlayer player) { + super(player); + } + + private boolean lastBlockWasInstantBreak = false; + private Vector3i lastBlock, lastCancelledBlock, lastLastBlock = null; + private final int exemptedY = player.getClientVersion().isOlderThan(ClientVersion.V_1_8) ? 255 : (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_14) ? -1 : 4095); + + // The client sometimes sends a wierd cancel packet + private boolean shouldExempt(final Vector3i pos) { + // lastLastBlock is always null when this happens, and lastBlock isn't + if (lastLastBlock != null || lastBlock == null) + return false; + + // on pre 1.14.4 clients, the YPos of this packet is always the same + if (player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4) && pos.y != exemptedY) + return false; + + // and if this block is not an instant break + return player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4) || getBlockDamage(player, pos) < 1; + } + + @Override + public void onBlockBreak(BlockBreak blockBreak) { + if (blockBreak.action == DiggingAction.START_DIGGING) { + lastBlockWasInstantBreak = getBlockDamage(player, blockBreak.position) >= 1; + lastCancelledBlock = null; + lastLastBlock = lastBlock; + lastBlock = blockBreak.position; + } + + if (blockBreak.action == DiggingAction.CANCELLED_DIGGING) { + if (!shouldExempt(blockBreak.position)) { + if (!blockBreak.position.equals(lastBlock)) { + // https://github.com/GrimAnticheat/Grim/issues/1512 + if (player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4) || (!lastBlockWasInstantBreak && blockBreak.position.equals(lastCancelledBlock))) { + if (flagAndAlert("action=CANCELLED_DIGGING" + ", last=" + MessageUtil.toUnlabledString(lastBlock) + ", pos=" + MessageUtil.toUnlabledString(blockBreak.position))) { + if (shouldModifyPackets()) { + blockBreak.cancel(); + } + } + } + } + } + + lastCancelledBlock = blockBreak.position; + lastLastBlock = null; + lastBlock = null; + } + + if (blockBreak.action == DiggingAction.FINISHED_DIGGING) { + if (!blockBreak.position.equals(lastCancelledBlock) // https://bugs.mojang.com/browse/MC-255057 + && (!lastBlockWasInstantBreak || player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4)) + && !blockBreak.position.equals(lastBlock)) { + if (flagAndAlert("action=FINISHED_DIGGING" + ", last=" + MessageUtil.toUnlabledString(lastBlock) + ", pos=" + MessageUtil.toUnlabledString(blockBreak.position))) { + if (shouldModifyPackets()) { + blockBreak.cancel(); + } + } + } + + lastCancelledBlock = null; + + // 1.14.4+ clients don't send another start break in protected regions + if (player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4)) { + lastLastBlock = null; + lastBlock = null; + } + } + } +} diff --git a/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java b/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java new file mode 100644 index 0000000000..4b18edeb2b --- /dev/null +++ b/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java @@ -0,0 +1,13 @@ +package ac.grim.grimac.checks.type; + +import ac.grim.grimac.checks.Check; +import ac.grim.grimac.player.GrimPlayer; +import ac.grim.grimac.utils.anticheat.update.BlockBreak; + +public class BlockBreakCheck extends Check { + public BlockBreakCheck(GrimPlayer player) { + super(player); + } + + public void onBlockBreak(final BlockBreak blockBreak) {} +} diff --git a/src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java b/src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java index 610f87507b..64541401ef 100644 --- a/src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java +++ b/src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java @@ -2,7 +2,7 @@ import ac.grim.grimac.GrimAPI; import ac.grim.grimac.checks.impl.badpackets.BadPacketsX; -import ac.grim.grimac.checks.impl.badpackets.BadPacketsZ; +import ac.grim.grimac.checks.impl.breaking.WrongBlock; import ac.grim.grimac.events.packets.patch.ResyncWorldUtil; import ac.grim.grimac.player.GrimPlayer; import ac.grim.grimac.utils.anticheat.update.*; @@ -53,6 +53,8 @@ import java.util.List; import java.util.function.BiFunction; +import static ac.grim.grimac.events.packets.patch.ResyncWorldUtil.resyncPosition; + public class CheckManagerListener extends PacketListenerAbstract { public CheckManagerListener() { @@ -456,39 +458,50 @@ public void onPacketReceive(PacketReceiveEvent event) { if (event.getPacketType() == PacketType.Play.Client.PLAYER_DIGGING) { WrapperPlayClientPlayerDigging dig = new WrapperPlayClientPlayerDigging(event); - WrappedBlockState block = player.compensatedWorld.getWrappedBlockStateAt(dig.getBlockPosition()); + DiggingAction action = dig.getAction(); + + if (action == DiggingAction.START_DIGGING || action == DiggingAction.FINISHED_DIGGING || action == DiggingAction.CANCELLED_DIGGING) { + Vector3i position = dig.getBlockPosition(); + WrappedBlockState block = player.compensatedWorld.getWrappedBlockStateAt(position); - player.checkManager.getPacketCheck(BadPacketsX.class).handle(event, dig, block.getType()); - player.checkManager.getPacketCheck(BadPacketsZ.class).handle(event, dig); + BlockBreak blockBreak = new BlockBreak(position, dig.getBlockFace(), action, player, block); + player.checkManager.onBlockBreak(blockBreak); - if (dig.getAction() == DiggingAction.FINISHED_DIGGING) { - // Not unbreakable - if (!block.getType().isAir() && block.getType().getHardness() != -1.0f && !event.isCancelled()) { - player.compensatedWorld.startPredicting(); - player.compensatedWorld.updateBlock(dig.getBlockPosition().getX(), dig.getBlockPosition().getY(), dig.getBlockPosition().getZ(), 0); - player.compensatedWorld.stopPredicting(dig); + if (blockBreak.isCancelled()) { + event.setCancelled(true); + player.onPacketCancel(); + resyncPosition(player, position); } - } - if (dig.getAction() == DiggingAction.START_DIGGING && !event.isCancelled()) { - double damage = BlockBreakSpeed.getBlockDamage(player, dig.getBlockPosition()); + player.checkManager.getPacketCheck(BadPacketsX.class).handle(event, dig, block.getType()); - //Instant breaking, no damage means it is unbreakable by creative players (with swords) - if (damage >= 1) { - player.compensatedWorld.startPredicting(); - if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_13) && Materials.isWaterSource(player.getClientVersion(), block)) { - // Vanilla uses a method to grab water flowing, but as you can't break flowing water - // We can simply treat all waterlogged blocks or source blocks as source blocks - player.compensatedWorld.updateBlock(dig.getBlockPosition(), StateTypes.WATER.createBlockState(CompensatedWorld.blockVersion)); - } else { - player.compensatedWorld.updateBlock(dig.getBlockPosition().getX(), dig.getBlockPosition().getY(), dig.getBlockPosition().getZ(), 0); + if (!event.isCancelled()) { + if (action == DiggingAction.FINISHED_DIGGING) { + // Not unbreakable + if (!block.getType().isAir() && block.getType().getHardness() != -1.0f) { + player.compensatedWorld.startPredicting(); + player.compensatedWorld.updateBlock(position.x, position.y, position.z, 0); + player.compensatedWorld.stopPredicting(dig); + } + } + + if (action == DiggingAction.START_DIGGING) { + double damage = BlockBreakSpeed.getBlockDamage(player, position); + + //Instant breaking, no damage means it is unbreakable by creative players (with swords) + if (damage >= 1) { + player.compensatedWorld.startPredicting(); + if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_13) && Materials.isWaterSource(player.getClientVersion(), block)) { + // Vanilla uses a method to grab water flowing, but as you can't break flowing water + // We can simply treat all waterlogged blocks or source blocks as source blocks + player.compensatedWorld.updateBlock(position, StateTypes.WATER.createBlockState(CompensatedWorld.blockVersion)); + } else { + player.compensatedWorld.updateBlock(position.x, position.y, position.z, 0); + } + player.compensatedWorld.stopPredicting(dig); + } } - player.compensatedWorld.stopPredicting(dig); - } - } - if (!event.isCancelled()) { - if (dig.getAction() == DiggingAction.START_DIGGING || dig.getAction() == DiggingAction.FINISHED_DIGGING || dig.getAction() == DiggingAction.CANCELLED_DIGGING) { player.compensatedWorld.handleBlockBreakPrediction(dig); } } diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index c396ca0455..1286d47323 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -6,6 +6,8 @@ import ac.grim.grimac.checks.impl.aim.AimModulo360; import ac.grim.grimac.checks.impl.aim.processor.AimProcessor; import ac.grim.grimac.checks.impl.badpackets.*; +import ac.grim.grimac.checks.impl.breaking.WrongBlock; +import ac.grim.grimac.checks.impl.breaking.PositionBreak; import ac.grim.grimac.checks.impl.combat.Reach; import ac.grim.grimac.checks.impl.crash.*; import ac.grim.grimac.checks.impl.exploit.ExploitA; @@ -49,7 +51,7 @@ public class CheckManager { ClassToInstanceMap rotationCheck; ClassToInstanceMap vehicleCheck; ClassToInstanceMap prePredictionChecks; - + ClassToInstanceMap blockBreakChecks; ClassToInstanceMap blockPlaceCheck; ClassToInstanceMap postPredictionCheck; @@ -93,7 +95,6 @@ public CheckManager(GrimPlayer player) { .put(BadPacketsW.class, new BadPacketsW(player)) .put(BadPacketsX.class, new BadPacketsX(player)) .put(BadPacketsY.class, new BadPacketsY(player)) - .put(BadPacketsZ.class, new BadPacketsZ(player)) .put(FastBreak.class, new FastBreak(player)) .put(TransactionOrder.class, new TransactionOrder(player)) .put(NoSlowB.class, new NoSlowB(player)) @@ -148,6 +149,11 @@ public CheckManager(GrimPlayer player) { .put(GhostBlockMitigation.class, new GhostBlockMitigation(player)) .build(); + blockBreakChecks = new ImmutableClassToInstanceMap.Builder() + .put(WrongBlock.class, new WrongBlock(player)) + .put(PositionBreak.class, new PositionBreak(player)) + .build(); + prePredictionChecks = new ImmutableClassToInstanceMap.Builder() .put(TimerCheck.class, new TimerCheck(player)) .put(CrashA.class, new CrashA(player)) @@ -171,6 +177,7 @@ public CheckManager(GrimPlayer player) { .putAll(postPredictionCheck) .putAll(blockPlaceCheck) .putAll(prePredictionChecks) + .putAll(blockBreakChecks) .build(); } @@ -258,6 +265,12 @@ public void onBlockPlace(final BlockPlace place) { } } + public void onBlockBreak(final BlockBreak blockBreak) { + for (BlockBreakCheck check : blockBreakChecks.values()) { + check.onBlockBreak(blockBreak); + } + } + public void onPostFlyingBlockPlace(final BlockPlace place) { for (BlockPlaceCheck check : blockPlaceCheck.values()) { check.onPostFlyingBlockPlace(place); diff --git a/src/main/java/ac/grim/grimac/utils/anticheat/update/BlockBreak.java b/src/main/java/ac/grim/grimac/utils/anticheat/update/BlockBreak.java new file mode 100644 index 0000000000..949d39e6e2 --- /dev/null +++ b/src/main/java/ac/grim/grimac/utils/anticheat/update/BlockBreak.java @@ -0,0 +1,59 @@ +package ac.grim.grimac.utils.anticheat.update; + +import ac.grim.grimac.player.GrimPlayer; +import ac.grim.grimac.utils.collisions.HitboxData; +import ac.grim.grimac.utils.collisions.datatypes.CollisionBox; +import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox; +import com.github.retrooper.packetevents.protocol.player.DiggingAction; +import com.github.retrooper.packetevents.protocol.world.BlockFace; +import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState; +import com.github.retrooper.packetevents.util.Vector3i; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + + +public class BlockBreak { + public final Vector3i position; + public final BlockFace face; + public final DiggingAction action; + @Getter + private boolean cancelled; + + private final GrimPlayer player; + private final WrappedBlockState block; + + public BlockBreak(Vector3i position, BlockFace face, DiggingAction action, GrimPlayer player, WrappedBlockState block) { + this.position = position; + this.face = face; + this.action = action; + this.player = player; + this.block = block; + } + + public void cancel() { + cancelled = true; + } + + public SimpleCollisionBox getCombinedBox() { + // Alright, instead of skidding AACAdditionsPro, let's just use bounding boxes + CollisionBox placedOn = HitboxData.getBlockHitbox(player, player.getInventory().getHeldItem().getType().getPlacedType(), player.getClientVersion(), block, position.x, position.y, position.z); + + List boxes = new ArrayList<>(); + placedOn.downCast(boxes); + + SimpleCollisionBox combined = new SimpleCollisionBox(position.x, position.y, position.z); + for (SimpleCollisionBox box : boxes) { + double minX = Math.max(box.minX, combined.minX); + double minY = Math.max(box.minY, combined.minY); + double minZ = Math.max(box.minZ, combined.minZ); + double maxX = Math.min(box.maxX, combined.maxX); + double maxY = Math.min(box.maxY, combined.maxY); + double maxZ = Math.min(box.maxZ, combined.maxZ); + combined = new SimpleCollisionBox(minX, minY, minZ, maxX, maxY, maxZ); + } + + return combined; + } +} From 33d3c50a4a3684bbe4e843aa61da75ced1b17ccc Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Mon, 12 Aug 2024 18:46:20 -0600 Subject: [PATCH 02/29] add PositionBreakB for cancelled digging packets --- ...PositionBreak.java => PositionBreakA.java} | 4 +-- .../checks/impl/breaking/PositionBreakB.java | 36 +++++++++++++++++++ .../ac/grim/grimac/manager/CheckManager.java | 6 ++-- 3 files changed, 42 insertions(+), 4 deletions(-) rename src/main/java/ac/grim/grimac/checks/impl/breaking/{PositionBreak.java => PositionBreakA.java} (96%) create mode 100644 src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakB.java diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java similarity index 96% rename from src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreak.java rename to src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java index 8f78122bcf..f5159b5d25 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java @@ -11,8 +11,8 @@ import java.util.Collections; @CheckData(name = "PositionBreak") -public class PositionBreak extends BlockBreakCheck { - public PositionBreak(GrimPlayer player) { +public class PositionBreakA extends BlockBreakCheck { + public PositionBreakA(GrimPlayer player) { super(player); } diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakB.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakB.java new file mode 100644 index 0000000000..30afd34ce1 --- /dev/null +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakB.java @@ -0,0 +1,36 @@ +package ac.grim.grimac.checks.impl.breaking; + +import ac.grim.grimac.checks.CheckData; +import ac.grim.grimac.checks.type.BlockBreakCheck; +import ac.grim.grimac.player.GrimPlayer; +import ac.grim.grimac.utils.anticheat.update.BlockBreak; +import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.player.DiggingAction; +import com.github.retrooper.packetevents.protocol.world.BlockFace; + +@CheckData(name = "PositionBreakB") +public class PositionBreakB extends BlockBreakCheck { + public PositionBreakB(GrimPlayer player) { + super(player); + } + + private BlockFace lastFace; + private final BlockFace releaseFace = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8) ? BlockFace.DOWN : BlockFace.SOUTH; + + @Override + public void onBlockBreak(BlockBreak blockBreak) { + if (blockBreak.action == DiggingAction.START_DIGGING) { + if (blockBreak.face == lastFace) { + lastFace = null; + } + } + + if (lastFace != null) { + flagAndAlert(); + } + + if (blockBreak.action == DiggingAction.CANCELLED_DIGGING) { + lastFace = blockBreak.face == releaseFace ? null : blockBreak.face; + } + } +} diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index 1286d47323..5273814a7e 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -6,8 +6,9 @@ import ac.grim.grimac.checks.impl.aim.AimModulo360; import ac.grim.grimac.checks.impl.aim.processor.AimProcessor; import ac.grim.grimac.checks.impl.badpackets.*; +import ac.grim.grimac.checks.impl.breaking.PositionBreakB; import ac.grim.grimac.checks.impl.breaking.WrongBlock; -import ac.grim.grimac.checks.impl.breaking.PositionBreak; +import ac.grim.grimac.checks.impl.breaking.PositionBreakA; import ac.grim.grimac.checks.impl.combat.Reach; import ac.grim.grimac.checks.impl.crash.*; import ac.grim.grimac.checks.impl.exploit.ExploitA; @@ -151,7 +152,8 @@ public CheckManager(GrimPlayer player) { blockBreakChecks = new ImmutableClassToInstanceMap.Builder() .put(WrongBlock.class, new WrongBlock(player)) - .put(PositionBreak.class, new PositionBreak(player)) + .put(PositionBreakA.class, new PositionBreakA(player)) + .put(PositionBreakB.class, new PositionBreakB(player)) .build(); prePredictionChecks = new ImmutableClassToInstanceMap.Builder() From 38179ee29b3262f15d8c27d365d7dce6002a418f Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Mon, 12 Aug 2024 18:47:13 -0600 Subject: [PATCH 03/29] fix import order --- src/main/java/ac/grim/grimac/manager/CheckManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index 5273814a7e..a542b4d9d8 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -6,9 +6,9 @@ import ac.grim.grimac.checks.impl.aim.AimModulo360; import ac.grim.grimac.checks.impl.aim.processor.AimProcessor; import ac.grim.grimac.checks.impl.badpackets.*; +import ac.grim.grimac.checks.impl.breaking.PositionBreakA; import ac.grim.grimac.checks.impl.breaking.PositionBreakB; import ac.grim.grimac.checks.impl.breaking.WrongBlock; -import ac.grim.grimac.checks.impl.breaking.PositionBreakA; import ac.grim.grimac.checks.impl.combat.Reach; import ac.grim.grimac.checks.impl.crash.*; import ac.grim.grimac.checks.impl.exploit.ExploitA; From 43c02072ac88beb543f16ddb2c61ef53a9b70d8b Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Mon, 12 Aug 2024 18:56:26 -0600 Subject: [PATCH 04/29] rename BadPacketsX to LiquidAirBreak --- .../checks/impl/badpackets/BadPacketsX.java | 44 ------------------- .../checks/impl/breaking/LiquidAirBreak.java | 44 +++++++++++++++++++ .../events/packets/CheckManagerListener.java | 4 -- .../ac/grim/grimac/manager/CheckManager.java | 3 +- .../utils/anticheat/update/BlockBreak.java | 3 +- 5 files changed, 47 insertions(+), 51 deletions(-) delete mode 100644 src/main/java/ac/grim/grimac/checks/impl/badpackets/BadPacketsX.java create mode 100644 src/main/java/ac/grim/grimac/checks/impl/breaking/LiquidAirBreak.java diff --git a/src/main/java/ac/grim/grimac/checks/impl/badpackets/BadPacketsX.java b/src/main/java/ac/grim/grimac/checks/impl/badpackets/BadPacketsX.java deleted file mode 100644 index 1986e6fb93..0000000000 --- a/src/main/java/ac/grim/grimac/checks/impl/badpackets/BadPacketsX.java +++ /dev/null @@ -1,44 +0,0 @@ -package ac.grim.grimac.checks.impl.badpackets; - -import ac.grim.grimac.checks.Check; -import ac.grim.grimac.checks.CheckData; -import ac.grim.grimac.checks.type.PacketCheck; -import ac.grim.grimac.player.GrimPlayer; -import ac.grim.grimac.utils.nmsutil.BlockBreakSpeed; -import com.github.retrooper.packetevents.event.PacketReceiveEvent; -import com.github.retrooper.packetevents.protocol.item.type.ItemTypes; -import com.github.retrooper.packetevents.protocol.player.ClientVersion; -import com.github.retrooper.packetevents.protocol.player.DiggingAction; -import com.github.retrooper.packetevents.protocol.world.states.type.StateType; -import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; -import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerDigging; - -@CheckData(name = "BadPacketsX", experimental = true) -public class BadPacketsX extends Check implements PacketCheck { - public BadPacketsX(GrimPlayer player) { - super(player); - } - - public final boolean noFireHitbox = player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_15_2); - - public final void handle(PacketReceiveEvent event, WrapperPlayClientPlayerDigging dig, StateType block) { - if (dig.getAction() != DiggingAction.START_DIGGING && dig.getAction() != DiggingAction.FINISHED_DIGGING) - return; - - // the block does not have a hitbox - boolean invalid = (block == StateTypes.LIGHT && !(player.getInventory().getHeldItem().is(ItemTypes.LIGHT) || player.getInventory().getOffHand().is(ItemTypes.LIGHT))) - || block.isAir() - || block == StateTypes.WATER - || block == StateTypes.LAVA - || block == StateTypes.BUBBLE_COLUMN - || block == StateTypes.MOVING_PISTON - || (block == StateTypes.FIRE && noFireHitbox) - // or the client claims to have broken an unbreakable block - || block.getHardness() == -1.0f && dig.getAction() == DiggingAction.FINISHED_DIGGING; - - if (invalid && flagAndAlert("block=" + block.getName() + ", type=" + dig.getAction()) && shouldModifyPackets()) { - event.setCancelled(true); - player.onPacketCancel(); - } - } -} diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/LiquidAirBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/LiquidAirBreak.java new file mode 100644 index 0000000000..a00e4f3b51 --- /dev/null +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/LiquidAirBreak.java @@ -0,0 +1,44 @@ +package ac.grim.grimac.checks.impl.breaking; + +import ac.grim.grimac.checks.CheckData; +import ac.grim.grimac.checks.type.BlockBreakCheck; +import ac.grim.grimac.player.GrimPlayer; +import ac.grim.grimac.utils.anticheat.update.BlockBreak; +import com.github.retrooper.packetevents.protocol.item.type.ItemTypes; +import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.player.DiggingAction; +import com.github.retrooper.packetevents.protocol.world.states.type.StateType; +import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; + +@CheckData(name = "LiquidAirBreak", experimental = true) +public class LiquidAirBreak extends BlockBreakCheck { + public LiquidAirBreak(GrimPlayer player) { + super(player); + } + + public final boolean noFireHitbox = player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_15_2); + + @Override + public void onBlockBreak(BlockBreak blockBreak) { + if (blockBreak.action == DiggingAction.CANCELLED_DIGGING) { + return; + } + + final StateType block = blockBreak.block.getType(); + + // the block does not have a hitbox + final boolean invalid = block == StateTypes.LIGHT && !player.getInventory().getHeldItem().is(ItemTypes.LIGHT) && !player.getInventory().getOffHand().is(ItemTypes.LIGHT) + || block.isAir() + || block == StateTypes.WATER + || block == StateTypes.LAVA + || block == StateTypes.BUBBLE_COLUMN + || block == StateTypes.MOVING_PISTON + || block == StateTypes.FIRE && noFireHitbox + // or the client claims to have broken an unbreakable block + || block.getHardness() == -1.0f && blockBreak.action == DiggingAction.FINISHED_DIGGING; + + if (invalid && flagAndAlert("block=" + block.getName() + ", type=" + blockBreak.action) && shouldModifyPackets()) { + blockBreak.cancel(); + } + } +} diff --git a/src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java b/src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java index 64541401ef..25880f141d 100644 --- a/src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java +++ b/src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java @@ -1,8 +1,6 @@ package ac.grim.grimac.events.packets; import ac.grim.grimac.GrimAPI; -import ac.grim.grimac.checks.impl.badpackets.BadPacketsX; -import ac.grim.grimac.checks.impl.breaking.WrongBlock; import ac.grim.grimac.events.packets.patch.ResyncWorldUtil; import ac.grim.grimac.player.GrimPlayer; import ac.grim.grimac.utils.anticheat.update.*; @@ -473,8 +471,6 @@ public void onPacketReceive(PacketReceiveEvent event) { resyncPosition(player, position); } - player.checkManager.getPacketCheck(BadPacketsX.class).handle(event, dig, block.getType()); - if (!event.isCancelled()) { if (action == DiggingAction.FINISHED_DIGGING) { // Not unbreakable diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index a542b4d9d8..323be2aec4 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -6,6 +6,7 @@ import ac.grim.grimac.checks.impl.aim.AimModulo360; import ac.grim.grimac.checks.impl.aim.processor.AimProcessor; import ac.grim.grimac.checks.impl.badpackets.*; +import ac.grim.grimac.checks.impl.breaking.LiquidAirBreak; import ac.grim.grimac.checks.impl.breaking.PositionBreakA; import ac.grim.grimac.checks.impl.breaking.PositionBreakB; import ac.grim.grimac.checks.impl.breaking.WrongBlock; @@ -94,7 +95,6 @@ public CheckManager(GrimPlayer player) { .put(BadPacketsU.class, new BadPacketsU(player)) .put(BadPacketsV.class, new BadPacketsV(player)) .put(BadPacketsW.class, new BadPacketsW(player)) - .put(BadPacketsX.class, new BadPacketsX(player)) .put(BadPacketsY.class, new BadPacketsY(player)) .put(FastBreak.class, new FastBreak(player)) .put(TransactionOrder.class, new TransactionOrder(player)) @@ -152,6 +152,7 @@ public CheckManager(GrimPlayer player) { blockBreakChecks = new ImmutableClassToInstanceMap.Builder() .put(WrongBlock.class, new WrongBlock(player)) + .put(LiquidAirBreak.class, new LiquidAirBreak(player)) .put(PositionBreakA.class, new PositionBreakA(player)) .put(PositionBreakB.class, new PositionBreakB(player)) .build(); diff --git a/src/main/java/ac/grim/grimac/utils/anticheat/update/BlockBreak.java b/src/main/java/ac/grim/grimac/utils/anticheat/update/BlockBreak.java index 949d39e6e2..af08f545db 100644 --- a/src/main/java/ac/grim/grimac/utils/anticheat/update/BlockBreak.java +++ b/src/main/java/ac/grim/grimac/utils/anticheat/update/BlockBreak.java @@ -13,7 +13,6 @@ import java.util.ArrayList; import java.util.List; - public class BlockBreak { public final Vector3i position; public final BlockFace face; @@ -22,7 +21,7 @@ public class BlockBreak { private boolean cancelled; private final GrimPlayer player; - private final WrappedBlockState block; + public final WrappedBlockState block; public BlockBreak(Vector3i position, BlockFace face, DiggingAction action, GrimPlayer player, WrappedBlockState block) { this.position = position; From fb58ad75638c6b63cba20a9051efbd231747ed9d Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Mon, 12 Aug 2024 18:59:59 -0600 Subject: [PATCH 05/29] Add breaking checks to punishments.yml --- src/main/resources/punishments/de.yml | 2 ++ src/main/resources/punishments/en.yml | 2 ++ src/main/resources/punishments/es.yml | 2 ++ src/main/resources/punishments/fr.yml | 2 ++ src/main/resources/punishments/it.yml | 2 ++ src/main/resources/punishments/nl.yml | 2 ++ src/main/resources/punishments/pt.yml | 2 ++ src/main/resources/punishments/ru.yml | 2 ++ src/main/resources/punishments/zh.yml | 2 ++ 9 files changed, 18 insertions(+) diff --git a/src/main/resources/punishments/de.yml b/src/main/resources/punishments/de.yml index ffb36b28d9..5ba4ed128f 100644 --- a/src/main/resources/punishments/de.yml +++ b/src/main/resources/punishments/de.yml @@ -71,6 +71,8 @@ Punishments: - "EntityControl" - "NoSlow" - "Place" + - "Break" + - "WrongBlock" - "Baritone" - "FastBreak" - "TransactionOrder" diff --git a/src/main/resources/punishments/en.yml b/src/main/resources/punishments/en.yml index 00f6e842c5..0a96555b5a 100644 --- a/src/main/resources/punishments/en.yml +++ b/src/main/resources/punishments/en.yml @@ -71,6 +71,8 @@ Punishments: - "EntityControl" - "NoSlow" - "Place" + - "Break" + - "WrongBlock" - "Baritone" - "FastBreak" - "TransactionOrder" diff --git a/src/main/resources/punishments/es.yml b/src/main/resources/punishments/es.yml index d8542bf0b1..f1c4674303 100644 --- a/src/main/resources/punishments/es.yml +++ b/src/main/resources/punishments/es.yml @@ -71,6 +71,8 @@ Punishments: - "EntityControl" - "NoSlow" - "Place" + - "Break" + - "WrongBlock" - "Baritone" - "FastBreak" - "TransactionOrder" diff --git a/src/main/resources/punishments/fr.yml b/src/main/resources/punishments/fr.yml index f1113cc77a..0504a2b175 100644 --- a/src/main/resources/punishments/fr.yml +++ b/src/main/resources/punishments/fr.yml @@ -71,6 +71,8 @@ Punishments: - "EntityControl" - "NoSlow" - "Place" + - "Break" + - "WrongBlock" - "Baritone" - "FastBreak" - "TransactionOrder" diff --git a/src/main/resources/punishments/it.yml b/src/main/resources/punishments/it.yml index 4521e1622e..50e384c890 100644 --- a/src/main/resources/punishments/it.yml +++ b/src/main/resources/punishments/it.yml @@ -58,6 +58,8 @@ Punishments: - "EntityControl" - "NoSlow" - "Place" + - "Break" + - "WrongBlock" - "Baritone" - "FastBreak" - "TransactionOrder" diff --git a/src/main/resources/punishments/nl.yml b/src/main/resources/punishments/nl.yml index 1f0c8075cc..0817a2bff2 100644 --- a/src/main/resources/punishments/nl.yml +++ b/src/main/resources/punishments/nl.yml @@ -71,6 +71,8 @@ Punishments: - "EntityControl" - "NoSlow" - "Place" + - "Break" + - "WrongBlock" - "Baritone" - "FastBreak" - "TransactionOrder" diff --git a/src/main/resources/punishments/pt.yml b/src/main/resources/punishments/pt.yml index d6e811564e..c5fef0b0a4 100644 --- a/src/main/resources/punishments/pt.yml +++ b/src/main/resources/punishments/pt.yml @@ -71,6 +71,8 @@ Punishments: - "EntityControl" - "NoSlow" - "Place" + - "Break" + - "WrongBlock" - "Baritone" - "FastBreak" - "TransactionOrder" diff --git a/src/main/resources/punishments/ru.yml b/src/main/resources/punishments/ru.yml index 1486066fe0..7068494337 100644 --- a/src/main/resources/punishments/ru.yml +++ b/src/main/resources/punishments/ru.yml @@ -71,6 +71,8 @@ Punishments: - "EntityControl" - "NoSlow" - "Place" + - "Break" + - "WrongBlock" - "Baritone" - "FastBreak" - "TransactionOrder" diff --git a/src/main/resources/punishments/zh.yml b/src/main/resources/punishments/zh.yml index 76b60092be..446fde5943 100644 --- a/src/main/resources/punishments/zh.yml +++ b/src/main/resources/punishments/zh.yml @@ -71,6 +71,8 @@ Punishments: - "EntityControl" - "NoSlow" - "Place" + - "Break" + - "WrongBlock" - "Baritone" - "FastBreak" - "TransactionOrder" From 3658ff4b2486efb4e21b6ff6e7a96cc87409e615 Mon Sep 17 00:00:00 2001 From: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com> Date: Tue, 13 Aug 2024 22:39:54 -0600 Subject: [PATCH 06/29] Fix PositionBreakA check name --- .../ac/grim/grimac/checks/impl/breaking/PositionBreakA.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java index f5159b5d25..8a4667e052 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java @@ -10,7 +10,7 @@ import java.util.Collections; -@CheckData(name = "PositionBreak") +@CheckData(name = "PositionBreakA") public class PositionBreakA extends BlockBreakCheck { public PositionBreakA(GrimPlayer player) { super(player); From 5083c954fcd7f7f1fe8d5efc8fd07098974b3824 Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Sun, 1 Sep 2024 17:01:52 -0600 Subject: [PATCH 07/29] rewrite fastbreak kept old fastbreak for 1.9+ --- .../checks/impl/breaking/FastBreak.java | 56 +++++++++++++++++++ .../{FastBreak.java => OldFastBreak.java} | 13 +++-- .../grimac/checks/type/BlockBreakCheck.java | 2 +- .../ac/grim/grimac/manager/CheckManager.java | 13 +++-- 4 files changed, 72 insertions(+), 12 deletions(-) create mode 100644 src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java rename src/main/java/ac/grim/grimac/checks/impl/misc/{FastBreak.java => OldFastBreak.java} (93%) diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java new file mode 100644 index 0000000000..585d477c03 --- /dev/null +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java @@ -0,0 +1,56 @@ +package ac.grim.grimac.checks.impl.breaking; + +import ac.grim.grimac.checks.CheckData; +import ac.grim.grimac.checks.type.BlockBreakCheck; +import ac.grim.grimac.player.GrimPlayer; +import ac.grim.grimac.utils.anticheat.update.BlockBreak; +import ac.grim.grimac.utils.nmsutil.BlockBreakSpeed; +import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.player.DiggingAction; +import com.github.retrooper.packetevents.util.Vector3i; +import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; + +@CheckData(name = "FastBreak") +public class FastBreak extends BlockBreakCheck { + public FastBreak(GrimPlayer playerData) { + super(playerData); + } + + private Vector3i targetBlock = null; + private double progress; + + @Override + public void onBlockBreak(BlockBreak blockBreak) { + if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9)) { + return; + } + + if (blockBreak.action == DiggingAction.START_DIGGING) { + targetBlock = blockBreak.position; + progress = BlockBreakSpeed.getBlockDamage(player, targetBlock); + } + + if (blockBreak.action == DiggingAction.FINISHED_DIGGING && progress < 1) { + if (flagAndAlert(String.format("progress=%.2f", progress)) && shouldModifyPackets()) { + blockBreak.cancel(); + player.onPacketCancel(); + } + } + + if (blockBreak.action == DiggingAction.CANCELLED_DIGGING && player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4)) { + progress = 0; + } + } + + @Override + public void onPacketReceive(PacketReceiveEvent event) { + if (targetBlock == null) { + return; + } + + if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) { + progress += BlockBreakSpeed.getBlockDamage(player, targetBlock); + } + } +} diff --git a/src/main/java/ac/grim/grimac/checks/impl/misc/FastBreak.java b/src/main/java/ac/grim/grimac/checks/impl/misc/OldFastBreak.java similarity index 93% rename from src/main/java/ac/grim/grimac/checks/impl/misc/FastBreak.java rename to src/main/java/ac/grim/grimac/checks/impl/misc/OldFastBreak.java index 2bf67f94fa..f4960cfdd5 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/misc/FastBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/misc/OldFastBreak.java @@ -29,9 +29,9 @@ // Based loosely off of Hawk BlockBreakSpeedSurvival // Also based loosely off of NoCheatPlus FastBreak // Also based off minecraft wiki: https://minecraft.wiki/w/Breaking#Instant_breaking -@CheckData(name = "FastBreak", experimental = false) -public class FastBreak extends Check implements PacketCheck { - public FastBreak(GrimPlayer playerData) { +@CheckData(name = "OldFastBreak") +public class OldFastBreak extends Check implements PacketCheck { + public OldFastBreak(GrimPlayer playerData) { super(playerData); } @@ -51,9 +51,12 @@ public FastBreak(GrimPlayer playerData) { @Override public void onPacketReceive(PacketReceiveEvent event) { + if (player.getClientVersion().isOlderThan(ClientVersion.V_1_9)) { + return; + } + // Find the most optimal block damage using the animation packet, which is sent at least once a tick when breaking blocks - // On 1.8 clients, via screws with this packet meaning we must fall back to the 1.8 idle flying packet - if ((player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? event.getPacketType() == PacketType.Play.Client.ANIMATION : WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) && targetBlock != null) { + if (event.getPacketType() == PacketType.Play.Client.ANIMATION && targetBlock != null) { maximumBlockDamage = Math.max(maximumBlockDamage, BlockBreakSpeed.getBlockDamage(player, targetBlock)); } diff --git a/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java b/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java index 4b18edeb2b..968b61dc86 100644 --- a/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java +++ b/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java @@ -4,7 +4,7 @@ import ac.grim.grimac.player.GrimPlayer; import ac.grim.grimac.utils.anticheat.update.BlockBreak; -public class BlockBreakCheck extends Check { +public class BlockBreakCheck extends Check implements PacketCheck { public BlockBreakCheck(GrimPlayer player) { super(player); } diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index 323be2aec4..263cd5e2ee 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -6,17 +6,14 @@ import ac.grim.grimac.checks.impl.aim.AimModulo360; import ac.grim.grimac.checks.impl.aim.processor.AimProcessor; import ac.grim.grimac.checks.impl.badpackets.*; -import ac.grim.grimac.checks.impl.breaking.LiquidAirBreak; -import ac.grim.grimac.checks.impl.breaking.PositionBreakA; -import ac.grim.grimac.checks.impl.breaking.PositionBreakB; -import ac.grim.grimac.checks.impl.breaking.WrongBlock; +import ac.grim.grimac.checks.impl.breaking.*; import ac.grim.grimac.checks.impl.combat.Reach; import ac.grim.grimac.checks.impl.crash.*; import ac.grim.grimac.checks.impl.exploit.ExploitA; import ac.grim.grimac.checks.impl.exploit.ExploitB; import ac.grim.grimac.checks.impl.groundspoof.NoFallA; import ac.grim.grimac.checks.impl.misc.ClientBrand; -import ac.grim.grimac.checks.impl.misc.FastBreak; +import ac.grim.grimac.checks.impl.misc.OldFastBreak; import ac.grim.grimac.checks.impl.misc.GhostBlockMitigation; import ac.grim.grimac.checks.impl.misc.TransactionOrder; import ac.grim.grimac.checks.impl.movement.*; @@ -96,7 +93,7 @@ public CheckManager(GrimPlayer player) { .put(BadPacketsV.class, new BadPacketsV(player)) .put(BadPacketsW.class, new BadPacketsW(player)) .put(BadPacketsY.class, new BadPacketsY(player)) - .put(FastBreak.class, new FastBreak(player)) + .put(OldFastBreak.class, new OldFastBreak(player)) .put(TransactionOrder.class, new TransactionOrder(player)) .put(NoSlowB.class, new NoSlowB(player)) .put(SetbackBlocker.class, new SetbackBlocker(player)) // Must be last class otherwise we can't check while blocking packets @@ -155,6 +152,7 @@ public CheckManager(GrimPlayer player) { .put(LiquidAirBreak.class, new LiquidAirBreak(player)) .put(PositionBreakA.class, new PositionBreakA(player)) .put(PositionBreakB.class, new PositionBreakB(player)) + .put(FastBreak.class, new FastBreak(player)) .build(); prePredictionChecks = new ImmutableClassToInstanceMap.Builder() @@ -215,6 +213,9 @@ public void onPacketReceive(final PacketReceiveEvent packet) { for (BlockPlaceCheck check : blockPlaceCheck.values()) { check.onPacketReceive(packet); } + for (BlockBreakCheck check : blockBreakChecks.values()) { + check.onPacketReceive(packet); + } } public void onPacketSend(final PacketSendEvent packet) { From b61d1cbaece7c89d645ecea26f4fdfe3a7dc789a Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Tue, 3 Sep 2024 16:52:25 -0600 Subject: [PATCH 08/29] make BlockBreakCheck an interface --- .../ac/grim/grimac/checks/impl/breaking/FastBreak.java | 3 ++- .../grimac/checks/impl/breaking/LiquidAirBreak.java | 3 ++- .../grimac/checks/impl/breaking/PositionBreakA.java | 3 ++- .../grimac/checks/impl/breaking/PositionBreakB.java | 3 ++- .../grim/grimac/checks/impl/breaking/WrongBlock.java | 4 ++-- .../ac/grim/grimac/checks/type/BlockBreakCheck.java | 10 ++-------- 6 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java index 585d477c03..4b640e4d05 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java @@ -1,5 +1,6 @@ package ac.grim.grimac.checks.impl.breaking; +import ac.grim.grimac.checks.Check; import ac.grim.grimac.checks.CheckData; import ac.grim.grimac.checks.type.BlockBreakCheck; import ac.grim.grimac.player.GrimPlayer; @@ -12,7 +13,7 @@ import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; @CheckData(name = "FastBreak") -public class FastBreak extends BlockBreakCheck { +public class FastBreak extends Check implements BlockBreakCheck { public FastBreak(GrimPlayer playerData) { super(playerData); } diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/LiquidAirBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/LiquidAirBreak.java index a00e4f3b51..d066c9a239 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/LiquidAirBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/LiquidAirBreak.java @@ -1,5 +1,6 @@ package ac.grim.grimac.checks.impl.breaking; +import ac.grim.grimac.checks.Check; import ac.grim.grimac.checks.CheckData; import ac.grim.grimac.checks.type.BlockBreakCheck; import ac.grim.grimac.player.GrimPlayer; @@ -11,7 +12,7 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; @CheckData(name = "LiquidAirBreak", experimental = true) -public class LiquidAirBreak extends BlockBreakCheck { +public class LiquidAirBreak extends Check implements BlockBreakCheck { public LiquidAirBreak(GrimPlayer player) { super(player); } diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java index 8a4667e052..e7dc540833 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java @@ -1,5 +1,6 @@ package ac.grim.grimac.checks.impl.breaking; +import ac.grim.grimac.checks.Check; import ac.grim.grimac.checks.CheckData; import ac.grim.grimac.checks.type.BlockBreakCheck; import ac.grim.grimac.player.GrimPlayer; @@ -11,7 +12,7 @@ import java.util.Collections; @CheckData(name = "PositionBreakA") -public class PositionBreakA extends BlockBreakCheck { +public class PositionBreakA extends Check implements BlockBreakCheck { public PositionBreakA(GrimPlayer player) { super(player); } diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakB.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakB.java index 30afd34ce1..5b2adee7fb 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakB.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakB.java @@ -1,5 +1,6 @@ package ac.grim.grimac.checks.impl.breaking; +import ac.grim.grimac.checks.Check; import ac.grim.grimac.checks.CheckData; import ac.grim.grimac.checks.type.BlockBreakCheck; import ac.grim.grimac.player.GrimPlayer; @@ -9,7 +10,7 @@ import com.github.retrooper.packetevents.protocol.world.BlockFace; @CheckData(name = "PositionBreakB") -public class PositionBreakB extends BlockBreakCheck { +public class PositionBreakB extends Check implements BlockBreakCheck { public PositionBreakB(GrimPlayer player) { super(player); } diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBlock.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBlock.java index 3eef717970..eae36f3c31 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBlock.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBlock.java @@ -1,8 +1,8 @@ package ac.grim.grimac.checks.impl.breaking; +import ac.grim.grimac.checks.Check; import ac.grim.grimac.checks.CheckData; import ac.grim.grimac.checks.type.BlockBreakCheck; -import ac.grim.grimac.checks.type.PacketCheck; import ac.grim.grimac.player.GrimPlayer; import ac.grim.grimac.utils.anticheat.MessageUtil; import ac.grim.grimac.utils.anticheat.update.BlockBreak; @@ -15,7 +15,7 @@ import static ac.grim.grimac.utils.nmsutil.BlockBreakSpeed.getBlockDamage; @CheckData(name = "WrongBlock", experimental = true) -public class WrongBlock extends BlockBreakCheck implements PacketCheck { +public class WrongBlock extends Check implements BlockBreakCheck { public WrongBlock(final GrimPlayer player) { super(player); } diff --git a/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java b/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java index 968b61dc86..1bc3b5f5e7 100644 --- a/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java +++ b/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java @@ -1,13 +1,7 @@ package ac.grim.grimac.checks.type; -import ac.grim.grimac.checks.Check; -import ac.grim.grimac.player.GrimPlayer; import ac.grim.grimac.utils.anticheat.update.BlockBreak; -public class BlockBreakCheck extends Check implements PacketCheck { - public BlockBreakCheck(GrimPlayer player) { - super(player); - } - - public void onBlockBreak(final BlockBreak blockBreak) {} +public interface BlockBreakCheck extends PacketCheck { + void onBlockBreak(final BlockBreak blockBreak); } From 0136f1605bd6c49d0b04b3baf7dcb8c6ed75cd63 Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Tue, 3 Sep 2024 17:05:29 -0600 Subject: [PATCH 09/29] add FarBreak --- .../grimac/checks/impl/breaking/FarBreak.java | 56 +++++++++++++++++++ .../checks/impl/breaking/FastBreak.java | 23 ++++++++ .../checks/impl/breaking/WrongBlock.java | 2 +- .../ac/grim/grimac/manager/CheckManager.java | 1 + 4 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java new file mode 100644 index 0000000000..9cd4d9103f --- /dev/null +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java @@ -0,0 +1,56 @@ +package ac.grim.grimac.checks.impl.breaking; + +import ac.grim.grimac.checks.Check; +import ac.grim.grimac.checks.CheckData; +import ac.grim.grimac.checks.type.BlockBreakCheck; +import ac.grim.grimac.player.GrimPlayer; +import ac.grim.grimac.utils.anticheat.update.BlockBreak; +import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox; +import ac.grim.grimac.utils.math.VectorUtils; +import com.github.retrooper.packetevents.protocol.attribute.Attributes; +import com.github.retrooper.packetevents.protocol.player.DiggingAction; +import org.bukkit.util.Vector; + +@CheckData(name = "FarBreak") +public class FarBreak extends Check implements BlockBreakCheck { + public FarBreak(GrimPlayer player) { + super(player); + } + + @Override + public void onBlockBreak(BlockBreak blockBreak) { + double x = player.x; + double y = player.y; + double z = player.z; + + if (blockBreak.action == DiggingAction.CANCELLED_DIGGING) { + if (((WrongBlock) player.checkManager.allChecks.get(WrongBlock.class)).shouldExempt(blockBreak.position)) { + return; + } + + x = player.lastX; + y = player.lastY; + z = player.lastZ; + } + + double min = Double.MAX_VALUE; + for (double d : player.getPossibleEyeHeights()) { + SimpleCollisionBox box = new SimpleCollisionBox(blockBreak.position); + Vector eyes = new Vector(x, y + d, z); + Vector best = VectorUtils.cutBoxToVector(eyes, box); + min = Math.min(min, eyes.distanceSquared(best)); + } + + // getPickRange() determines this? + // With 1.20.5+ the new attribute determines creative mode reach using a modifier + double maxReach = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE); + double threshold = player.getMovementThreshold(); + maxReach += Math.hypot(threshold, threshold); + + if (min > maxReach * maxReach) { + if (flagAndAlert("distance=" + Math.sqrt(min)) && shouldModifyPackets()) { + blockBreak.cancel(); + } + } + } +} diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java index 4b640e4d05..11a496f605 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java @@ -5,12 +5,16 @@ import ac.grim.grimac.checks.type.BlockBreakCheck; import ac.grim.grimac.player.GrimPlayer; import ac.grim.grimac.utils.anticheat.update.BlockBreak; +import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox; +import ac.grim.grimac.utils.math.VectorUtils; import ac.grim.grimac.utils.nmsutil.BlockBreakSpeed; import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.protocol.attribute.Attributes; import com.github.retrooper.packetevents.protocol.player.ClientVersion; import com.github.retrooper.packetevents.protocol.player.DiggingAction; import com.github.retrooper.packetevents.util.Vector3i; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; +import org.bukkit.util.Vector; @CheckData(name = "FastBreak") public class FastBreak extends Check implements BlockBreakCheck { @@ -51,6 +55,25 @@ public void onPacketReceive(PacketReceiveEvent event) { } if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) { + // check if the player is within range of the block + double min = Double.MAX_VALUE; + for (double d : player.getPossibleEyeHeights()) { + SimpleCollisionBox box = new SimpleCollisionBox(targetBlock); + Vector eyes = new Vector(player.x, player.y + d, player.z); + Vector best = VectorUtils.cutBoxToVector(eyes, box); + min = Math.min(min, eyes.distanceSquared(best)); + } + + // getPickRange() determines this? + // With 1.20.5+ the new attribute determines creative mode reach using a modifier + double maxReach = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE); + double threshold = player.getMovementThreshold(); + maxReach += Math.hypot(threshold, threshold); + + if (min > maxReach * maxReach) { + return; + } + progress += BlockBreakSpeed.getBlockDamage(player, targetBlock); } } diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBlock.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBlock.java index eae36f3c31..6eb5e5a4c3 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBlock.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBlock.java @@ -25,7 +25,7 @@ public WrongBlock(final GrimPlayer player) { private final int exemptedY = player.getClientVersion().isOlderThan(ClientVersion.V_1_8) ? 255 : (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_14) ? -1 : 4095); // The client sometimes sends a wierd cancel packet - private boolean shouldExempt(final Vector3i pos) { + public boolean shouldExempt(final Vector3i pos) { // lastLastBlock is always null when this happens, and lastBlock isn't if (lastLastBlock != null || lastBlock == null) return false; diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index 263cd5e2ee..59452903f6 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -148,6 +148,7 @@ public CheckManager(GrimPlayer player) { .build(); blockBreakChecks = new ImmutableClassToInstanceMap.Builder() + .put(FarBreak.class, new FarBreak(player)) .put(WrongBlock.class, new WrongBlock(player)) .put(LiquidAirBreak.class, new LiquidAirBreak(player)) .put(PositionBreakA.class, new PositionBreakA(player)) From 8b47da5ef8e90baccd0a34e032b9e088abf20596 Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Wed, 4 Sep 2024 15:33:55 -0600 Subject: [PATCH 10/29] WrongBlock -> WrongBreak --- .../java/ac/grim/grimac/checks/impl/breaking/FarBreak.java | 2 +- .../impl/breaking/{WrongBlock.java => WrongBreak.java} | 6 +++--- src/main/java/ac/grim/grimac/manager/CheckManager.java | 2 +- src/main/resources/punishments/de.yml | 1 - src/main/resources/punishments/en.yml | 1 - src/main/resources/punishments/es.yml | 1 - src/main/resources/punishments/fr.yml | 1 - src/main/resources/punishments/it.yml | 1 - src/main/resources/punishments/nl.yml | 1 - src/main/resources/punishments/pt.yml | 1 - src/main/resources/punishments/ru.yml | 1 - src/main/resources/punishments/zh.yml | 1 - 12 files changed, 5 insertions(+), 14 deletions(-) rename src/main/java/ac/grim/grimac/checks/impl/breaking/{WrongBlock.java => WrongBreak.java} (96%) diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java index 9cd4d9103f..18a72a4a1d 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java @@ -24,7 +24,7 @@ public void onBlockBreak(BlockBreak blockBreak) { double z = player.z; if (blockBreak.action == DiggingAction.CANCELLED_DIGGING) { - if (((WrongBlock) player.checkManager.allChecks.get(WrongBlock.class)).shouldExempt(blockBreak.position)) { + if (((WrongBreak) player.checkManager.allChecks.get(WrongBreak.class)).shouldExempt(blockBreak.position)) { return; } diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBlock.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBreak.java similarity index 96% rename from src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBlock.java rename to src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBreak.java index 6eb5e5a4c3..b4e6bd409f 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBlock.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBreak.java @@ -14,9 +14,9 @@ import static ac.grim.grimac.utils.nmsutil.BlockBreakSpeed.getBlockDamage; -@CheckData(name = "WrongBlock", experimental = true) -public class WrongBlock extends Check implements BlockBreakCheck { - public WrongBlock(final GrimPlayer player) { +@CheckData(name = "WrongBreak", experimental = true) +public class WrongBreak extends Check implements BlockBreakCheck { + public WrongBreak(final GrimPlayer player) { super(player); } diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index 59452903f6..8bac19077b 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -149,7 +149,7 @@ public CheckManager(GrimPlayer player) { blockBreakChecks = new ImmutableClassToInstanceMap.Builder() .put(FarBreak.class, new FarBreak(player)) - .put(WrongBlock.class, new WrongBlock(player)) + .put(WrongBreak.class, new WrongBreak(player)) .put(LiquidAirBreak.class, new LiquidAirBreak(player)) .put(PositionBreakA.class, new PositionBreakA(player)) .put(PositionBreakB.class, new PositionBreakB(player)) diff --git a/src/main/resources/punishments/de.yml b/src/main/resources/punishments/de.yml index 5ba4ed128f..4deec85bf2 100644 --- a/src/main/resources/punishments/de.yml +++ b/src/main/resources/punishments/de.yml @@ -72,7 +72,6 @@ Punishments: - "NoSlow" - "Place" - "Break" - - "WrongBlock" - "Baritone" - "FastBreak" - "TransactionOrder" diff --git a/src/main/resources/punishments/en.yml b/src/main/resources/punishments/en.yml index 0a96555b5a..0821949f6d 100644 --- a/src/main/resources/punishments/en.yml +++ b/src/main/resources/punishments/en.yml @@ -72,7 +72,6 @@ Punishments: - "NoSlow" - "Place" - "Break" - - "WrongBlock" - "Baritone" - "FastBreak" - "TransactionOrder" diff --git a/src/main/resources/punishments/es.yml b/src/main/resources/punishments/es.yml index f1c4674303..44f48fca25 100644 --- a/src/main/resources/punishments/es.yml +++ b/src/main/resources/punishments/es.yml @@ -72,7 +72,6 @@ Punishments: - "NoSlow" - "Place" - "Break" - - "WrongBlock" - "Baritone" - "FastBreak" - "TransactionOrder" diff --git a/src/main/resources/punishments/fr.yml b/src/main/resources/punishments/fr.yml index 0504a2b175..a33ae014aa 100644 --- a/src/main/resources/punishments/fr.yml +++ b/src/main/resources/punishments/fr.yml @@ -72,7 +72,6 @@ Punishments: - "NoSlow" - "Place" - "Break" - - "WrongBlock" - "Baritone" - "FastBreak" - "TransactionOrder" diff --git a/src/main/resources/punishments/it.yml b/src/main/resources/punishments/it.yml index 50e384c890..5a57b7cf79 100644 --- a/src/main/resources/punishments/it.yml +++ b/src/main/resources/punishments/it.yml @@ -59,7 +59,6 @@ Punishments: - "NoSlow" - "Place" - "Break" - - "WrongBlock" - "Baritone" - "FastBreak" - "TransactionOrder" diff --git a/src/main/resources/punishments/nl.yml b/src/main/resources/punishments/nl.yml index 0817a2bff2..a89a97ad9d 100644 --- a/src/main/resources/punishments/nl.yml +++ b/src/main/resources/punishments/nl.yml @@ -72,7 +72,6 @@ Punishments: - "NoSlow" - "Place" - "Break" - - "WrongBlock" - "Baritone" - "FastBreak" - "TransactionOrder" diff --git a/src/main/resources/punishments/pt.yml b/src/main/resources/punishments/pt.yml index c5fef0b0a4..8e70ae6488 100644 --- a/src/main/resources/punishments/pt.yml +++ b/src/main/resources/punishments/pt.yml @@ -72,7 +72,6 @@ Punishments: - "NoSlow" - "Place" - "Break" - - "WrongBlock" - "Baritone" - "FastBreak" - "TransactionOrder" diff --git a/src/main/resources/punishments/ru.yml b/src/main/resources/punishments/ru.yml index 7068494337..173928e3f4 100644 --- a/src/main/resources/punishments/ru.yml +++ b/src/main/resources/punishments/ru.yml @@ -72,7 +72,6 @@ Punishments: - "NoSlow" - "Place" - "Break" - - "WrongBlock" - "Baritone" - "FastBreak" - "TransactionOrder" diff --git a/src/main/resources/punishments/zh.yml b/src/main/resources/punishments/zh.yml index 446fde5943..dfb12264b0 100644 --- a/src/main/resources/punishments/zh.yml +++ b/src/main/resources/punishments/zh.yml @@ -72,7 +72,6 @@ Punishments: - "NoSlow" - "Place" - "Break" - - "WrongBlock" - "Baritone" - "FastBreak" - "TransactionOrder" From a89d83055e8205872f647fb1ccae7fdd2b3ad754 Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Wed, 4 Sep 2024 15:40:34 -0600 Subject: [PATCH 11/29] don't require implementing onBlockBreak --- src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java b/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java index 1bc3b5f5e7..8bac07a558 100644 --- a/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java +++ b/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java @@ -3,5 +3,5 @@ import ac.grim.grimac.utils.anticheat.update.BlockBreak; public interface BlockBreakCheck extends PacketCheck { - void onBlockBreak(final BlockBreak blockBreak); + default void onBlockBreak(final BlockBreak blockBreak) {} } From 86ad878c28797a58710676e8524e80d1c7fd2f01 Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Wed, 4 Sep 2024 16:04:39 -0600 Subject: [PATCH 12/29] fix some falses in vehicles --- .../grimac/checks/impl/breaking/FarBreak.java | 2 ++ .../checks/impl/breaking/FastBreak.java | 32 ++++++++++--------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java index 18a72a4a1d..c7d700d184 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java @@ -19,6 +19,8 @@ public FarBreak(GrimPlayer player) { @Override public void onBlockBreak(BlockBreak blockBreak) { + if (player.compensatedEntities.getSelf().inVehicle()) return; // falses + double x = player.x; double y = player.y; double z = player.z; diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java index 11a496f605..021a6774dd 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java @@ -55,23 +55,25 @@ public void onPacketReceive(PacketReceiveEvent event) { } if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) { - // check if the player is within range of the block - double min = Double.MAX_VALUE; - for (double d : player.getPossibleEyeHeights()) { - SimpleCollisionBox box = new SimpleCollisionBox(targetBlock); - Vector eyes = new Vector(player.x, player.y + d, player.z); - Vector best = VectorUtils.cutBoxToVector(eyes, box); - min = Math.min(min, eyes.distanceSquared(best)); - } + if (!player.compensatedEntities.getSelf().inVehicle()) { // falses + // check if the player is within range of the block + double min = Double.MAX_VALUE; + for (double d : player.getPossibleEyeHeights()) { + SimpleCollisionBox box = new SimpleCollisionBox(targetBlock); + Vector eyes = new Vector(player.x, player.y + d, player.z); + Vector best = VectorUtils.cutBoxToVector(eyes, box); + min = Math.min(min, eyes.distanceSquared(best)); + } - // getPickRange() determines this? - // With 1.20.5+ the new attribute determines creative mode reach using a modifier - double maxReach = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE); - double threshold = player.getMovementThreshold(); - maxReach += Math.hypot(threshold, threshold); + // getPickRange() determines this? + // With 1.20.5+ the new attribute determines creative mode reach using a modifier + double maxReach = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE); + double threshold = player.getMovementThreshold(); + maxReach += Math.hypot(threshold, threshold); - if (min > maxReach * maxReach) { - return; + if (min > maxReach * maxReach) { + return; + } } progress += BlockBreakSpeed.getBlockDamage(player, targetBlock); From e9232af4ee231338c9547c562e83153271b0a62a Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Wed, 4 Sep 2024 16:50:32 -0600 Subject: [PATCH 13/29] fix some more falses --- .../java/ac/grim/grimac/checks/impl/breaking/FarBreak.java | 2 +- .../ac/grim/grimac/checks/impl/breaking/PositionBreakA.java | 5 ++--- .../java/ac/grim/grimac/checks/impl/breaking/WrongBreak.java | 4 +++- src/main/java/ac/grim/grimac/manager/CheckManager.java | 2 +- .../ac/grim/grimac/utils/anticheat/update/BlockBreak.java | 3 +++ 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java index c7d700d184..4ed71d5769 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java @@ -26,7 +26,7 @@ public void onBlockBreak(BlockBreak blockBreak) { double z = player.z; if (blockBreak.action == DiggingAction.CANCELLED_DIGGING) { - if (((WrongBreak) player.checkManager.allChecks.get(WrongBreak.class)).shouldExempt(blockBreak.position)) { + if (blockBreak.isWeirdCancel) { return; } diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java index e7dc540833..f74e51616d 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java @@ -19,9 +19,8 @@ public PositionBreakA(GrimPlayer player) { @Override public void onBlockBreak(BlockBreak blockBreak) { - if (blockBreak.action == DiggingAction.CANCELLED_DIGGING) { - return; // buggy - } + if (player.compensatedEntities.getSelf().inVehicle()) return; // falses + if (blockBreak.action == DiggingAction.CANCELLED_DIGGING) return; // buggy SimpleCollisionBox combined = blockBreak.getCombinedBox(); diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBreak.java index b4e6bd409f..e846421f86 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/WrongBreak.java @@ -25,7 +25,7 @@ public WrongBreak(final GrimPlayer player) { private final int exemptedY = player.getClientVersion().isOlderThan(ClientVersion.V_1_8) ? 255 : (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_14) ? -1 : 4095); // The client sometimes sends a wierd cancel packet - public boolean shouldExempt(final Vector3i pos) { + private boolean shouldExempt(final Vector3i pos) { // lastLastBlock is always null when this happens, and lastBlock isn't if (lastLastBlock != null || lastBlock == null) return false; @@ -59,6 +59,8 @@ public void onBlockBreak(BlockBreak blockBreak) { } } } + } else { + blockBreak.isWeirdCancel = true; } lastCancelledBlock = blockBreak.position; diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index 8bac19077b..4361548ae0 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -148,11 +148,11 @@ public CheckManager(GrimPlayer player) { .build(); blockBreakChecks = new ImmutableClassToInstanceMap.Builder() - .put(FarBreak.class, new FarBreak(player)) .put(WrongBreak.class, new WrongBreak(player)) .put(LiquidAirBreak.class, new LiquidAirBreak(player)) .put(PositionBreakA.class, new PositionBreakA(player)) .put(PositionBreakB.class, new PositionBreakB(player)) + .put(FarBreak.class, new FarBreak(player)) .put(FastBreak.class, new FastBreak(player)) .build(); diff --git a/src/main/java/ac/grim/grimac/utils/anticheat/update/BlockBreak.java b/src/main/java/ac/grim/grimac/utils/anticheat/update/BlockBreak.java index af08f545db..357781c192 100644 --- a/src/main/java/ac/grim/grimac/utils/anticheat/update/BlockBreak.java +++ b/src/main/java/ac/grim/grimac/utils/anticheat/update/BlockBreak.java @@ -20,6 +20,9 @@ public class BlockBreak { @Getter private boolean cancelled; + // set by WrongBreak + public boolean isWeirdCancel; + private final GrimPlayer player; public final WrappedBlockState block; From 4ac3d57e219f3d653f4580e00e99c26b8b40464e Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Wed, 4 Sep 2024 18:43:31 -0600 Subject: [PATCH 14/29] Add RotationBreak --- .../checks/impl/breaking/FastBreak.java | 93 +++++++++++--- .../checks/impl/breaking/RotationBreak.java | 114 ++++++++++++++++++ .../grimac/checks/type/BlockBreakCheck.java | 1 + .../events/packets/CheckManagerListener.java | 52 +++++++- .../events/packets/PacketPlayerDigging.java | 1 + .../ac/grim/grimac/manager/CheckManager.java | 13 +- .../ac/grim/grimac/player/GrimPlayer.java | 9 +- 7 files changed, 255 insertions(+), 28 deletions(-) create mode 100644 src/main/java/ac/grim/grimac/checks/impl/breaking/RotationBreak.java diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java index 021a6774dd..f5ef0e90c0 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java @@ -6,16 +6,27 @@ import ac.grim.grimac.player.GrimPlayer; import ac.grim.grimac.utils.anticheat.update.BlockBreak; import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox; +import ac.grim.grimac.utils.data.Pair; import ac.grim.grimac.utils.math.VectorUtils; import ac.grim.grimac.utils.nmsutil.BlockBreakSpeed; +import ac.grim.grimac.utils.nmsutil.Ray; +import ac.grim.grimac.utils.nmsutil.ReachUtils; import com.github.retrooper.packetevents.event.PacketReceiveEvent; import com.github.retrooper.packetevents.protocol.attribute.Attributes; import com.github.retrooper.packetevents.protocol.player.ClientVersion; import com.github.retrooper.packetevents.protocol.player.DiggingAction; +import com.github.retrooper.packetevents.protocol.world.BlockFace; +import com.github.retrooper.packetevents.util.Vector3d; +import com.github.retrooper.packetevents.util.Vector3f; import com.github.retrooper.packetevents.util.Vector3i; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; import org.bukkit.util.Vector; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + @CheckData(name = "FastBreak") public class FastBreak extends Check implements BlockBreakCheck { public FastBreak(GrimPlayer playerData) { @@ -55,23 +66,8 @@ public void onPacketReceive(PacketReceiveEvent event) { } if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) { - if (!player.compensatedEntities.getSelf().inVehicle()) { // falses - // check if the player is within range of the block - double min = Double.MAX_VALUE; - for (double d : player.getPossibleEyeHeights()) { - SimpleCollisionBox box = new SimpleCollisionBox(targetBlock); - Vector eyes = new Vector(player.x, player.y + d, player.z); - Vector best = VectorUtils.cutBoxToVector(eyes, box); - min = Math.min(min, eyes.distanceSquared(best)); - } - - // getPickRange() determines this? - // With 1.20.5+ the new attribute determines creative mode reach using a modifier - double maxReach = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE); - double threshold = player.getMovementThreshold(); - maxReach += Math.hypot(threshold, threshold); - - if (min > maxReach * maxReach) { + if (!player.compensatedEntities.getSelf().inVehicle()) { + if (!didRayTraceHit() || !isWithinRange()) { return; } } @@ -79,4 +75,67 @@ public void onPacketReceive(PacketReceiveEvent event) { progress += BlockBreakSpeed.getBlockDamage(player, targetBlock); } } + + private boolean isWithinRange() { + double min = Double.MAX_VALUE; + for (double d : player.getPossibleEyeHeights()) { + SimpleCollisionBox box = new SimpleCollisionBox(targetBlock); + Vector eyes = new Vector(player.x, player.y + d, player.z); + Vector best = VectorUtils.cutBoxToVector(eyes, box); + min = Math.min(min, eyes.distanceSquared(best)); + } + + // getPickRange() determines this? + // With 1.20.5+ the new attribute determines creative mode reach using a modifier + double maxReach = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE); + double threshold = player.getMovementThreshold(); + maxReach += Math.hypot(threshold, threshold); + + return min <= maxReach * maxReach; + } + + private boolean didRayTraceHit() { + SimpleCollisionBox box = new SimpleCollisionBox(targetBlock); + + // Start checking if player is in the block + double minEyeHeight = Collections.min(player.getPossibleEyeHeights()); + double maxEyeHeight = Collections.max(player.getPossibleEyeHeights()); + + SimpleCollisionBox eyePositions = new SimpleCollisionBox(player.lastX, player.lastY + minEyeHeight, player.lastZ, player.lastX, player.lastY + maxEyeHeight, player.lastZ); + eyePositions.expand(player.getMovementThreshold()); + + // If the player is inside a block, then they can ray trace through the block and hit the other side of the block + if (eyePositions.isIntersected(box)) { + return true; + } + // End checking if the player is in the block + + List possibleLookDirs = new ArrayList<>(Arrays.asList( + new Vector3f(player.lastXRot, player.yRot, 0), + new Vector3f(player.xRot, player.yRot, 0) + )); + + // 1.9+ players could be a tick behind because we don't get skipped ticks + if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9)) { + possibleLookDirs.add(new Vector3f(player.lastXRot, player.lastYRot, 0)); + } + + // 1.7 players do not have any of these issues! They are always on the latest look vector + if (player.getClientVersion().isOlderThan(ClientVersion.V_1_8)) { + possibleLookDirs = Collections.singletonList(new Vector3f(player.xRot, player.yRot, 0)); + } + + final double distance = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE); + for (double d : player.getPossibleEyeHeights()) { + for (Vector3f lookDir : possibleLookDirs) { + Vector3d starting = new Vector3d(player.lastX, player.lastY + d, player.lastZ); + Ray trace = new Ray(player, starting.getX(), starting.getY(), starting.getZ(), lookDir.getX(), lookDir.getY()); + Pair intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance)); + + if (intercept.getFirst() != null) return true; + } + } + + return false; + } } diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/RotationBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/RotationBreak.java new file mode 100644 index 0000000000..34dc716226 --- /dev/null +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/RotationBreak.java @@ -0,0 +1,114 @@ +package ac.grim.grimac.checks.impl.breaking; + +import ac.grim.grimac.checks.Check; +import ac.grim.grimac.checks.CheckData; +import ac.grim.grimac.checks.type.BlockBreakCheck; +import ac.grim.grimac.player.GrimPlayer; +import ac.grim.grimac.utils.anticheat.update.BlockBreak; +import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox; +import ac.grim.grimac.utils.data.Pair; +import ac.grim.grimac.utils.nmsutil.Ray; +import ac.grim.grimac.utils.nmsutil.ReachUtils; +import com.github.retrooper.packetevents.protocol.attribute.Attributes; +import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.player.DiggingAction; +import com.github.retrooper.packetevents.protocol.player.GameMode; +import com.github.retrooper.packetevents.protocol.world.BlockFace; +import com.github.retrooper.packetevents.util.Vector3d; +import com.github.retrooper.packetevents.util.Vector3f; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +@CheckData(name = "RotationBreak") +public class RotationBreak extends Check implements BlockBreakCheck { + public RotationBreak(GrimPlayer player) { + super(player); + } + + private double flagBuffer = 0; // If the player flags once, force them to play legit, or we will cancel the tick before. + private boolean ignorePost = false; + + @Override + public void onBlockBreak(BlockBreak blockBreak) { + if (player.gamemode == GameMode.SPECTATOR) return; // you don't send flying packets when spectating entities + if (player.compensatedEntities.getSelf().inVehicle()) return; // falses + if (blockBreak.action == DiggingAction.CANCELLED_DIGGING) return; // falses + + if (flagBuffer > 0 && !didRayTraceHit(blockBreak)) { + ignorePost = true; + // If the player hit and has flagged this check recently + if (flagAndAlert("pre-flying, action=" + blockBreak.action) && shouldModifyPackets()) { + blockBreak.cancel(); + } + } + } + + @Override + public void onPostFlyingBlockBreak(BlockBreak blockBreak) { + if (player.gamemode == GameMode.SPECTATOR) return; // you don't send flying packets when spectating entities + if (player.compensatedEntities.getSelf().inVehicle()) return; // falses + if (blockBreak.action == DiggingAction.CANCELLED_DIGGING) return; // falses + + // Don't flag twice + if (ignorePost) { + ignorePost = false; + return; + } + + if (didRayTraceHit(blockBreak)) { + flagBuffer = Math.max(0, flagBuffer - 0.1); + } else { + flagBuffer = 1; + flagAndAlert("post-flying, action=" + blockBreak.action); + } + } + + private boolean didRayTraceHit(BlockBreak blockBreak) { + SimpleCollisionBox box = new SimpleCollisionBox(blockBreak.position); + + // Start checking if player is in the block + double minEyeHeight = Collections.min(player.getPossibleEyeHeights()); + double maxEyeHeight = Collections.max(player.getPossibleEyeHeights()); + + SimpleCollisionBox eyePositions = new SimpleCollisionBox(player.x, player.y + minEyeHeight, player.z, player.x, player.y + maxEyeHeight, player.z); + eyePositions.expand(player.getMovementThreshold()); + + // If the player is inside a block, then they can ray trace through the block and hit the other side of the block + if (eyePositions.isIntersected(box)) { + return true; + } + // End checking if the player is in the block + + List possibleLookDirs = new ArrayList<>(Arrays.asList( + new Vector3f(player.lastXRot, player.yRot, 0), + new Vector3f(player.xRot, player.yRot, 0) + )); + + // 1.9+ players could be a tick behind because we don't get skipped ticks + if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9)) { + possibleLookDirs.add(new Vector3f(player.lastXRot, player.lastYRot, 0)); + } + + // 1.7 players do not have any of these issues! They are always on the latest look vector + if (player.getClientVersion().isOlderThan(ClientVersion.V_1_8)) { + possibleLookDirs = Collections.singletonList(new Vector3f(player.xRot, player.yRot, 0)); + } + + final double distance = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE); + for (double d : player.getPossibleEyeHeights()) { + for (Vector3f lookDir : possibleLookDirs) { + Vector3d starting = new Vector3d(player.x, player.y + d, player.z); + Ray trace = new Ray(player, starting.getX(), starting.getY(), starting.getZ(), lookDir.getX(), lookDir.getY()); + Pair intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance)); + + if (intercept.getFirst() != null) return true; + } + } + + return false; + } +} diff --git a/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java b/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java index 8bac07a558..7363fa2afb 100644 --- a/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java +++ b/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java @@ -4,4 +4,5 @@ public interface BlockBreakCheck extends PacketCheck { default void onBlockBreak(final BlockBreak blockBreak) {} + default void onPostFlyingBlockBreak(final BlockBreak blockBreak) {} } diff --git a/src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java b/src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java index 25880f141d..e89d00058c 100644 --- a/src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java +++ b/src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java @@ -207,6 +207,40 @@ public static void handleQueuedPlaces(GrimPlayer player, boolean hasLook, float } } + public static void handleQueuedBreaks(GrimPlayer player, boolean hasLook, float pitch, float yaw, long now) { + BlockBreak blockBreak; + while ((blockBreak = player.queuedBreaks.poll()) != null) { + double lastX = player.x; + double lastY = player.y; + double lastZ = player.z; + + player.x = player.packetStateData.lastClaimedPosition.getX(); + player.y = player.packetStateData.lastClaimedPosition.getY(); + player.z = player.packetStateData.lastClaimedPosition.getZ(); + + if (player.compensatedEntities.getSelf().getRiding() != null) { + Vector3d posFromVehicle = BoundingBoxSize.getRidingOffsetFromVehicle(player.compensatedEntities.getSelf().getRiding(), player); + player.x = posFromVehicle.getX(); + player.y = posFromVehicle.getY(); + player.z = posFromVehicle.getZ(); + } + + // Less than 15 milliseconds ago means this is likely (fix all look vectors being a tick behind server sided) + // Or mojang had the idle packet... for the 1.7/1.8 clients + // No idle packet on 1.9+ + if ((now - player.lastBlockBreak < 15 || player.getClientVersion().isOlderThan(ClientVersion.V_1_9)) && hasLook) { + player.xRot = yaw; + player.yRot = pitch; + } + + player.checkManager.onPostFlyingBlockBreak(blockBreak); + + player.x = lastX; + player.y = lastY; + player.z = lastZ; + } + } + private static void handleUseItem(GrimPlayer player, ItemStack placedWith, InteractionHand hand) { // Lilypads are USE_ITEM (THIS CAN DESYNC, WTF MOJANG) if (placedWith.getType() == ItemTypes.LILY_PAD) { @@ -459,19 +493,24 @@ public void onPacketReceive(PacketReceiveEvent event) { DiggingAction action = dig.getAction(); if (action == DiggingAction.START_DIGGING || action == DiggingAction.FINISHED_DIGGING || action == DiggingAction.CANCELLED_DIGGING) { + player.lastBlockBreak = System.currentTimeMillis(); + Vector3i position = dig.getBlockPosition(); WrappedBlockState block = player.compensatedWorld.getWrappedBlockStateAt(position); BlockBreak blockBreak = new BlockBreak(position, dig.getBlockFace(), action, player, block); player.checkManager.onBlockBreak(blockBreak); - if (blockBreak.isCancelled()) { - event.setCancelled(true); - player.onPacketCancel(); + if (event.isCancelled() || blockBreak.isCancelled()) { + if (!event.isCancelled()) { + event.setCancelled(true); + player.onPacketCancel(); + } + resyncPosition(player, position); - } + } else { + player.queuedBreaks.add(blockBreak); - if (!event.isCancelled()) { if (action == DiggingAction.FINISHED_DIGGING) { // Not unbreakable if (!block.getType().isAir() && block.getType().getHardness() != -1.0f) { @@ -484,7 +523,7 @@ public void onPacketReceive(PacketReceiveEvent event) { if (action == DiggingAction.START_DIGGING) { double damage = BlockBreakSpeed.getBlockDamage(player, position); - //Instant breaking, no damage means it is unbreakable by creative players (with swords) + // Instant breaking, no damage means it is unbreakable by creative players (with swords) if (damage >= 1) { player.compensatedWorld.startPredicting(); if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_13) && Materials.isWaterSource(player.getClientVersion(), block)) { @@ -689,6 +728,7 @@ private void handleFlying(GrimPlayer player, double x, double y, double z, float } handleQueuedPlaces(player, hasLook, pitch, yaw, now); + handleQueuedBreaks(player, hasLook, pitch, yaw, now); // We can set the new pos after the places if (hasPosition) { diff --git a/src/main/java/ac/grim/grimac/events/packets/PacketPlayerDigging.java b/src/main/java/ac/grim/grimac/events/packets/PacketPlayerDigging.java index f084272e11..d6037b4558 100644 --- a/src/main/java/ac/grim/grimac/events/packets/PacketPlayerDigging.java +++ b/src/main/java/ac/grim/grimac/events/packets/PacketPlayerDigging.java @@ -191,6 +191,7 @@ public void onPacketReceive(PacketReceiveEvent event) { final GrimPlayer player = GrimAPI.INSTANCE.getPlayerDataManager().getPlayer(event.getUser()); if (player == null) return; + // do we need to do this with block breaks too? // Prevent issues if the player switches slots, while lagging, standing still, and is placing blocks CheckManagerListener.handleQueuedPlaces(player, false, 0, 0, System.currentTimeMillis()); diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index 4361548ae0..2af3bd7d21 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -148,6 +148,7 @@ public CheckManager(GrimPlayer player) { .build(); blockBreakChecks = new ImmutableClassToInstanceMap.Builder() + .put(RotationBreak.class, new RotationBreak(player)) .put(WrongBreak.class, new WrongBreak(player)) .put(LiquidAirBreak.class, new LiquidAirBreak(player)) .put(PositionBreakA.class, new PositionBreakA(player)) @@ -270,15 +271,21 @@ public void onBlockPlace(final BlockPlace place) { } } + public void onPostFlyingBlockPlace(final BlockPlace place) { + for (BlockPlaceCheck check : blockPlaceCheck.values()) { + check.onPostFlyingBlockPlace(place); + } + } + public void onBlockBreak(final BlockBreak blockBreak) { for (BlockBreakCheck check : blockBreakChecks.values()) { check.onBlockBreak(blockBreak); } } - public void onPostFlyingBlockPlace(final BlockPlace place) { - for (BlockPlaceCheck check : blockPlaceCheck.values()) { - check.onPostFlyingBlockPlace(place); + public void onPostFlyingBlockBreak(final BlockBreak blockBreak) { + for (BlockBreakCheck check : blockBreakChecks.values()) { + check.onPostFlyingBlockBreak(blockBreak); } } diff --git a/src/main/java/ac/grim/grimac/player/GrimPlayer.java b/src/main/java/ac/grim/grimac/player/GrimPlayer.java index d55074e57e..477fd93214 100644 --- a/src/main/java/ac/grim/grimac/player/GrimPlayer.java +++ b/src/main/java/ac/grim/grimac/player/GrimPlayer.java @@ -14,6 +14,7 @@ import ac.grim.grimac.predictionengine.PointThreeEstimator; import ac.grim.grimac.predictionengine.UncertaintyHandler; import ac.grim.grimac.utils.anticheat.LogUtil; +import ac.grim.grimac.utils.anticheat.update.BlockBreak; import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox; import ac.grim.grimac.utils.data.*; import ac.grim.grimac.utils.data.packetentity.PacketEntity; @@ -198,6 +199,7 @@ public class GrimPlayer implements GrimUser { public DimensionType dimensionType; public Vector3d bedPosition; public long lastBlockPlaceUseItem = 0; + public long lastBlockBreak = 0; public AtomicInteger cancelledPackets = new AtomicInteger(0); public MainSupportingBlockData mainSupportingBlockData = new MainSupportingBlockData(null, false); @@ -211,6 +213,7 @@ public void onPacketCancel() { public int totalFlyingPacketsSent; public Queue placeUseItemPackets = new LinkedBlockingQueue<>(); + public Queue queuedBreaks = new LinkedBlockingQueue<>(); // This variable is for support with test servers that want to be able to disable grim // Grim disabler 2022 still working! public boolean disableGrim = false; @@ -331,8 +334,10 @@ public boolean addTransactionResponse(short id) { playerClockAtLeast = data.getSecond(); } while (data.getFirst() != id); - // A transaction means a new tick, so apply any block places - CheckManagerListener.handleQueuedPlaces(this, false, 0, 0, System.currentTimeMillis()); + // A transaction means a new tick, so apply any block places or breaks + long now = System.currentTimeMillis(); + CheckManagerListener.handleQueuedPlaces(this, false, 0, 0, now); + CheckManagerListener.handleQueuedBreaks(this, false, 0, 0, now); latencyUtils.handleNettySyncTransaction(lastTransactionReceived.get()); } From df22faa754b2d44395c4bbc17e1f7102f4c92d0a Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Thu, 12 Sep 2024 18:26:29 -0600 Subject: [PATCH 15/29] Add NoSwingBreak --- .../checks/impl/breaking/FastBreak.java | 13 +++++- .../checks/impl/breaking/NoSwingBreak.java | 43 +++++++++++++++++++ .../ac/grim/grimac/manager/CheckManager.java | 1 + 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/main/java/ac/grim/grimac/checks/impl/breaking/NoSwingBreak.java diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java index f5ef0e90c0..a252813cd1 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java @@ -13,6 +13,7 @@ import ac.grim.grimac.utils.nmsutil.ReachUtils; import com.github.retrooper.packetevents.event.PacketReceiveEvent; import com.github.retrooper.packetevents.protocol.attribute.Attributes; +import com.github.retrooper.packetevents.protocol.packettype.PacketType; import com.github.retrooper.packetevents.protocol.player.ClientVersion; import com.github.retrooper.packetevents.protocol.player.DiggingAction; import com.github.retrooper.packetevents.protocol.world.BlockFace; @@ -35,6 +36,7 @@ public FastBreak(GrimPlayer playerData) { private Vector3i targetBlock = null; private double progress; + private boolean sentAnimation; @Override public void onBlockBreak(BlockBreak blockBreak) { @@ -62,9 +64,14 @@ public void onBlockBreak(BlockBreak blockBreak) { @Override public void onPacketReceive(PacketReceiveEvent event) { if (targetBlock == null) { + sentAnimation = false; return; } + if (event.getPacketType() == PacketType.Play.Client.ANIMATION) { + sentAnimation = true; + } + if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) { if (!player.compensatedEntities.getSelf().inVehicle()) { if (!didRayTraceHit() || !isWithinRange()) { @@ -72,7 +79,11 @@ public void onPacketReceive(PacketReceiveEvent event) { } } - progress += BlockBreakSpeed.getBlockDamage(player, targetBlock); + if (sentAnimation) { + progress += BlockBreakSpeed.getBlockDamage(player, targetBlock); + } + + sentAnimation = false; } } diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/NoSwingBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/NoSwingBreak.java new file mode 100644 index 0000000000..d62e0324f7 --- /dev/null +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/NoSwingBreak.java @@ -0,0 +1,43 @@ +package ac.grim.grimac.checks.impl.breaking; + +import ac.grim.grimac.checks.Check; +import ac.grim.grimac.checks.CheckData; +import ac.grim.grimac.checks.type.BlockBreakCheck; +import ac.grim.grimac.player.GrimPlayer; +import ac.grim.grimac.utils.anticheat.update.BlockBreak; +import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.protocol.packettype.PacketType; +import com.github.retrooper.packetevents.protocol.player.DiggingAction; +import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; + +@CheckData(name = "NoSwingBreak") +public class NoSwingBreak extends Check implements BlockBreakCheck { + public NoSwingBreak(GrimPlayer playerData) { + super(playerData); + } + + private boolean sentAnimation; + private boolean sentBreak; + + @Override + public void onBlockBreak(BlockBreak blockBreak) { + if (blockBreak.action != DiggingAction.CANCELLED_DIGGING) { + sentBreak = true; + } + } + + @Override + public void onPacketReceive(PacketReceiveEvent event) { + if (event.getPacketType() == PacketType.Play.Client.ANIMATION) { + sentAnimation = true; + } + + if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) { + if (sentBreak && !sentAnimation) { + flagAndAlert(); + } + + sentAnimation = sentBreak = false; + } + } +} diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index 2af3bd7d21..c506294913 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -154,6 +154,7 @@ public CheckManager(GrimPlayer player) { .put(PositionBreakA.class, new PositionBreakA(player)) .put(PositionBreakB.class, new PositionBreakB(player)) .put(FarBreak.class, new FarBreak(player)) + .put(NoSwingBreak.class, new NoSwingBreak(player)) .put(FastBreak.class, new FastBreak(player)) .build(); From 3cf1366c4c91443e86fdb24bc2af1f568d903ffc Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Fri, 13 Sep 2024 15:47:24 -0600 Subject: [PATCH 16/29] do not check noswing in fastbreak --- .../grimac/checks/impl/breaking/FastBreak.java | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java index a252813cd1..4bd3253513 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java @@ -36,7 +36,6 @@ public FastBreak(GrimPlayer playerData) { private Vector3i targetBlock = null; private double progress; - private boolean sentAnimation; @Override public void onBlockBreak(BlockBreak blockBreak) { @@ -64,26 +63,13 @@ public void onBlockBreak(BlockBreak blockBreak) { @Override public void onPacketReceive(PacketReceiveEvent event) { if (targetBlock == null) { - sentAnimation = false; return; } - if (event.getPacketType() == PacketType.Play.Client.ANIMATION) { - sentAnimation = true; - } - if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) { - if (!player.compensatedEntities.getSelf().inVehicle()) { - if (!didRayTraceHit() || !isWithinRange()) { - return; - } - } - - if (sentAnimation) { + if (player.compensatedEntities.getSelf().inVehicle() || didRayTraceHit() && isWithinRange()) { progress += BlockBreakSpeed.getBlockDamage(player, targetBlock); } - - sentAnimation = false; } } From 5daca09aae71d9c6765bd846491bf3dcfc21d0e8 Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Thu, 19 Sep 2024 16:54:59 -0600 Subject: [PATCH 17/29] Add MultiBreak --- .../checks/impl/breaking/MultiBreak.java | 72 +++++++++++++++++++ .../grimac/checks/type/BlockBreakCheck.java | 2 +- .../ac/grim/grimac/manager/CheckManager.java | 4 ++ 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 src/main/java/ac/grim/grimac/checks/impl/breaking/MultiBreak.java diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/MultiBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/MultiBreak.java new file mode 100644 index 0000000000..a9505786f4 --- /dev/null +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/MultiBreak.java @@ -0,0 +1,72 @@ +package ac.grim.grimac.checks.impl.breaking; + +import ac.grim.grimac.checks.Check; +import ac.grim.grimac.checks.CheckData; +import ac.grim.grimac.checks.type.BlockBreakCheck; +import ac.grim.grimac.player.GrimPlayer; +import ac.grim.grimac.utils.anticheat.MessageUtil; +import ac.grim.grimac.utils.anticheat.update.BlockBreak; +import ac.grim.grimac.utils.anticheat.update.PredictionComplete; +import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.player.DiggingAction; +import com.github.retrooper.packetevents.protocol.world.BlockFace; +import com.github.retrooper.packetevents.util.Vector3i; +import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; + +import java.util.ArrayList; +import java.util.List; + +@CheckData(name = "MultiBreak", experimental = true) +public class MultiBreak extends Check implements BlockBreakCheck { + public MultiBreak(GrimPlayer player) { + super(player); + } + + private final List flags = new ArrayList<>(); + + private boolean hasBroken; + private BlockFace lastFace; + private Vector3i lastPos; + + @Override + public void onBlockBreak(BlockBreak blockBreak) { + if (blockBreak.action == DiggingAction.CANCELLED_DIGGING) { + return; + } + + if (hasBroken && (blockBreak.face != lastFace || !blockBreak.position.equals(lastPos))) { + final String verbose = "face=" + blockBreak.face + ", lastFace=" + lastFace + + ", pos=" + MessageUtil.toUnlabledString(blockBreak.position) + ", lastPos=" + MessageUtil.toUnlabledString(lastPos); + if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) { + if (flagAndAlert(verbose) && shouldModifyPackets()) { + blockBreak.cancel(); + } + } else { + flags.add(verbose); + } + } + + lastFace = blockBreak.face; + lastPos = blockBreak.position; + hasBroken = true; + } + + @Override + public void onPacketReceive(PacketReceiveEvent event) { + if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) { + hasBroken = false; + } + } + + @Override + public void onPredictionComplete(PredictionComplete predictionComplete) { + if (player.getClientVersion().isNewerThan(ClientVersion.V_1_8) && !player.skippedTickInActualMovement) { + for (String verbose : flags) { + flagAndAlert(verbose); + } + } + + flags.clear(); + } +} diff --git a/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java b/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java index 7363fa2afb..07b7722fa3 100644 --- a/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java +++ b/src/main/java/ac/grim/grimac/checks/type/BlockBreakCheck.java @@ -2,7 +2,7 @@ import ac.grim.grimac.utils.anticheat.update.BlockBreak; -public interface BlockBreakCheck extends PacketCheck { +public interface BlockBreakCheck extends PostPredictionCheck { default void onBlockBreak(final BlockBreak blockBreak) {} default void onPostFlyingBlockBreak(final BlockBreak blockBreak) {} } diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index c506294913..a4581b09dc 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -153,6 +153,7 @@ public CheckManager(GrimPlayer player) { .put(LiquidAirBreak.class, new LiquidAirBreak(player)) .put(PositionBreakA.class, new PositionBreakA(player)) .put(PositionBreakB.class, new PositionBreakB(player)) + .put(MultiBreak.class, new MultiBreak(player)) .put(FarBreak.class, new FarBreak(player)) .put(NoSwingBreak.class, new NoSwingBreak(player)) .put(FastBreak.class, new FastBreak(player)) @@ -264,6 +265,9 @@ public void onPredictionFinish(final PredictionComplete complete) { for (BlockPlaceCheck check : blockPlaceCheck.values()) { check.onPredictionComplete(complete); } + for (BlockBreakCheck check : blockBreakChecks.values()) { + check.onPredictionComplete(complete); + } } public void onBlockPlace(final BlockPlace place) { From 2093341830cef8d634ddb6bd758c083d062e67e5 Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Thu, 19 Sep 2024 16:56:03 -0600 Subject: [PATCH 18/29] LiquidAirBreak -> AirLiquidBreak --- .../breaking/{LiquidAirBreak.java => AirLiquidBreak.java} | 6 +++--- src/main/java/ac/grim/grimac/manager/CheckManager.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename src/main/java/ac/grim/grimac/checks/impl/breaking/{LiquidAirBreak.java => AirLiquidBreak.java} (91%) diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/LiquidAirBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/AirLiquidBreak.java similarity index 91% rename from src/main/java/ac/grim/grimac/checks/impl/breaking/LiquidAirBreak.java rename to src/main/java/ac/grim/grimac/checks/impl/breaking/AirLiquidBreak.java index d066c9a239..162d202640 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/LiquidAirBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/AirLiquidBreak.java @@ -11,9 +11,9 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateType; import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; -@CheckData(name = "LiquidAirBreak", experimental = true) -public class LiquidAirBreak extends Check implements BlockBreakCheck { - public LiquidAirBreak(GrimPlayer player) { +@CheckData(name = "AirLiquidBreak", experimental = true) +public class AirLiquidBreak extends Check implements BlockBreakCheck { + public AirLiquidBreak(GrimPlayer player) { super(player); } diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index a4581b09dc..4528b05125 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -150,7 +150,7 @@ public CheckManager(GrimPlayer player) { blockBreakChecks = new ImmutableClassToInstanceMap.Builder() .put(RotationBreak.class, new RotationBreak(player)) .put(WrongBreak.class, new WrongBreak(player)) - .put(LiquidAirBreak.class, new LiquidAirBreak(player)) + .put(AirLiquidBreak.class, new AirLiquidBreak(player)) .put(PositionBreakA.class, new PositionBreakA(player)) .put(PositionBreakB.class, new PositionBreakB(player)) .put(MultiBreak.class, new MultiBreak(player)) From e0c331dc9cd3e9ac716e539cc03f670975b78b8b Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Thu, 19 Sep 2024 18:08:56 -0600 Subject: [PATCH 19/29] experimental --- src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java | 2 +- .../java/ac/grim/grimac/checks/impl/breaking/NoSwingBreak.java | 2 +- .../ac/grim/grimac/checks/impl/breaking/PositionBreakA.java | 2 +- .../ac/grim/grimac/checks/impl/breaking/PositionBreakB.java | 2 +- .../java/ac/grim/grimac/checks/impl/breaking/RotationBreak.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java index 4ed71d5769..161ca1222e 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java @@ -11,7 +11,7 @@ import com.github.retrooper.packetevents.protocol.player.DiggingAction; import org.bukkit.util.Vector; -@CheckData(name = "FarBreak") +@CheckData(name = "FarBreak", experimental = true) public class FarBreak extends Check implements BlockBreakCheck { public FarBreak(GrimPlayer player) { super(player); diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/NoSwingBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/NoSwingBreak.java index d62e0324f7..b774970ad1 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/NoSwingBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/NoSwingBreak.java @@ -10,7 +10,7 @@ import com.github.retrooper.packetevents.protocol.player.DiggingAction; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; -@CheckData(name = "NoSwingBreak") +@CheckData(name = "NoSwingBreak", experimental = true) public class NoSwingBreak extends Check implements BlockBreakCheck { public NoSwingBreak(GrimPlayer playerData) { super(playerData); diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java index f74e51616d..14264c7237 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakA.java @@ -11,7 +11,7 @@ import java.util.Collections; -@CheckData(name = "PositionBreakA") +@CheckData(name = "PositionBreakA", experimental = true) public class PositionBreakA extends Check implements BlockBreakCheck { public PositionBreakA(GrimPlayer player) { super(player); diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakB.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakB.java index 5b2adee7fb..5de10e30ad 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakB.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/PositionBreakB.java @@ -9,7 +9,7 @@ import com.github.retrooper.packetevents.protocol.player.DiggingAction; import com.github.retrooper.packetevents.protocol.world.BlockFace; -@CheckData(name = "PositionBreakB") +@CheckData(name = "PositionBreakB", experimental = true) public class PositionBreakB extends Check implements BlockBreakCheck { public PositionBreakB(GrimPlayer player) { super(player); diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/RotationBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/RotationBreak.java index 34dc716226..b1bb0e1a41 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/RotationBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/RotationBreak.java @@ -23,7 +23,7 @@ import java.util.Collections; import java.util.List; -@CheckData(name = "RotationBreak") +@CheckData(name = "RotationBreak", experimental = true) public class RotationBreak extends Check implements BlockBreakCheck { public RotationBreak(GrimPlayer player) { super(player); From cde52a154999daf449f76be94894a37bbfbd8a5e Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Thu, 19 Sep 2024 18:11:21 -0600 Subject: [PATCH 20/29] I'll do this for now --- .../impl/breaking/{FastBreak.java => FastBreakB.java} | 7 +++---- .../impl/misc/{OldFastBreak.java => FastBreakA.java} | 9 ++++----- src/main/java/ac/grim/grimac/manager/CheckManager.java | 6 +++--- 3 files changed, 10 insertions(+), 12 deletions(-) rename src/main/java/ac/grim/grimac/checks/impl/breaking/{FastBreak.java => FastBreakB.java} (96%) rename src/main/java/ac/grim/grimac/checks/impl/misc/{OldFastBreak.java => FastBreakA.java} (96%) diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java similarity index 96% rename from src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java rename to src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java index 4bd3253513..b5c7710dcc 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java @@ -13,7 +13,6 @@ import ac.grim.grimac.utils.nmsutil.ReachUtils; import com.github.retrooper.packetevents.event.PacketReceiveEvent; import com.github.retrooper.packetevents.protocol.attribute.Attributes; -import com.github.retrooper.packetevents.protocol.packettype.PacketType; import com.github.retrooper.packetevents.protocol.player.ClientVersion; import com.github.retrooper.packetevents.protocol.player.DiggingAction; import com.github.retrooper.packetevents.protocol.world.BlockFace; @@ -28,9 +27,9 @@ import java.util.Collections; import java.util.List; -@CheckData(name = "FastBreak") -public class FastBreak extends Check implements BlockBreakCheck { - public FastBreak(GrimPlayer playerData) { +@CheckData(name = "FastBreakB", experimental = true) +public class FastBreakB extends Check implements BlockBreakCheck { + public FastBreakB(GrimPlayer playerData) { super(playerData); } diff --git a/src/main/java/ac/grim/grimac/checks/impl/misc/OldFastBreak.java b/src/main/java/ac/grim/grimac/checks/impl/misc/FastBreakA.java similarity index 96% rename from src/main/java/ac/grim/grimac/checks/impl/misc/OldFastBreak.java rename to src/main/java/ac/grim/grimac/checks/impl/misc/FastBreakA.java index f4960cfdd5..cb6d1e1d37 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/misc/OldFastBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/misc/FastBreakA.java @@ -17,7 +17,6 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; import com.github.retrooper.packetevents.util.Vector3i; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerDigging; -import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerAcknowledgeBlockChanges; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerBlockChange; import io.github.retrooper.packetevents.util.folia.FoliaScheduler; @@ -29,9 +28,9 @@ // Based loosely off of Hawk BlockBreakSpeedSurvival // Also based loosely off of NoCheatPlus FastBreak // Also based off minecraft wiki: https://minecraft.wiki/w/Breaking#Instant_breaking -@CheckData(name = "OldFastBreak") -public class OldFastBreak extends Check implements PacketCheck { - public OldFastBreak(GrimPlayer playerData) { +@CheckData(name = "FastBreakA") +public class FastBreakA extends Check implements PacketCheck { + public FastBreakA(GrimPlayer playerData) { super(playerData); } @@ -51,7 +50,7 @@ public OldFastBreak(GrimPlayer playerData) { @Override public void onPacketReceive(PacketReceiveEvent event) { - if (player.getClientVersion().isOlderThan(ClientVersion.V_1_9)) { + if (player.getClientVersion().isOlderThan(ClientVersion.V_1_9) && GrimAPI.INSTANCE.getConfigManager().isExperimentalChecks()) { return; } diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index 4528b05125..db8cab0129 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -13,7 +13,7 @@ import ac.grim.grimac.checks.impl.exploit.ExploitB; import ac.grim.grimac.checks.impl.groundspoof.NoFallA; import ac.grim.grimac.checks.impl.misc.ClientBrand; -import ac.grim.grimac.checks.impl.misc.OldFastBreak; +import ac.grim.grimac.checks.impl.misc.FastBreakA; import ac.grim.grimac.checks.impl.misc.GhostBlockMitigation; import ac.grim.grimac.checks.impl.misc.TransactionOrder; import ac.grim.grimac.checks.impl.movement.*; @@ -93,7 +93,7 @@ public CheckManager(GrimPlayer player) { .put(BadPacketsV.class, new BadPacketsV(player)) .put(BadPacketsW.class, new BadPacketsW(player)) .put(BadPacketsY.class, new BadPacketsY(player)) - .put(OldFastBreak.class, new OldFastBreak(player)) + .put(FastBreakA.class, new FastBreakA(player)) .put(TransactionOrder.class, new TransactionOrder(player)) .put(NoSlowB.class, new NoSlowB(player)) .put(SetbackBlocker.class, new SetbackBlocker(player)) // Must be last class otherwise we can't check while blocking packets @@ -156,7 +156,7 @@ public CheckManager(GrimPlayer player) { .put(MultiBreak.class, new MultiBreak(player)) .put(FarBreak.class, new FarBreak(player)) .put(NoSwingBreak.class, new NoSwingBreak(player)) - .put(FastBreak.class, new FastBreak(player)) + .put(FastBreakB.class, new FastBreakB(player)) .build(); prePredictionChecks = new ImmutableClassToInstanceMap.Builder() From 6f7520cbf0ba06050e44ec52762573b3757f81cb Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Fri, 20 Sep 2024 20:00:44 -0600 Subject: [PATCH 21/29] performance --- .../java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java index b5c7710dcc..e05dd23441 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java @@ -61,7 +61,7 @@ public void onBlockBreak(BlockBreak blockBreak) { @Override public void onPacketReceive(PacketReceiveEvent event) { - if (targetBlock == null) { + if (targetBlock == null || progress > 1) { return; } From 37d28c3cb1f4819081b84bc3c49a5cdb4f6531af Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Fri, 20 Sep 2024 20:02:21 -0600 Subject: [PATCH 22/29] you can't break blocks while using items --- .../ac/grim/grimac/checks/impl/breaking/FastBreakB.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java index e05dd23441..f7df9718dc 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java @@ -66,8 +66,10 @@ public void onPacketReceive(PacketReceiveEvent event) { } if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) { - if (player.compensatedEntities.getSelf().inVehicle() || didRayTraceHit() && isWithinRange()) { - progress += BlockBreakSpeed.getBlockDamage(player, targetBlock); + if (!player.packetStateData.isSlowedByUsingItem()) { + if (player.compensatedEntities.getSelf().inVehicle() || didRayTraceHit() && isWithinRange()) { + progress += BlockBreakSpeed.getBlockDamage(player, targetBlock); + } } } } From c5e7a7d61e0aef2e5ba38e070936164a398c3a5a Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Fri, 20 Sep 2024 20:04:05 -0600 Subject: [PATCH 23/29] except on 1.7 --- .../java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java index f7df9718dc..e4ee6e0cb8 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java @@ -66,7 +66,7 @@ public void onPacketReceive(PacketReceiveEvent event) { } if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) { - if (!player.packetStateData.isSlowedByUsingItem()) { + if (!player.packetStateData.isSlowedByUsingItem() || player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_7_10)) { if (player.compensatedEntities.getSelf().inVehicle() || didRayTraceHit() && isWithinRange()) { progress += BlockBreakSpeed.getBlockDamage(player, targetBlock); } From 215e4c5f0dd0b5884ce4d5f329dc25905229f587 Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Fri, 20 Sep 2024 20:17:41 -0600 Subject: [PATCH 24/29] fix false --- .../ac/grim/grimac/checks/impl/breaking/FastBreakB.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java index e4ee6e0cb8..03d4bf32b7 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakB.java @@ -53,15 +53,11 @@ public void onBlockBreak(BlockBreak blockBreak) { player.onPacketCancel(); } } - - if (blockBreak.action == DiggingAction.CANCELLED_DIGGING && player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4)) { - progress = 0; - } } @Override public void onPacketReceive(PacketReceiveEvent event) { - if (targetBlock == null || progress > 1) { + if (targetBlock == null || progress >= 1) { return; } From f774e0d1b95687b3937f5fcd382ed5b2f7fc6e69 Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Mon, 14 Oct 2024 14:53:04 -0600 Subject: [PATCH 25/29] oops --- src/main/java/ac/grim/grimac/checks/impl/misc/FastBreakA.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/ac/grim/grimac/checks/impl/misc/FastBreakA.java b/src/main/java/ac/grim/grimac/checks/impl/misc/FastBreakA.java index cb6d1e1d37..f3333a47f1 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/misc/FastBreakA.java +++ b/src/main/java/ac/grim/grimac/checks/impl/misc/FastBreakA.java @@ -17,6 +17,7 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; import com.github.retrooper.packetevents.util.Vector3i; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerDigging; +import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerAcknowledgeBlockChanges; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerBlockChange; import io.github.retrooper.packetevents.util.folia.FoliaScheduler; @@ -55,7 +56,8 @@ public void onPacketReceive(PacketReceiveEvent event) { } // Find the most optimal block damage using the animation packet, which is sent at least once a tick when breaking blocks - if (event.getPacketType() == PacketType.Play.Client.ANIMATION && targetBlock != null) { + // On 1.8 clients, via screws with this packet meaning we must fall back to the 1.8 idle flying packet + if ((player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? event.getPacketType() == PacketType.Play.Client.ANIMATION : WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) && targetBlock != null) { maximumBlockDamage = Math.max(maximumBlockDamage, BlockBreakSpeed.getBlockDamage(player, targetBlock)); } From f310a6e04de2d0fa1b729a7d0c056d02b63cb9f0 Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Mon, 14 Oct 2024 14:54:40 -0600 Subject: [PATCH 26/29] I don't like cancels --- .../grimac/checks/impl/breaking/FarBreak.java | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java index 161ca1222e..b754e23ccd 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java @@ -19,26 +19,12 @@ public FarBreak(GrimPlayer player) { @Override public void onBlockBreak(BlockBreak blockBreak) { - if (player.compensatedEntities.getSelf().inVehicle()) return; // falses - - double x = player.x; - double y = player.y; - double z = player.z; - - if (blockBreak.action == DiggingAction.CANCELLED_DIGGING) { - if (blockBreak.isWeirdCancel) { - return; - } - - x = player.lastX; - y = player.lastY; - z = player.lastZ; - } + if (player.compensatedEntities.getSelf().inVehicle() || blockBreak.action == DiggingAction.CANCELLED_DIGGING) return; // falses double min = Double.MAX_VALUE; for (double d : player.getPossibleEyeHeights()) { SimpleCollisionBox box = new SimpleCollisionBox(blockBreak.position); - Vector eyes = new Vector(x, y + d, z); + Vector eyes = new Vector(player.x, player.y + d, player.z); Vector best = VectorUtils.cutBoxToVector(eyes, box); min = Math.min(min, eyes.distanceSquared(best)); } From b6df7a3a1addc26a25ca12ecc8ae7eadd0bef7c1 Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Mon, 14 Oct 2024 14:55:13 -0600 Subject: [PATCH 27/29] fix MultiBreak false --- .../java/ac/grim/grimac/checks/impl/breaking/MultiBreak.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/MultiBreak.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/MultiBreak.java index a9505786f4..b48137dc44 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/breaking/MultiBreak.java +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/MultiBreak.java @@ -61,7 +61,7 @@ public void onPacketReceive(PacketReceiveEvent event) { @Override public void onPredictionComplete(PredictionComplete predictionComplete) { - if (player.getClientVersion().isNewerThan(ClientVersion.V_1_8) && !player.skippedTickInActualMovement) { + if (player.getClientVersion().isNewerThan(ClientVersion.V_1_8) && !player.skippedTickInActualMovement && predictionComplete.isChecked()) { for (String verbose : flags) { flagAndAlert(verbose); } From f6e65004bdfee8790d93d839fe070ae38106bf5b Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Sat, 26 Oct 2024 13:11:44 -0600 Subject: [PATCH 28/29] NoBreakDelay --- .../checks/impl/breaking/NoBreakDelay.java | 59 +++++++++++++++++++ .../impl/breaking/NoBreakDelayMitigation.java | 45 ++++++++++++++ .../ac/grim/grimac/manager/CheckManager.java | 2 + .../ac/grim/grimac/utils/math/GrimMath.java | 7 +++ src/main/resources/config/de.yml | 6 ++ src/main/resources/config/en.yml | 6 ++ src/main/resources/config/es.yml | 6 ++ src/main/resources/config/fr.yml | 6 ++ src/main/resources/config/it.yml | 6 ++ src/main/resources/config/nl.yml | 6 ++ src/main/resources/config/pt.yml | 6 ++ src/main/resources/config/ru.yml | 6 ++ src/main/resources/config/tr.yml | 6 ++ src/main/resources/config/zh.yml | 6 ++ 14 files changed, 173 insertions(+) create mode 100644 src/main/java/ac/grim/grimac/checks/impl/breaking/NoBreakDelay.java create mode 100644 src/main/java/ac/grim/grimac/checks/impl/breaking/NoBreakDelayMitigation.java diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/NoBreakDelay.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/NoBreakDelay.java new file mode 100644 index 0000000000..9d75f86483 --- /dev/null +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/NoBreakDelay.java @@ -0,0 +1,59 @@ +package ac.grim.grimac.checks.impl.breaking; + +import ac.grim.grimac.checks.Check; +import ac.grim.grimac.checks.CheckData; +import ac.grim.grimac.checks.type.BlockBreakCheck; +import ac.grim.grimac.player.GrimPlayer; +import ac.grim.grimac.utils.anticheat.update.BlockBreak; +import ac.grim.grimac.utils.anticheat.update.PredictionComplete; +import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.player.DiggingAction; +import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; + +@CheckData(name = "NoBreakDelay", experimental = true) +public class NoBreakDelay extends Check implements BlockBreakCheck { + public NoBreakDelay(GrimPlayer player) { + super(player); + } + + private boolean hasFinished; + private int flags; + + @Override + public void onBlockBreak(BlockBreak blockBreak) { + if (blockBreak.action == DiggingAction.START_DIGGING) { + if (hasFinished) { + if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) { + if (flagAndAlert() && shouldModifyPackets()) { + blockBreak.cancel(); + } + } else { + flags++; + } + } + } + + if (blockBreak.action == DiggingAction.FINISHED_DIGGING) { + hasFinished = true; + } + } + + @Override + public void onPacketReceive(PacketReceiveEvent event) { + if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType()) && !player.packetStateData.lastPacketWasTeleport && !player.packetStateData.lastPacketWasOnePointSeventeenDuplicate) { + hasFinished = false; + } + } + + @Override + public void onPredictionComplete(PredictionComplete predictionComplete) { + if (!player.skippedTickInActualMovement) { + for (; flags > 0; flags--) { + flagAndAlert(); + } + } + + flags = 0; + } +} diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/NoBreakDelayMitigation.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/NoBreakDelayMitigation.java new file mode 100644 index 0000000000..ae80b9362c --- /dev/null +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/NoBreakDelayMitigation.java @@ -0,0 +1,45 @@ +package ac.grim.grimac.checks.impl.breaking; + +import ac.grim.grimac.api.config.ConfigManager; +import ac.grim.grimac.checks.Check; +import ac.grim.grimac.checks.type.BlockBreakCheck; +import ac.grim.grimac.player.GrimPlayer; +import ac.grim.grimac.utils.anticheat.update.BlockBreak; +import ac.grim.grimac.utils.math.GrimMath; +import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.player.DiggingAction; +import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; + +public class NoBreakDelayMitigation extends Check implements BlockBreakCheck { + public NoBreakDelayMitigation(GrimPlayer player) { + super(player); + } + + private int minTicks; + private int ticks; + + @Override + public void onBlockBreak(BlockBreak blockBreak) { + if (blockBreak.action == DiggingAction.START_DIGGING + && player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8) + && ticks < minTicks + ) blockBreak.cancel(); + + if (blockBreak.action == DiggingAction.FINISHED_DIGGING) { + ticks = 0; + } + } + + @Override + public void onPacketReceive(PacketReceiveEvent event) { + if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType()) && !player.packetStateData.lastPacketWasTeleport && !player.packetStateData.lastPacketWasOnePointSeventeenDuplicate) { + ticks++; + } + } + + @Override + public void onReload(ConfigManager config) { + minTicks = GrimMath.clampInt(config.getIntElse("min-break-delay", 3), 0, 6); + } +} diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index db8cab0129..0a80c37981 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -156,6 +156,8 @@ public CheckManager(GrimPlayer player) { .put(MultiBreak.class, new MultiBreak(player)) .put(FarBreak.class, new FarBreak(player)) .put(NoSwingBreak.class, new NoSwingBreak(player)) + .put(NoBreakDelay.class, new NoBreakDelay(player)) + .put(NoBreakDelayMitigation.class, new NoBreakDelayMitigation(player)) .put(FastBreakB.class, new FastBreakB(player)) .build(); diff --git a/src/main/java/ac/grim/grimac/utils/math/GrimMath.java b/src/main/java/ac/grim/grimac/utils/math/GrimMath.java index b9758391e2..47eb64a847 100644 --- a/src/main/java/ac/grim/grimac/utils/math/GrimMath.java +++ b/src/main/java/ac/grim/grimac/utils/math/GrimMath.java @@ -60,6 +60,13 @@ public static double clamp(double num, double min, double max) { return Math.min(num, max); } + public static int clampInt(int num, int min, int max) { + if (num < min) { + return min; + } + return Math.min(num, max); + } + public static float clampFloat(float num, float min, float max) { if (num < min) { return min; diff --git a/src/main/resources/config/de.yml b/src/main/resources/config/de.yml index 29d10af784..45d4a3e874 100644 --- a/src/main/resources/config/de.yml +++ b/src/main/resources/config/de.yml @@ -164,6 +164,12 @@ exploit: # Ihr gültiger Bereich ist von 2 bis 4 begrenzt distance-to-check-if-ghostblocks: 2 +# The minimum tick delay allowed between block breaks. +# this is usually 6, but releasing the block break key resets this +# delay, thus there is no alert for break delays less than this. +# Only affects pre-1.9 clients, and must be from 0 to 6. +min-break-delay: 3 + # Aktivieren Sie die Protokollierung von Plugins, die in netty on join injiziert wurden, um Kompatibilitätsprobleme zu beheben. debug-pipeline-on-join: false diff --git a/src/main/resources/config/en.yml b/src/main/resources/config/en.yml index aff61a8f20..2c37cfcd7d 100644 --- a/src/main/resources/config/en.yml +++ b/src/main/resources/config/en.yml @@ -167,6 +167,12 @@ exploit: # Its valid range is limited from 2 to 4 distance-to-check-if-ghostblocks: 2 +# The minimum tick delay allowed between block breaks. +# this is usually 6, but releasing the block break key resets this +# delay, thus there is no alert for break delays less than this. +# Only affects pre-1.9 clients, and must be from 0 to 6. +min-break-delay: 3 + # Enable logging plugins who have injected into netty on join to debug compatibility issues debug-pipeline-on-join: false diff --git a/src/main/resources/config/es.yml b/src/main/resources/config/es.yml index b83737e466..08abc43525 100644 --- a/src/main/resources/config/es.yml +++ b/src/main/resources/config/es.yml @@ -168,6 +168,12 @@ exploit: allow-building-on-ghostblocks: true distance-to-check-if-ghostblocks: 2 +# The minimum tick delay allowed between block breaks. +# this is usually 6, but releasing the block break key resets this +# delay, thus there is no alert for break delays less than this. +# Only affects pre-1.9 clients, and must be from 0 to 6. +min-break-delay: 3 + # Habilitar el registro de plugins que se han inyectado a netty para intentar resolver problemas de compatibilidad. debug-pipeline-on-join: false diff --git a/src/main/resources/config/fr.yml b/src/main/resources/config/fr.yml index 0e1c36c451..dd8886e7cd 100644 --- a/src/main/resources/config/fr.yml +++ b/src/main/resources/config/fr.yml @@ -163,6 +163,12 @@ exploit: allow-building-on-ghostblocks: true distance-to-check-if-ghostblocks: 2 +# The minimum tick delay allowed between block breaks. +# this is usually 6, but releasing the block break key resets this +# delay, thus there is no alert for break delays less than this. +# Only affects pre-1.9 clients, and must be from 0 to 6. +min-break-delay: 3 + # Activer l'enregistrement des plugins ayant injecté dans Netty lors de la connexion pour déboguer les problèmes de compatibilité debug-pipeline-on-join: false diff --git a/src/main/resources/config/it.yml b/src/main/resources/config/it.yml index 82926afb77..eb12a43759 100644 --- a/src/main/resources/config/it.yml +++ b/src/main/resources/config/it.yml @@ -144,6 +144,12 @@ exploit: # Distanza per controllare i ghost blocks distance-to-check-if-ghostblocks: 2 +# The minimum tick delay allowed between block breaks. +# this is usually 6, but releasing the block break key resets this +# delay, thus there is no alert for break delays less than this. +# Only affects pre-1.9 clients, and must be from 0 to 6. +min-break-delay: 3 + # Enable logging plugins who have injected into netty on join to debug compatibility issues debug-pipeline-on-join: false diff --git a/src/main/resources/config/nl.yml b/src/main/resources/config/nl.yml index f198782f54..87422a45a8 100644 --- a/src/main/resources/config/nl.yml +++ b/src/main/resources/config/nl.yml @@ -167,6 +167,12 @@ exploit: # Het geldige bereik is beperkt van 2 tot 4 distance-to-check-if-ghostblocks: 2 +# The minimum tick delay allowed between block breaks. +# this is usually 6, but releasing the block break key resets this +# delay, thus there is no alert for break delays less than this. +# Only affects pre-1.9 clients, and must be from 0 to 6. +min-break-delay: 3 + # Logging plugins inschakelen die geïnjecteerd zijn in netty on join om compatibiliteitsproblemen te debuggen debug-pipeline-on-join: false diff --git a/src/main/resources/config/pt.yml b/src/main/resources/config/pt.yml index 386bf6d103..46a899b11d 100644 --- a/src/main/resources/config/pt.yml +++ b/src/main/resources/config/pt.yml @@ -172,6 +172,12 @@ exploit: # O valor válido é limitado de 2 a 4. distance-to-check-if-ghostblocks: 2 +# The minimum tick delay allowed between block breaks. +# this is usually 6, but releasing the block break key resets this +# delay, thus there is no alert for break delays less than this. +# Only affects pre-1.9 clients, and must be from 0 to 6. +min-break-delay: 3 + # Registra plugins que são injetados na netty ao entrar para depurar erros de compatibilidade. debug-pipeline-on-join: false diff --git a/src/main/resources/config/ru.yml b/src/main/resources/config/ru.yml index 0cd1bae724..225738caad 100644 --- a/src/main/resources/config/ru.yml +++ b/src/main/resources/config/ru.yml @@ -163,6 +163,12 @@ exploit: allow-building-on-ghostblocks: true distance-to-check-if-ghostblocks: 2 +# The minimum tick delay allowed between block breaks. +# this is usually 6, but releasing the block break key resets this +# delay, thus there is no alert for break delays less than this. +# Only affects pre-1.9 clients, and must be from 0 to 6. +min-break-delay: 3 + # Включить запись в журнал плагинов, которые внедрились в netty при присоединении для отладки проблем совместимости debug-pipeline-on-join: false diff --git a/src/main/resources/config/tr.yml b/src/main/resources/config/tr.yml index 4e5e23c480..90ad136b90 100644 --- a/src/main/resources/config/tr.yml +++ b/src/main/resources/config/tr.yml @@ -167,6 +167,12 @@ exploit: # Geçerli aralığı 2 ile 4 arasında sınırlıdır distance-to-check-if-ghostblocks: 2 +# The minimum tick delay allowed between block breaks. +# this is usually 6, but releasing the block break key resets this +# delay, thus there is no alert for break delays less than this. +# Only affects pre-1.9 clients, and must be from 0 to 6. +min-break-delay: 3 + # Netty'ye enjekte olan eklentileri giriş sırasında günlüklemeyi etkinleştirerek uyumluluk sorunlarını gider debug-pipeline-on-join: false diff --git a/src/main/resources/config/zh.yml b/src/main/resources/config/zh.yml index 01cacd08eb..0872a54128 100644 --- a/src/main/resources/config/zh.yml +++ b/src/main/resources/config/zh.yml @@ -165,6 +165,12 @@ exploit: allow-building-on-ghostblocks: true distance-to-check-if-ghostblocks: 2 +# The minimum tick delay allowed between block breaks. +# this is usually 6, but releasing the block break key resets this +# delay, thus there is no alert for break delays less than this. +# Only affects pre-1.9 clients, and must be from 0 to 6. +min-break-delay: 3 + # 启用在加入时注入 netty 的日志插件以调试兼容性问题 debug-pipeline-on-join: false From 262126df9b84578b6985883a30847e8e377101d6 Mon Sep 17 00:00:00 2001 From: ManInMyVan Date: Sat, 26 Oct 2024 16:18:24 -0600 Subject: [PATCH 29/29] make FastBreakA a BlockBreakCheck --- .../checks/impl/breaking/FastBreakA.java | 122 ++++++++++++++ .../grimac/checks/impl/misc/FastBreakA.java | 159 ------------------ .../events/packets/CheckManagerListener.java | 2 +- .../events/packets/patch/ResyncWorldUtil.java | 33 ++++ .../ac/grim/grimac/manager/CheckManager.java | 4 +- 5 files changed, 158 insertions(+), 162 deletions(-) create mode 100644 src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakA.java delete mode 100644 src/main/java/ac/grim/grimac/checks/impl/misc/FastBreakA.java diff --git a/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakA.java b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakA.java new file mode 100644 index 0000000000..3c637c6ac0 --- /dev/null +++ b/src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakA.java @@ -0,0 +1,122 @@ +package ac.grim.grimac.checks.impl.breaking; + +import ac.grim.grimac.GrimAPI; +import ac.grim.grimac.checks.Check; +import ac.grim.grimac.checks.CheckData; +import ac.grim.grimac.checks.type.BlockBreakCheck; +import ac.grim.grimac.player.GrimPlayer; +import ac.grim.grimac.utils.anticheat.update.BlockBreak; +import ac.grim.grimac.utils.math.GrimMath; +import ac.grim.grimac.utils.nmsutil.BlockBreakSpeed; +import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.protocol.packettype.PacketType; +import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.player.DiggingAction; +import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState; +import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; +import com.github.retrooper.packetevents.util.Vector3i; +import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; + +// Based loosely off of Hawk BlockBreakSpeedSurvival +// Also based loosely off of NoCheatPlus FastBreak +// Also based off minecraft wiki: https://minecraft.wiki/w/Breaking#Instant_breaking +@CheckData(name = "FastBreakA") +public class FastBreakA extends Check implements BlockBreakCheck { + public FastBreakA(GrimPlayer playerData) { + super(playerData); + } + + // The block the player is currently breaking + Vector3i targetBlock = null; + // The maximum amount of damage the player deals to the block + // + double maximumBlockDamage = 0; + // The last time a finish digging packet was sent, to enforce 0.3-second delay after non-instabreak + long lastFinishBreak = 0; + // The time the player started to break the block, to know how long the player waited until they finished breaking the block + long startBreak = 0; + + // The buffer to this check + double blockBreakBalance = 0; + double blockDelayBalance = 0; + + @Override + public void onBlockBreak(BlockBreak blockBreak) { + if (isDisabled()) return; + + if (blockBreak.action == DiggingAction.START_DIGGING) { + WrappedBlockState block = player.compensatedWorld.getWrappedBlockStateAt(blockBreak.position); + + // Exempt all blocks that do not exist in the player version + if (WrappedBlockState.getDefaultState(player.getClientVersion(), block.getType()).getType() == StateTypes.AIR) { + return; + } + + startBreak = System.currentTimeMillis() - (targetBlock == null ? 50 : 0); // ??? + targetBlock = blockBreak.position; + + maximumBlockDamage = BlockBreakSpeed.getBlockDamage(player, targetBlock); + + double breakDelay = System.currentTimeMillis() - lastFinishBreak; + + if (breakDelay >= 275) { // Reduce buffer if "close enough" + blockDelayBalance *= 0.9; + } else { // Otherwise, increase buffer + blockDelayBalance += 300 - breakDelay; + } + + if (blockDelayBalance > 1000) { // If more than a second of advantage + if (flagAndAlert("Delay=" + breakDelay) && shouldModifyPackets()) { + blockBreak.cancel(); + } + } + + clampBalance(); + } + + if (blockBreak.action == DiggingAction.FINISHED_DIGGING && targetBlock != null) { + double predictedTime = Math.ceil(1 / maximumBlockDamage) * 50; + double realTime = System.currentTimeMillis() - startBreak; + double diff = predictedTime - realTime; + + clampBalance(); + + if (diff < 25) { // Reduce buffer if "close enough" + blockBreakBalance *= 0.9; + } else { // Otherwise, increase buffer + blockBreakBalance += diff; + } + + if (blockBreakBalance > 1000) { // If more than a second of advantage + if (flagAndAlert("Diff=" + diff + ",Balance=" + blockBreakBalance) && shouldModifyPackets()) { + blockBreak.cancel(); + } + } + + lastFinishBreak = System.currentTimeMillis(); + } + } + + @Override + public void onPacketReceive(PacketReceiveEvent event) { + // Find the most optimal block damage using the animation packet, which is sent at least once a tick when breaking blocks + // On 1.8 clients, via screws with this packet meaning we must fall back to the 1.8 idle flying packet + if (!isDisabled() && targetBlock != null && ( + player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) + ? event.getPacketType() == PacketType.Play.Client.ANIMATION + : WrapperPlayClientPlayerFlying.isFlying(event.getPacketType()) + )) { + maximumBlockDamage = Math.max(maximumBlockDamage, BlockBreakSpeed.getBlockDamage(player, targetBlock)); + } + } + + private void clampBalance() { + double balance = Math.max(1000, (player.getTransactionPing())); + blockBreakBalance = GrimMath.clamp(blockBreakBalance, -balance, balance); // Clamp not Math.max in case other logic changes + blockDelayBalance = GrimMath.clamp(blockDelayBalance, -balance, balance); + } + + private boolean isDisabled() { + return player.getClientVersion().isOlderThan(ClientVersion.V_1_9) && GrimAPI.INSTANCE.getConfigManager().isExperimentalChecks(); + } +} diff --git a/src/main/java/ac/grim/grimac/checks/impl/misc/FastBreakA.java b/src/main/java/ac/grim/grimac/checks/impl/misc/FastBreakA.java deleted file mode 100644 index f3333a47f1..0000000000 --- a/src/main/java/ac/grim/grimac/checks/impl/misc/FastBreakA.java +++ /dev/null @@ -1,159 +0,0 @@ -package ac.grim.grimac.checks.impl.misc; - -import ac.grim.grimac.GrimAPI; -import ac.grim.grimac.checks.Check; -import ac.grim.grimac.checks.CheckData; -import ac.grim.grimac.checks.type.PacketCheck; -import ac.grim.grimac.player.GrimPlayer; -import ac.grim.grimac.utils.math.GrimMath; -import ac.grim.grimac.utils.nmsutil.BlockBreakSpeed; -import com.github.retrooper.packetevents.PacketEvents; -import com.github.retrooper.packetevents.event.PacketReceiveEvent; -import com.github.retrooper.packetevents.manager.server.ServerVersion; -import com.github.retrooper.packetevents.protocol.packettype.PacketType; -import com.github.retrooper.packetevents.protocol.player.ClientVersion; -import com.github.retrooper.packetevents.protocol.player.DiggingAction; -import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState; -import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; -import com.github.retrooper.packetevents.util.Vector3i; -import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerDigging; -import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; -import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerAcknowledgeBlockChanges; -import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerBlockChange; -import io.github.retrooper.packetevents.util.folia.FoliaScheduler; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.entity.Player; - -// Based loosely off of Hawk BlockBreakSpeedSurvival -// Also based loosely off of NoCheatPlus FastBreak -// Also based off minecraft wiki: https://minecraft.wiki/w/Breaking#Instant_breaking -@CheckData(name = "FastBreakA") -public class FastBreakA extends Check implements PacketCheck { - public FastBreakA(GrimPlayer playerData) { - super(playerData); - } - - // The block the player is currently breaking - Vector3i targetBlock = null; - // The maximum amount of damage the player deals to the block - // - double maximumBlockDamage = 0; - // The last time a finish digging packet was sent, to enforce 0.3-second delay after non-instabreak - long lastFinishBreak = 0; - // The time the player started to break the block, to know how long the player waited until they finished breaking the block - long startBreak = 0; - - // The buffer to this check - double blockBreakBalance = 0; - double blockDelayBalance = 0; - - @Override - public void onPacketReceive(PacketReceiveEvent event) { - if (player.getClientVersion().isOlderThan(ClientVersion.V_1_9) && GrimAPI.INSTANCE.getConfigManager().isExperimentalChecks()) { - return; - } - - // Find the most optimal block damage using the animation packet, which is sent at least once a tick when breaking blocks - // On 1.8 clients, via screws with this packet meaning we must fall back to the 1.8 idle flying packet - if ((player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? event.getPacketType() == PacketType.Play.Client.ANIMATION : WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) && targetBlock != null) { - maximumBlockDamage = Math.max(maximumBlockDamage, BlockBreakSpeed.getBlockDamage(player, targetBlock)); - } - - if (event.getPacketType() == PacketType.Play.Client.PLAYER_DIGGING) { - WrapperPlayClientPlayerDigging digging = new WrapperPlayClientPlayerDigging(event); - final Vector3i blockPosition = digging.getBlockPosition(); - - if (digging.getAction() == DiggingAction.START_DIGGING) { - WrappedBlockState block = player.compensatedWorld.getWrappedBlockStateAt(blockPosition); - - // Exempt all blocks that do not exist in the player version - if (WrappedBlockState.getDefaultState(player.getClientVersion(), block.getType()).getType() == StateTypes.AIR) { - return; - } - - startBreak = System.currentTimeMillis() - (targetBlock == null ? 50 : 0); // ??? - targetBlock = blockPosition; - - maximumBlockDamage = BlockBreakSpeed.getBlockDamage(player, targetBlock); - - double breakDelay = System.currentTimeMillis() - lastFinishBreak; - - if (breakDelay >= 275) { // Reduce buffer if "close enough" - blockDelayBalance *= 0.9; - } else { // Otherwise, increase buffer - blockDelayBalance += 300 - breakDelay; - } - - if (blockDelayBalance > 1000) { // If more than a second of advantage - flagAndAlert("Delay=" + breakDelay); - if (shouldModifyPackets()) { - event.setCancelled(true); // Cancelling start digging will cause server to reject block break - player.onPacketCancel(); - } - } - - clampBalance(); - } - - if (digging.getAction() == DiggingAction.FINISHED_DIGGING && targetBlock != null) { - double predictedTime = Math.ceil(1 / maximumBlockDamage) * 50; - double realTime = System.currentTimeMillis() - startBreak; - double diff = predictedTime - realTime; - - clampBalance(); - - if (diff < 25) { // Reduce buffer if "close enough" - blockBreakBalance *= 0.9; - } else { // Otherwise, increase buffer - blockBreakBalance += diff; - } - - if (blockBreakBalance > 1000) { // If more than a second of advantage - FoliaScheduler.getEntityScheduler().execute(player.bukkitPlayer, GrimAPI.INSTANCE.getPlugin(), () -> { - Player bukkitPlayer = player.bukkitPlayer; - if (bukkitPlayer == null || !bukkitPlayer.isOnline()) return; - - if (bukkitPlayer.getLocation().distance(new Location(bukkitPlayer.getWorld(), blockPosition.getX(), blockPosition.getY(), blockPosition.getZ())) < 64) { - final int chunkX = blockPosition.getX() >> 4; - final int chunkZ = blockPosition.getZ() >> 4; - if (!bukkitPlayer.getWorld().isChunkLoaded(chunkX, chunkZ)) return; // Don't load chunks sync - - Chunk chunk = bukkitPlayer.getWorld().getChunkAt(chunkX, chunkZ); - Block block = chunk.getBlock(blockPosition.getX() & 15, blockPosition.getY(), blockPosition.getZ() & 15); - - int blockId; - - if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_13)) { - // Cache this because strings are expensive - blockId = WrappedBlockState.getByString(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), block.getBlockData().getAsString(false)).getGlobalId(); - } else { - blockId = (block.getType().getId() << 4) | block.getData(); - } - - player.user.sendPacket(new WrapperPlayServerBlockChange(blockPosition, blockId)); - - if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_19)) { // Via will handle this for us pre-1.19 - player.user.sendPacket(new WrapperPlayServerAcknowledgeBlockChanges(digging.getSequence())); // Make 1.19 clients apply the changes - } - } - }, null, 0); - - if (flagAndAlert("Diff=" + diff + ",Balance=" + blockBreakBalance) && shouldModifyPackets()) { - event.setCancelled(true); - player.onPacketCancel(); - } - } - - lastFinishBreak = System.currentTimeMillis(); - } - } - } - - private void clampBalance() { - double balance = Math.max(1000, (player.getTransactionPing())); - blockBreakBalance = GrimMath.clamp(blockBreakBalance, -balance, balance); // Clamp not Math.max in case other logic changes - blockDelayBalance = GrimMath.clamp(blockDelayBalance, -balance, balance); - } -} diff --git a/src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java b/src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java index e89d00058c..43fe17f1e3 100644 --- a/src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java +++ b/src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java @@ -507,7 +507,7 @@ public void onPacketReceive(PacketReceiveEvent event) { player.onPacketCancel(); } - resyncPosition(player, position); + resyncPosition(player, position, dig.getSequence()); } else { player.queuedBreaks.add(blockBreak); diff --git a/src/main/java/ac/grim/grimac/events/packets/patch/ResyncWorldUtil.java b/src/main/java/ac/grim/grimac/events/packets/patch/ResyncWorldUtil.java index 40cc77f5c0..8c9d4fa7f7 100644 --- a/src/main/java/ac/grim/grimac/events/packets/patch/ResyncWorldUtil.java +++ b/src/main/java/ac/grim/grimac/events/packets/patch/ResyncWorldUtil.java @@ -9,9 +9,12 @@ import com.github.retrooper.packetevents.netty.channel.ChannelHelper; import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState; import com.github.retrooper.packetevents.util.Vector3i; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerAcknowledgeBlockChanges; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerBlockChange; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerMultiBlockChange; import io.github.retrooper.packetevents.util.folia.FoliaScheduler; import org.bukkit.Chunk; +import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; @@ -113,4 +116,34 @@ public static void resyncPositions(GrimPlayer player, int minBlockX, int mY, int } }, null, 0); } + + public static void resyncPosition(GrimPlayer player, Vector3i pos, int sequence) { + if (player.bukkitPlayer == null) return; + + FoliaScheduler.getEntityScheduler().execute(player.bukkitPlayer, GrimAPI.INSTANCE.getPlugin(), () -> { + if (!player.bukkitPlayer.isOnline() || !player.getSetbackTeleportUtil().hasAcceptedSpawnTeleport) return; + + final int chunkX = pos.x >> 4; + final int chunkZ = pos.z >> 4; + + if (!player.compensatedWorld.isChunkLoaded(chunkX, chunkZ)) return; + if (player.bukkitPlayer.getLocation().distance(new Location(player.bukkitPlayer.getWorld(), pos.x, pos.y, pos.z)) >= 64) return; + if (!player.bukkitPlayer.getWorld().isChunkLoaded(chunkX, chunkZ)) return; // Don't load chunks sync + + final Block block = player.bukkitPlayer.getWorld().getChunkAt(chunkX, chunkZ).getBlock(pos.x & 15, pos.y, pos.z & 15); + + final int blockId; + if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_13)) { + // Cache this because strings are expensive + blockId = blockDataToId.computeIfAbsent(block.getBlockData(), data -> WrappedBlockState.getByString(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), data.getAsString(false)).getGlobalId()); + } else { + blockId = (block.getType().getId() << 4) | block.getData(); + } + + player.user.sendPacket(new WrapperPlayServerBlockChange(pos, blockId)); + if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_19)) { // Via will handle this for us pre-1.19 + player.user.sendPacket(new WrapperPlayServerAcknowledgeBlockChanges(sequence)); // Make 1.19 clients apply the changes + } + }, null, 0); + } } diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index 0a80c37981..2c81a9e2bd 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -13,7 +13,7 @@ import ac.grim.grimac.checks.impl.exploit.ExploitB; import ac.grim.grimac.checks.impl.groundspoof.NoFallA; import ac.grim.grimac.checks.impl.misc.ClientBrand; -import ac.grim.grimac.checks.impl.misc.FastBreakA; +import ac.grim.grimac.checks.impl.breaking.FastBreakA; import ac.grim.grimac.checks.impl.misc.GhostBlockMitigation; import ac.grim.grimac.checks.impl.misc.TransactionOrder; import ac.grim.grimac.checks.impl.movement.*; @@ -93,7 +93,6 @@ public CheckManager(GrimPlayer player) { .put(BadPacketsV.class, new BadPacketsV(player)) .put(BadPacketsW.class, new BadPacketsW(player)) .put(BadPacketsY.class, new BadPacketsY(player)) - .put(FastBreakA.class, new FastBreakA(player)) .put(TransactionOrder.class, new TransactionOrder(player)) .put(NoSlowB.class, new NoSlowB(player)) .put(SetbackBlocker.class, new SetbackBlocker(player)) // Must be last class otherwise we can't check while blocking packets @@ -158,6 +157,7 @@ public CheckManager(GrimPlayer player) { .put(NoSwingBreak.class, new NoSwingBreak(player)) .put(NoBreakDelay.class, new NoBreakDelay(player)) .put(NoBreakDelayMitigation.class, new NoBreakDelayMitigation(player)) + .put(FastBreakA.class, new FastBreakA(player)) .put(FastBreakB.class, new FastBreakB(player)) .build();