hopefuly fix errors with mitigate-desync-noslow

This commit is contained in:
ManInMyVan committed 2025-02-04 17:29:08 -07:00
1 parent e329171b11
commit 68a04d05f8
5 files changed
+107 -122

No files matched your search

@@ -9,6 +9,8 @@ import ac.grim.grimac.utils.data.TrackerData;
import ac.grim.grimac.utils.data.packetentity.PacketEntity;
import ac.grim.grimac.utils.data.packetentity.PacketEntityHook;
import ac.grim.grimac.utils.data.packetentity.PacketEntityTrackXRot;
import ac.grim.grimac.utils.math.GrimMath;
import ac.grim.grimac.utils.nmsutil.BukkitNMS;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.event.PacketSendEvent;
@@ -254,21 +256,19 @@ public class PacketEntityReplication extends Check implements PacketCheck {
WrapperPlayServerSetSlot slot = new WrapperPlayServerSetSlot(event);
if (slot.getWindowId() == 0) {
if (player.isMitigateDesyncNoSlow() && GrimMath.inRange(slot.getSlot(), 36, 44)) {
BukkitNMS.resetBukkitItemUsage(player.bukkitPlayer);
}
player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get(), () -> {
if (slot.getSlot() - 36 == player.packetStateData.lastSlotSelected) {
player.packetStateData.setSlowedByUsingItem(false);
if (player.isMitigateDesyncNoSlow()) {
player.resetBukkitItemUsage();
}
}
});
player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get() + 1, () -> {
if (slot.getSlot() - 36 == player.packetStateData.lastSlotSelected) {
player.packetStateData.setSlowedByUsingItem(false);
if (player.isMitigateDesyncNoSlow()) {
player.resetBukkitItemUsage();
}
}
});
}
@@ -4,6 +4,7 @@ import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.checks.impl.badpackets.BadPacketsW;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.data.packetentity.PacketEntity;
import ac.grim.grimac.utils.nmsutil.BukkitNMS;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.PacketListenerAbstract;
import com.github.retrooper.packetevents.event.PacketListenerPriority;
@@ -43,7 +44,7 @@ public class PacketPlayerAttack extends PacketListenerAbstract {
if (interact.getAction() == WrapperPlayClientInteractEntity.InteractAction.ATTACK) {
if (player.isMitigateAutoblock()) {
player.resetBukkitItemUsage();
BukkitNMS.resetBukkitItemUsage(player.bukkitPlayer);
}
ItemStack heldItem = player.getInventory().getHeldItem();
@@ -66,31 +66,23 @@ import net.kyori.adventure.text.Component;
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.Contract;
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 {
private static final @Nullable Consumer<@NotNull Player> resetActiveBukkitItem;
private static final @Nullable Predicate<@NotNull Player> isUsingBukkitItem;
public UUID uuid;
public final User user;
public int entityID;
@@ -861,113 +853,6 @@ public class GrimPlayer implements GrimUser {
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 {
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;
try { // paper only
LivingEntity.class.getMethod("clearActiveItem");
resetActiveBukkitItem0 = LivingEntity::clearActiveItem;
} catch (NoSuchMethodException ignored) {}
}
} 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?)");
}
}
}
private final FeatureManagerImpl featureManager = new FeatureManagerImpl(this);
@Override
@@ -109,6 +109,10 @@ public class GrimMath {
return value >= min && value <= max;
}
public static boolean inRange(int value, int min, int max) {
return value >= min && value <= max;
}
public static boolean isNearlySame(double a, double b, double epoch) {
return Math.abs(a-b) < epoch;
}
@@ -0,0 +1,95 @@
package ac.grim.grimac.utils.nmsutil;
import com.github.retrooper.packetevents.PacketEvents;
import lombok.experimental.UtilityClass;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.function.Predicate;
@UtilityClass
public class BukkitNMS {
// resets item usage, then returns whether the player was using an item
private final @NotNull Predicate<@NotNull Player> resetActiveBukkitItem;
public void resetBukkitItemUsage(@Nullable Player player) {
if (player != null && resetActiveBukkitItem.test(player)) {
// only update if they were using an item to prevent certain issues
player.updateInventory();
}
}
static {
try {
switch (PacketEvents.getAPI().getServerManager().getVersion()) {
case 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");
resetActiveBukkitItem = player -> {
try {
Object handle = getHandle.invoke(player);
clearActiveItem.invoke(handle);
return (boolean) isUsingItem.invoke(handle);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
};
}
case 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");
resetActiveBukkitItem = player -> {
try {
Object handle = getHandle.invoke(player);
clearActiveItem.invoke(handle);
Object item = getItemInUse.invoke(handle);
return item != null && !((boolean) isEmpty.invoke(item));
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
};
}
case 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");
resetActiveBukkitItem = player -> {
try {
Object handle = getHandle.invoke(player);
clearActiveItem.invoke(handle);
Object item = getItemInUse.invoke(handle);
return item != null && !((boolean) isEmpty.invoke(item));
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
};
}
default -> {
// cause an exception if these methods don't exist
Player.class.getMethod("clearActiveItem");
Player.class.getMethod("getItemInUse");
resetActiveBukkitItem = player -> {
player.clearActiveItem();
return player.getItemInUse() != null;
};
}
}
} catch (ClassNotFoundException | NoSuchMethodException e) {
throw new RuntimeException("you are likely using an unsupported server software and or version!", e);
}
}
}