Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add Breaking Checks #1639

Draft
wants to merge 29 commits into
base: 2.0
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f532baa
Add PositionBreak and rename BadPacketsZ to WrongBlock
ManInMyVan Aug 9, 2024
33d3c50
add PositionBreakB for cancelled digging packets
ManInMyVan Aug 13, 2024
38179ee
fix import order
ManInMyVan Aug 13, 2024
43c0207
rename BadPacketsX to LiquidAirBreak
ManInMyVan Aug 13, 2024
fb58ad7
Add breaking checks to punishments.yml
ManInMyVan Aug 13, 2024
3658ff4
Fix PositionBreakA check name
ManInMyVan Aug 14, 2024
5083c95
rewrite fastbreak
ManInMyVan Sep 1, 2024
b61d1cb
make BlockBreakCheck an interface
ManInMyVan Sep 3, 2024
0136f16
add FarBreak
ManInMyVan Sep 3, 2024
8b47da5
WrongBlock -> WrongBreak
ManInMyVan Sep 4, 2024
a89d830
don't require implementing onBlockBreak
ManInMyVan Sep 4, 2024
86ad878
fix some falses in vehicles
ManInMyVan Sep 4, 2024
e9232af
fix some more falses
ManInMyVan Sep 4, 2024
4ac3d57
Add RotationBreak
ManInMyVan Sep 5, 2024
df22faa
Add NoSwingBreak
ManInMyVan Sep 13, 2024
3cf1366
do not check noswing in fastbreak
ManInMyVan Sep 13, 2024
5daca09
Add MultiBreak
ManInMyVan Sep 19, 2024
2093341
LiquidAirBreak -> AirLiquidBreak
ManInMyVan Sep 19, 2024
e0c331d
experimental
ManInMyVan Sep 20, 2024
cde52a1
I'll do this for now
ManInMyVan Sep 20, 2024
6f7520c
performance
ManInMyVan Sep 21, 2024
37d28c3
you can't break blocks while using items
ManInMyVan Sep 21, 2024
c5e7a7d
except on 1.7
ManInMyVan Sep 21, 2024
215e4c5
fix false
ManInMyVan Sep 21, 2024
f774e0d
oops
ManInMyVan Oct 14, 2024
f310a6e
I don't like cancels
ManInMyVan Oct 14, 2024
b6df7a3
fix MultiBreak false
ManInMyVan Oct 14, 2024
f6e6500
NoBreakDelay
ManInMyVan Oct 26, 2024
262126d
make FastBreakA a BlockBreakCheck
ManInMyVan Oct 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

105 changes: 0 additions & 105 deletions src/main/java/ac/grim/grimac/checks/impl/badpackets/BadPacketsZ.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
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.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 = "AirLiquidBreak", experimental = true)
public class AirLiquidBreak extends Check implements BlockBreakCheck {
public AirLiquidBreak(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();
}
}
}
44 changes: 44 additions & 0 deletions src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
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", experimental = true)
public class FarBreak extends Check implements BlockBreakCheck {
public FarBreak(GrimPlayer player) {
super(player);
}

@Override
public void onBlockBreak(BlockBreak blockBreak) {
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(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 (flagAndAlert("distance=" + Math.sqrt(min)) && shouldModifyPackets()) {
blockBreak.cancel();
}
}
}
}
122 changes: 122 additions & 0 deletions src/main/java/ac/grim/grimac/checks/impl/breaking/FastBreakA.java
Original file line number Diff line number Diff line change
@@ -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();
}
}
Loading