diff --git a/src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderN.java b/src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderN.java new file mode 100644 index 0000000000..c70cd8fc1b --- /dev/null +++ b/src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderN.java @@ -0,0 +1,69 @@ +package ac.grim.grimac.checks.impl.packetorder; + +import ac.grim.grimac.checks.CheckData; +import ac.grim.grimac.checks.type.BlockPlaceCheck; +import ac.grim.grimac.player.GrimPlayer; +import ac.grim.grimac.utils.anticheat.update.BlockPlace; +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.ClientVersion; +import com.github.retrooper.packetevents.protocol.world.BlockFace; +import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerBlockPlacement; +import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; + +@CheckData(name = "PacketOrderN", experimental = true) +public class PacketOrderN extends BlockPlaceCheck { + public PacketOrderN(final GrimPlayer player) { + super(player); + } + + private int invalid; + private boolean usingWithoutPlacing, placing; + + @Override + public void onBlockPlace(BlockPlace place) { + placing = true; + if (usingWithoutPlacing) { + if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) { + if (flagAndAlert() && shouldModifyPackets() && shouldCancel()) { + place.resync(); + } + } else { + invalid++; + } + } + } + + @Override + public void onPacketReceive(PacketReceiveEvent event) { + if (event.getPacketType() == PacketType.Play.Client.USE_ITEM + || event.getPacketType() == PacketType.Play.Client.PLAYER_BLOCK_PLACEMENT + && new WrapperPlayClientPlayerBlockPlacement(event).getFace() == BlockFace.OTHER) { + if (!placing) { + usingWithoutPlacing = true; + } + + placing = false; + } + + if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType()) && player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8) && !player.packetStateData.lastPacketWasTeleport) { + usingWithoutPlacing = placing = false; + } + } + + @Override + public void onPredictionComplete(PredictionComplete predictionComplete) { + // we don't need to check pre-1.9 players here (no tick skipping) + if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) return; + + if (!player.skippedTickInActualMovement) { + for (; invalid >= 1; invalid--) { + flagAndAlert(); + } + } + + invalid = 0; + usingWithoutPlacing = placing = false; + } +} diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index facfad833f..5856b1a82b 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -163,6 +163,7 @@ public CheckManager(GrimPlayer player) { .put(FabricatedPlace.class, new FabricatedPlace(player)) .put(PositionPlace.class, new PositionPlace(player)) .put(RotationPlace.class, new RotationPlace(player)) + .put(PacketOrderN.class, new PacketOrderN(player)) .put(DuplicateRotPlace.class, new DuplicateRotPlace(player)) .put(GhostBlockMitigation.class, new GhostBlockMitigation(player)) .build();