diff --git a/src/main/java/ac/grim/grimac/checks/impl/scaffolding/MultiPlace.java b/src/main/java/ac/grim/grimac/checks/impl/scaffolding/MultiPlace.java new file mode 100644 index 0000000000..4e0715bcab --- /dev/null +++ b/src/main/java/ac/grim/grimac/checks/impl/scaffolding/MultiPlace.java @@ -0,0 +1,75 @@ +package ac.grim.grimac.checks.impl.scaffolding; + +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.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.world.BlockFace; +import com.github.retrooper.packetevents.util.Vector3f; +import com.github.retrooper.packetevents.util.Vector3i; +import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; + +import java.util.ArrayList; +import java.util.List; + +import static ac.grim.grimac.utils.anticheat.MessageUtil.toUnlabledString; + +@CheckData(name = "MultiPlace", experimental = true) +public class MultiPlace extends BlockPlaceCheck { + public MultiPlace(GrimPlayer player) { + super(player); + } + + private final List flags = new ArrayList<>(); + + private boolean hasPlaced; + private BlockFace lastFace; + private Vector3f lastCursor; + private Vector3i lastPos; + + @Override + public void onBlockPlace(final BlockPlace place) { + final BlockFace face = place.getDirection(); + final Vector3f cursor = place.getCursor(); + final Vector3i pos = place.getPlacedAgainstBlockLocation(); + + if (hasPlaced && (face != lastFace || !cursor.equals(lastCursor) || !pos.equals(lastPos))) { + final String verbose = "face=" + face + ", lastFace=" + lastFace + + ", cursor=" + toUnlabledString(cursor) + ", lastCursor=" + toUnlabledString(lastCursor) + + ", pos=" + toUnlabledString(pos) + ", lastPos=" + toUnlabledString(lastPos); + if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) { + if (flagAndAlert(verbose) && shouldModifyPackets() && shouldCancel()) { + place.resync(); + } + } else { + flags.add(verbose); + } + } + + lastFace = face; + lastCursor = cursor; + lastPos = pos; + hasPlaced = true; + } + + @Override + public void onPacketReceive(PacketReceiveEvent event) { + if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) { + hasPlaced = false; + } + } + + @Override + public void onPredictionComplete(PredictionComplete predictionComplete) { + if (player.getClientVersion().isNewerThan(ClientVersion.V_1_8) && !player.skippedTickInActualMovement) { + for (String verbose : flags) { + flagAndAlert(verbose); + } + } + + flags.clear(); + } +} diff --git a/src/main/java/ac/grim/grimac/checks/type/BlockPlaceCheck.java b/src/main/java/ac/grim/grimac/checks/type/BlockPlaceCheck.java index 92bcf308c1..9791634419 100644 --- a/src/main/java/ac/grim/grimac/checks/type/BlockPlaceCheck.java +++ b/src/main/java/ac/grim/grimac/checks/type/BlockPlaceCheck.java @@ -14,7 +14,7 @@ import java.util.ArrayList; import java.util.List; -public class BlockPlaceCheck extends Check implements RotationCheck { +public class BlockPlaceCheck extends Check implements RotationCheck, PostPredictionCheck { private static final List weirdBoxes = new ArrayList<>(); private static final List buggyBoxes = new ArrayList<>(); diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index b2a6bea031..c396ca0455 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -139,6 +139,7 @@ public CheckManager(GrimPlayer player) { .put(InvalidPlaceA.class, new InvalidPlaceA(player)) .put(InvalidPlaceB.class, new InvalidPlaceB(player)) .put(AirLiquidPlace.class, new AirLiquidPlace(player)) + .put(MultiPlace.class, new MultiPlace(player)) .put(FarPlace.class, new FarPlace(player)) .put(FabricatedPlace.class, new FabricatedPlace(player)) .put(PositionPlace.class, new PositionPlace(player)) @@ -201,6 +202,9 @@ public void onPacketReceive(final PacketReceiveEvent packet) { for (PostPredictionCheck check : postPredictionCheck.values()) { check.onPacketReceive(packet); } + for (BlockPlaceCheck check : blockPlaceCheck.values()) { + check.onPacketReceive(packet); + } } public void onPacketSend(final PacketSendEvent packet) { @@ -213,6 +217,9 @@ public void onPacketSend(final PacketSendEvent packet) { for (PostPredictionCheck check : postPredictionCheck.values()) { check.onPacketSend(packet); } + for (BlockPlaceCheck check : blockPlaceCheck.values()) { + check.onPacketSend(packet); + } } public void onPositionUpdate(final PositionUpdate position) { @@ -240,6 +247,9 @@ public void onPredictionFinish(final PredictionComplete complete) { for (PostPredictionCheck check : postPredictionCheck.values()) { check.onPredictionComplete(complete); } + for (BlockPlaceCheck check : blockPlaceCheck.values()) { + check.onPredictionComplete(complete); + } } public void onBlockPlace(final BlockPlace place) { diff --git a/src/main/java/ac/grim/grimac/utils/anticheat/MessageUtil.java b/src/main/java/ac/grim/grimac/utils/anticheat/MessageUtil.java index 74b6b2b73f..10914621ad 100644 --- a/src/main/java/ac/grim/grimac/utils/anticheat/MessageUtil.java +++ b/src/main/java/ac/grim/grimac/utils/anticheat/MessageUtil.java @@ -3,6 +3,8 @@ import ac.grim.grimac.GrimAPI; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; +import com.github.retrooper.packetevents.util.Vector3f; +import com.github.retrooper.packetevents.util.Vector3i; import lombok.experimental.UtilityClass; import net.md_5.bungee.api.ChatColor; @@ -11,6 +13,13 @@ @UtilityClass public class MessageUtil { + public String toUnlabledString(Vector3i vec) { + return vec == null ? "null" : vec.x + ", " + vec.y + ", " + vec.z; + } + + public String toUnlabledString(Vector3f vec) { + return vec == null ? "null" : vec.x + ", " + vec.y + ", " + vec.z; + } public String format(String string) { string = formatWithNoColor(string);