forked from GrimAnticheat/Grim
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# Conflicts: # src/main/java/ac/grim/grimac/commands/GrimDump.java # src/main/java/ac/grim/grimac/commands/GrimLog.java # src/main/java/ac/grim/grimac/commands/GrimVersion.java # src/main/java/ac/grim/grimac/manager/init/start/PlaceholderAPIExpansion.java # src/main/java/ac/grim/grimac/utils/nmsutil/BlockRayTrace.java
- Loading branch information
Showing
113 changed files
with
1,175 additions
and
721 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
src/main/java/ac/grim/grimac/checks/impl/badpackets/BadPacketsV.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
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 com.github.retrooper.packetevents.event.PacketReceiveEvent; | ||
import com.github.retrooper.packetevents.protocol.packettype.PacketType; | ||
import com.github.retrooper.packetevents.util.Vector3d; | ||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; | ||
|
||
@CheckData(name = "BadPacketsV", description = "Did not move far enough", experimental = true) | ||
public class BadPacketsV extends Check implements PacketCheck { | ||
public BadPacketsV(GrimPlayer player) { | ||
super(player); | ||
} | ||
|
||
private int noReminderTicks; | ||
|
||
@Override | ||
public void onPacketReceive(PacketReceiveEvent event) { | ||
if (!player.canSkipTicks() && isTickPacket(event.getPacketType())) { | ||
if (event.getPacketType() == PacketType.Play.Client.PLAYER_POSITION || event.getPacketType() == PacketType.Play.Client.PLAYER_POSITION_AND_ROTATION) { | ||
if (noReminderTicks < 20 && !player.uncertaintyHandler.lastTeleportTicks.hasOccurredSince(1)) { | ||
final double deltaSq = new WrapperPlayClientPlayerFlying(event).getLocation().getPosition() | ||
.distanceSquared(new Vector3d(player.lastX, player.lastY, player.lastZ)); | ||
if (deltaSq <= player.getMovementThreshold() * player.getMovementThreshold()) { | ||
flagAndAlert("delta=" + Math.sqrt(deltaSq)); | ||
} | ||
} | ||
|
||
noReminderTicks = 0; | ||
} else { | ||
noReminderTicks++; | ||
} | ||
} | ||
} | ||
} |
128 changes: 58 additions & 70 deletions
128
src/main/java/ac/grim/grimac/checks/impl/badpackets/BadPacketsX.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,93 +1,81 @@ | ||
package ac.grim.grimac.checks.impl.badpackets; | ||
|
||
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.checks.type.PostPredictionCheck; | ||
import ac.grim.grimac.player.GrimPlayer; | ||
import ac.grim.grimac.utils.anticheat.update.BlockBreak; | ||
import ac.grim.grimac.utils.change.BlockModification; | ||
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.util.Vector3i; | ||
import ac.grim.grimac.utils.anticheat.update.PredictionComplete; | ||
import com.github.retrooper.packetevents.event.PacketReceiveEvent; | ||
import com.github.retrooper.packetevents.protocol.packettype.PacketType; | ||
import com.github.retrooper.packetevents.protocol.player.GameMode; | ||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEntityAction; | ||
|
||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
|
||
@CheckData(name = "BadPacketsX") | ||
public class BadPacketsX extends Check implements BlockBreakCheck { | ||
@CheckData(name = "BadPacketsX", experimental = true) | ||
public class BadPacketsX extends Check implements PostPredictionCheck { | ||
public BadPacketsX(GrimPlayer player) { | ||
super(player); | ||
} | ||
|
||
private int lastTick; | ||
private boolean didLastFlag; | ||
private Vector3i lastBreakLoc; | ||
private StateType lastBlockType; | ||
|
||
public final boolean noFireHitbox = player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_15_2); | ||
private boolean sprint; | ||
private boolean sneak; | ||
private int flags; | ||
|
||
@Override | ||
public void onBlockBreak(BlockBreak blockBreak) { | ||
if (blockBreak.action != DiggingAction.START_DIGGING && blockBreak.action != DiggingAction.FINISHED_DIGGING) | ||
public void onPredictionComplete(final PredictionComplete predictionComplete) { | ||
if (!player.canSkipTicks()) { | ||
if (flags > 0) { | ||
setbackIfAboveSetbackVL(); | ||
} | ||
|
||
flags = 0; | ||
return; | ||
} | ||
|
||
final StateType block = blockBreak.block.getType(); | ||
if (player.isTickingReliablyFor(3)) { | ||
for (; flags > 0; flags--) { | ||
if (flagAndAlert()) { | ||
setbackIfAboveSetbackVL(); | ||
} | ||
} | ||
} | ||
|
||
// Fixes false from breaking kelp underwater | ||
// The client sends two start digging packets to the server both in the same tick. BadPacketsX gets called twice, doesn't false the first time, but falses the second | ||
// One ends up breaking the kelp, the other ends up doing nothing besides falsing this check because we think they're trying to mine water | ||
// I am explicitly making this patch as narrow and specific as possible to potentially discover other blocks that exhibit similar behaviour | ||
int newTick = GrimAPI.INSTANCE.getTickManager().currentTick; | ||
if (lastTick == newTick | ||
&& lastBreakLoc.equals(blockBreak.position) | ||
&& !didLastFlag | ||
&& lastBlockType.getHardness() == 0.0F | ||
&& lastBlockType.getBlastResistance() == 0.0F | ||
&& block == StateTypes.WATER | ||
) return; | ||
flags = 0; | ||
} | ||
|
||
// prevents rare false on rapidly breaking short grass | ||
List<StateType> previousBlockStates = player.blockHistory.modificationQueue.stream() | ||
.filter((blockModification) -> blockModification.getLocation().equals(blockBreak.position) | ||
&& newTick - blockModification.getTick() < 2 | ||
&& (blockModification.getCause() == BlockModification.Cause.START_DIGGING || blockModification.getCause() == BlockModification.Cause.HANDLE_NETTY_SYNC_TRANSACTION)) | ||
.flatMap(mod -> Stream.of(mod.getOldBlockContents().getType())) | ||
.collect(Collectors.toList()); | ||
@Override | ||
public void onPacketReceive(PacketReceiveEvent event) { | ||
if (player.gamemode == GameMode.SPECTATOR || isTickPacket(event.getPacketType())) { | ||
sprint = sneak = false; | ||
return; | ||
} | ||
|
||
previousBlockStates.add(0, block); | ||
if (event.getPacketType() == PacketType.Play.Client.ENTITY_ACTION) { | ||
WrapperPlayClientEntityAction wrapper = new WrapperPlayClientEntityAction(event); | ||
switch (wrapper.getAction()) { | ||
case START_SNEAKING: | ||
case STOP_SNEAKING: | ||
if (sneak) { | ||
if (player.canSkipTicks() || flagAndAlert()) { | ||
flags++; | ||
} | ||
} | ||
sneak = true; | ||
break; | ||
|
||
boolean invalid = false; | ||
for (StateType possibleBlockState : previousBlockStates) { | ||
// the block does not have a hitbox | ||
invalid = (possibleBlockState == StateTypes.LIGHT && !(player.getInventory().getHeldItem().is(ItemTypes.LIGHT) || player.getInventory().getOffHand().is(ItemTypes.LIGHT))) | ||
|| possibleBlockState.isAir() | ||
|| possibleBlockState == StateTypes.WATER | ||
|| possibleBlockState == StateTypes.LAVA | ||
|| possibleBlockState == StateTypes.BUBBLE_COLUMN | ||
|| possibleBlockState == StateTypes.MOVING_PISTON | ||
|| possibleBlockState == StateTypes.FIRE && noFireHitbox | ||
// or the client claims to have broken an unbreakable block | ||
|| possibleBlockState.getHardness() == -1.0f && blockBreak.action == DiggingAction.FINISHED_DIGGING; | ||
if (!invalid) { | ||
break; | ||
} | ||
} | ||
case START_SPRINTING: | ||
case STOP_SPRINTING: | ||
if (sprint) { | ||
if (player.canSkipTicks() || flagAndAlert()) { | ||
flags++; | ||
} | ||
} | ||
sprint = true; | ||
break; | ||
|
||
if (invalid && flagAndAlert("block=" + block.getName() + ", type=" + blockBreak.action)) { | ||
didLastFlag = true; | ||
if (shouldModifyPackets()) { | ||
blockBreak.cancel(); | ||
default: | ||
// Handle other cases if necessary | ||
break; | ||
} | ||
} else { | ||
didLastFlag = false; | ||
} | ||
lastTick = newTick; | ||
lastBreakLoc = blockBreak.position; | ||
lastBlockType = block; | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
src/main/java/ac/grim/grimac/checks/impl/breaking/AirLiquidBreak.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
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 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.util.Vector3i; | ||
|
||
@CheckData(name = "AirLiquidBreak", description = "Breaking a block that cannot be broken") | ||
public class AirLiquidBreak extends Check implements BlockBreakCheck { | ||
public AirLiquidBreak(GrimPlayer player) { | ||
super(player); | ||
} | ||
|
||
private int lastTick; | ||
private boolean didLastFlag; | ||
private Vector3i lastBreakLoc; | ||
private StateType lastBlockType; | ||
|
||
public final boolean noFireHitbox = player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_15_2); | ||
|
||
@Override | ||
public void onBlockBreak(BlockBreak blockBreak) { | ||
if (blockBreak.action != DiggingAction.START_DIGGING && blockBreak.action != DiggingAction.FINISHED_DIGGING) | ||
return; | ||
|
||
final StateType block = blockBreak.block.getType(); | ||
|
||
// Fixes false from breaking kelp underwater | ||
// The client sends two start digging packets to the server both in the same tick. AirLiquidBreak gets called twice, doesn't false the first time, but falses the second | ||
// One ends up breaking the kelp, the other ends up doing nothing besides falsing this check because we think they're trying to mine water | ||
// I am explicitly making this patch as narrow and specific as possible to potentially discover other blocks that exhibit similar behaviour | ||
int newTick = GrimAPI.INSTANCE.getTickManager().currentTick; | ||
if (lastTick == newTick | ||
&& lastBreakLoc.equals(blockBreak.position) | ||
&& !didLastFlag | ||
&& lastBlockType.getHardness() == 0.0F | ||
&& lastBlockType.getBlastResistance() == 0.0F | ||
&& block == StateTypes.WATER | ||
) return; | ||
lastTick = newTick; | ||
lastBreakLoc = blockBreak.position; | ||
lastBlockType = block; | ||
|
||
// 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 && blockBreak.action == DiggingAction.FINISHED_DIGGING; | ||
|
||
if (invalid && flagAndAlert("block=" + block.getName() + ", type=" + blockBreak.action) && shouldModifyPackets()) { | ||
didLastFlag = true; | ||
blockBreak.cancel(); | ||
} else { | ||
didLastFlag = false; | ||
} | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
src/main/java/ac/grim/grimac/checks/impl/breaking/FarBreak.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 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 com.github.retrooper.packetevents.protocol.player.GameMode; | ||
import org.bukkit.util.Vector; | ||
|
||
@CheckData(name = "FarBreak", description = "Breaking blocks too far away", experimental = true) | ||
public class FarBreak extends Check implements BlockBreakCheck { | ||
public FarBreak(GrimPlayer player) { | ||
super(player); | ||
} | ||
|
||
@Override | ||
public void onBlockBreak(BlockBreak blockBreak) { | ||
if (player.gamemode == GameMode.SPECTATOR || 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.BLOCK_INTERACTION_RANGE); | ||
if (player.packetStateData.didLastMovementIncludePosition || player.canSkipTicks()) { | ||
double threshold = player.getMovementThreshold(); | ||
maxReach += Math.hypot(threshold, threshold); | ||
} | ||
|
||
if (min > maxReach * maxReach && flagAndAlert(String.format("distance=%.2f", Math.sqrt(min))) && shouldModifyPackets()) { | ||
blockBreak.cancel(); | ||
} | ||
} | ||
} |
2 changes: 1 addition & 1 deletion
2
...im/grimac/checks/impl/misc/FastBreak.java → ...rimac/checks/impl/breaking/FastBreak.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
src/main/java/ac/grim/grimac/checks/impl/breaking/InvalidBreak.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
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; | ||
|
||
@CheckData(name = "InvalidBreak", description = "Sent impossible block face id") | ||
public class InvalidBreak extends Check implements BlockBreakCheck { | ||
public InvalidBreak(GrimPlayer player) { | ||
super(player); | ||
} | ||
|
||
@Override | ||
public void onBlockBreak(BlockBreak blockBreak) { | ||
if (blockBreak.faceId < 0 || blockBreak.faceId > 5) { | ||
// ban | ||
if (flagAndAlert("face=" + blockBreak.faceId) && shouldModifyPackets()) { | ||
blockBreak.cancel(); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.