Skip to content

Commit

Permalink
patch full autoblock and desync noslows
Browse files Browse the repository at this point in the history
  • Loading branch information
ManInMyVan committed Oct 27, 2024
1 parent de0c28b commit 13ad59f
Show file tree
Hide file tree
Showing 18 changed files with 234 additions and 11 deletions.
8 changes: 4 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ java.targetCompatibility = JavaVersion.VERSION_17

// Set to false for debug builds
// You cannot live reload classes if the jar relocates dependencies
var relocate = true;
var relocate = true

repositories {
mavenLocal()
Expand Down Expand Up @@ -50,9 +50,9 @@ dependencies {

implementation("org.jetbrains:annotations:24.1.0")
compileOnly("org.geysermc.floodgate:api:2.0-SNAPSHOT")
compileOnly("org.spigotmc:spigot-api:1.18.2-R0.1-SNAPSHOT")
compileOnly("io.papermc.paper:paper-api:1.18.2-R0.1-SNAPSHOT")

compileOnly("com.viaversion:viaversion-api:4.9.4-SNAPSHOT")
//
compileOnly("io.netty:netty-all:4.1.85.Final")
}

Expand Down Expand Up @@ -157,4 +157,4 @@ tasks.shadowJar {
relocate("org.intellij", "ac.grim.grimac.shaded.intellij")
relocate("org.jetbrains", "ac.grim.grimac.shaded.jetbrains")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ public void onPacketReceive(PacketReceiveEvent event) {
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package ac.grim.grimac.checks.impl.movement;

import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.api.config.ConfigManager;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.type.PostPredictionCheck;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.anticheat.update.PredictionComplete;

public class NoSlowMitigation extends Check implements PostPredictionCheck {
private double offsetToFlag;
private double bestOffset = 1;
private boolean flaggedLastTick;

public NoSlowMitigation(GrimPlayer player) {
super(player);
}

@Override
public void onPredictionComplete(final PredictionComplete predictionComplete) {
if (!predictionComplete.isChecked()) return;

if (wouldFlag()) {
if (flaggedLastTick) {
player.resetBukkitItemUsage();
}
flaggedLastTick = true;
} else flaggedLastTick = false;

bestOffset = 1;
}

public void handlePredictionAnalysis(double offset) {
bestOffset = Math.min(bestOffset, offset);
}

public boolean wouldFlag() {
return GrimAPI.INSTANCE.getConfigManager().isMitigateNoSlow()
&& !player.packetStateData.isSlowedByUsingItem()
&& bestOffset > offsetToFlag
&& player.isUsingBukkitItem();
}

@Override
public void onReload(ConfigManager config) {
offsetToFlag = config.getDoubleElse("mitigate-noslow-threshold", 0.001);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ public void onPacketReceive(PacketReceiveEvent event) {
}

if (interact.getAction() == WrapperPlayClientInteractEntity.InteractAction.ATTACK) {
if (GrimAPI.INSTANCE.getConfigManager().isMitigateAutoBlock()) {
player.resetBukkitItemUsage();
}

ItemStack heldItem = player.getInventory().getHeldItem();
PacketEntity entity = player.compensatedEntities.getEntity(interact.getEntityId());

Expand Down
1 change: 1 addition & 0 deletions src/main/java/ac/grim/grimac/manager/CheckManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ public CheckManager(GrimPlayer player) {
.put(SuperDebug.class, new SuperDebug(player))
.put(DebugHandler.class, new DebugHandler(player))
.put(EntityControl.class, new EntityControl(player))
.put(NoSlowMitigation.class, new NoSlowMitigation(player))
.put(NoSlowA.class, new NoSlowA(player))
.put(NoSlowC.class, new NoSlowC(player))
.put(NoSlowD.class, new NoSlowD(player))
Expand Down
7 changes: 3 additions & 4 deletions src/main/java/ac/grim/grimac/manager/ConfigManagerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,7 @@ public ConfigManager getConfig() {
@Getter
private final File punishFile = new File(GrimAPI.INSTANCE.getPlugin().getDataFolder(), "punishments.yml");
@Getter
private boolean ignoreDuplicatePacketRotation = false;

@Getter
private boolean experimentalChecks = false;
private boolean experimentalChecks, ignoreDuplicatePacketRotation, mitigateAutoBlock, mitigateNoSlow;

private final List<Pattern> ignoredClientPatterns = new ArrayList<>();

Expand Down Expand Up @@ -98,6 +95,8 @@ public void reload() {
}
experimentalChecks = config.getBooleanElse("experimental-checks", false);
ignoreDuplicatePacketRotation = config.getBooleanElse("ignore-duplicate-packet-rotation", false);
mitigateAutoBlock = config.getBooleanElse("mitigate-auto-block", true);
mitigateNoSlow = config.getBooleanElse("mitigate-noslow", true);
}

public boolean isIgnoredClient(String brand) {
Expand Down
117 changes: 117 additions & 0 deletions src/main/java/ac/grim/grimac/player/GrimPlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,31 @@
import net.kyori.adventure.text.TranslatableComponent;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Predicate;

// Everything in this class should be sync'd to the anticheat thread.
// Put variables sync'd to the netty thread in PacketStateData
// Variables that need lag compensation should have their own class
// Soon there will be a generic class for lag compensation
public class GrimPlayer implements GrimUser {
public static final @Nullable Consumer<@NotNull Player> resetActiveBukkitItem;
public static final @Nullable Predicate<@NotNull Player> isUsingBukkitItem;

public UUID playerUUID;
public final User user;
public int entityID;
Expand Down Expand Up @@ -731,4 +740,112 @@ public void reload(ConfigManager config) {
public void reload() {
reload(GrimAPI.INSTANCE.getConfigManager().getConfig());
}

public void resetBukkitItemUsage() {
if (resetActiveBukkitItem != null && this.isUsingBukkitItem()) {
this.bukkitPlayer.updateInventory();
resetActiveBukkitItem.accept(this.bukkitPlayer);
}
}

public boolean isUsingBukkitItem() {
return isUsingBukkitItem != null && this.bukkitPlayer != null && isUsingBukkitItem.test(this.bukkitPlayer);
}

static {
ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
Predicate<Player> isUsingBukkitItem0 = null;
Consumer<Player> resetActiveBukkitItem0 = null;

try {
try { // paper 1.16+
LivingEntity.class.getMethod("clearActiveItem");
resetActiveBukkitItem0 = LivingEntity::clearActiveItem;
} catch (NoSuchMethodException ignored) {}

if (version == ServerVersion.V_1_8_8) {
Class<?> EntityHuman = Class.forName("net.minecraft.server.v1_8_R3.EntityHuman");
Method getHandle = Class.forName("org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer").getMethod("getHandle");
Method clearActiveItem = EntityHuman.getMethod("bV");
Method isUsingItem = EntityHuman.getMethod("bS");

resetActiveBukkitItem0 = player -> {
try {
clearActiveItem.invoke(getHandle.invoke(player));
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
};

isUsingBukkitItem0 = player -> {
try {
return (boolean) isUsingItem.invoke(getHandle.invoke(player));
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
};
} else if (version == ServerVersion.V_1_12_2) {
Class<?> EntityLiving = Class.forName("net.minecraft.server.v1_12_R1.EntityLiving");
Method getHandle = Class.forName("org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer").getMethod("getHandle");
Method clearActiveItem = EntityLiving.getMethod("cN");
Method getItemInUse = EntityLiving.getMethod("cJ");
Method isEmpty = Class.forName("net.minecraft.server.v1_12_R1.ItemStack").getMethod("isEmpty");

resetActiveBukkitItem0 = player -> {
try {
clearActiveItem.invoke(getHandle.invoke(player));
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
};

isUsingBukkitItem0 = player -> {
try {
var item = getItemInUse.invoke(getHandle.invoke(player));
return item != null && !((boolean) isEmpty.invoke(item));
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
};
} else if (version == ServerVersion.V_1_16_5) {
Class<?> EntityLiving = Class.forName("net.minecraft.server.v1_16_R3.EntityLiving");
Method getHandle = Class.forName("org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer").getMethod("getHandle");
Method clearActiveItem = EntityLiving.getMethod("clearActiveItem");
Method getItemInUse = EntityLiving.getMethod("getActiveItem");
Method isEmpty = Class.forName("net.minecraft.server.v1_16_R3.ItemStack").getMethod("isEmpty");

resetActiveBukkitItem0 = player -> {
try {
clearActiveItem.invoke(getHandle.invoke(player));
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
};

isUsingBukkitItem0 = player -> {
try {
Object item = getItemInUse.invoke(getHandle.invoke(player));
return item != null && !((boolean) isEmpty.invoke(item));
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
};
} else if (version.isNewerThanOrEquals(ServerVersion.V_1_17_1)) {
isUsingBukkitItem0 = player -> player.getItemInUse() != null;
}
} catch (ClassNotFoundException | NoSuchMethodException e) {
throw new RuntimeException(e);
} finally {
resetActiveBukkitItem = resetActiveBukkitItem0;
isUsingBukkitItem = isUsingBukkitItem0;

if (resetActiveBukkitItem == null) {
LogUtil.warn("could not find method to reset item usage (are you using spigot?)");
}

if (isUsingBukkitItem == null) {
LogUtil.warn("could not find method to get item usage status (are you using an unsupported version?)");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ac.grim.grimac.predictionengine.predictions;

import ac.grim.grimac.checks.impl.movement.NoSlowMitigation;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.predictionengine.SneakingEstimator;
import ac.grim.grimac.predictionengine.movementtick.MovementTickerPlayer;
Expand Down Expand Up @@ -174,6 +175,10 @@ private void doPredictions(GrimPlayer player, List<VectorData> possibleVelocitie
player.checkManager.getNoSlow().handlePredictionAnalysis(Math.sqrt(player.uncertaintyHandler.reduceOffset(resultAccuracy)));
}

if (!player.packetStateData.isSlowedByUsingItem() && clientVelAfterInput.isFlipItem()) {
player.checkManager.getPostPredictionCheck(NoSlowMitigation.class).handlePredictionAnalysis(Math.sqrt(player.uncertaintyHandler.reduceOffset(resultAccuracy)));
}

if (player.checkManager.getKnockbackHandler().shouldIgnoreForPrediction(clientVelAfterInput) ||
player.checkManager.getExplosionHandler().shouldIgnoreForPrediction(clientVelAfterInput)) {
continue;
Expand All @@ -192,7 +197,7 @@ private void doPredictions(GrimPlayer player, List<VectorData> possibleVelocitie
}

// Close enough, there's no reason to continue our predictions (if either kb or explosion will flag, continue searching)
if (bestInput < 1e-5 * 1e-5 && !player.checkManager.getKnockbackHandler().wouldFlag() && !player.checkManager.getExplosionHandler().wouldFlag()) {
if (bestInput < 1e-5 * 1e-5 && !player.checkManager.getKnockbackHandler().wouldFlag() && !player.checkManager.getExplosionHandler().wouldFlag() && !player.checkManager.getPostPredictionCheck(NoSlowMitigation.class).wouldFlag()) {
break;
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/main/resources/config/de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,11 @@ debug-pipeline-on-join: false
# Aktiviert experimentelle Prüfungen
experimental-checks: false

mitigate-auto-block: true

mitigate-noslow: true
mitigate-noslow-threshold: 0.001

# Grim bricht manchmal illegale Pakete ab, z.B. mit Timer, nachdem X Pakete in einer Sekunde abgebrochen wurden, wann sollte
# wir den Spieler einfach kicken? Dies ist erforderlich, da einige Paketbegrenzer die von Grim abgebrochenen Pakete nicht zählen.
packet-spam-threshold: 100
Expand Down
5 changes: 5 additions & 0 deletions src/main/resources/config/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,11 @@ debug-pipeline-on-join: false
# Enables experimental checks
experimental-checks: false

mitigate-auto-block: true

mitigate-noslow: true
mitigate-noslow-threshold: 0.001

# Grim sometimes cancels illegal packets such as with timer, after X packets in a second cancelled, when should
# we simply kick the player? This is required as some packet limiters don't count packets cancelled by grim.
packet-spam-threshold: 100
Expand Down
5 changes: 5 additions & 0 deletions src/main/resources/config/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,11 @@ debug-pipeline-on-join: false
# Habilitar comprobaciones experimentales
experimental-checks: false

mitigate-auto-block: true

mitigate-noslow: true
mitigate-noslow-threshold: 0.001

# Grim a veces cancela paquetes ilegal como los de Timer. Después de X paquetes en un solo segundo cancelados,
# cuando deberíamos simplemente expulsar al jugador? Esto es obligatorio ya que algunos limitadores de paquetes
# no cuentan los paquetes cancelados por Grim.
Expand Down
5 changes: 5 additions & 0 deletions src/main/resources/config/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ debug-pipeline-on-join: false
# Active les vérifications expérimentales
experimental-checks: false

mitigate-auto-block: true

mitigate-noslow: true
mitigate-noslow-threshold: 0.001

# Grim annule parfois des paquets illégaux, comme ceux liés au chronomètre, après avoir annulé X paquets en une seconde,
# à partir de combien de paquets annulés devrions-nous simplement expulser le joueur ?
# Cela est nécessaire car certains limiteurs de paquets ne comptent pas les paquets annulés par Grim.
Expand Down
5 changes: 5 additions & 0 deletions src/main/resources/config/it.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ debug-pipeline-on-join: false
# Enables experimental checks
experimental-checks: false

mitigate-auto-block: true

mitigate-noslow: true
mitigate-noslow-threshold: 0.001

# Grim sometimes cancels illegal packets such as with timer, after X packets in a second cancelled, when should
# we simply kick the player? This is required as some packet limiters don't count packets cancelled by grim.
packet-spam-threshold: 100
Expand Down
5 changes: 5 additions & 0 deletions src/main/resources/config/nl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,11 @@ debug-pipeline-on-join: false
# Experimentele controles inschakelen
experimental-checks: false

mitigate-auto-block: true

mitigate-noslow: true
mitigate-noslow-threshold: 0.001

# Grim annuleert soms illegale pakketten zoals met timer, na X pakketten in een seconde geannuleerd, wanneer moeten
# we de speler gewoon schoppen? Dit is nodig omdat sommige pakket-begrenzers pakketten die door grim worden geannuleerd niet tellen
packet-spam-threshold: 100
Expand Down
5 changes: 5 additions & 0 deletions src/main/resources/config/pt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ debug-pipeline-on-join: false
# Habilita verificações experimentais.
experimental-checks: false

mitigate-auto-block: true

mitigate-noslow: true
mitigate-noslow-threshold: 0.001

# Grim às vezes cancela pacotes ilegais como com o timer, depois de X pacotes em um segundo que foram cancelados, quando
# deve-se simplesmente expulsar o jogador? Isso é requirido já que alguns limitadores de pacotes não contam pacotes
# cancelados pelo Grim.
Expand Down
6 changes: 5 additions & 1 deletion src/main/resources/config/ru.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ Knockback:
# Это сделано для того, чтобы игрок не собирал слишком много нарушений и никогда не смог очистить их все.
max-ceiling: 4


Explosion:
threshold: 0.001
setbackvl: 3
Expand Down Expand Up @@ -169,6 +168,11 @@ debug-pipeline-on-join: false
# Включает экспериментальные проверки
experimental-checks: false

mitigate-auto-block: true

mitigate-noslow: true
mitigate-noslow-threshold: 0.001

# Грим иногда отменяет незаконные пакеты, например, с таймером, после X пакетов в секунду отмененных, когда следует
# нам просто кикнуть игрока? Это необходимо, так как некоторые ограничители пакетов не учитывают пакеты, отмененные Гримом.
packet-spam-threshold: 100
Expand Down
Loading

0 comments on commit 13ad59f

Please sign in to comment.