hopefuly fix errors with mitigate-desync-noslow
This commit is contained in:
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user