From a7a237f0aba04e8ee3865840b0fc6138ddf549da Mon Sep 17 00:00:00 2001 From: Vrekt Date: Tue, 17 Aug 2021 08:52:39 -0500 Subject: [PATCH] #5 #9, Speed liquid fix, WaterWalk check, flight fix. --- src/main/java/me/vrekt/arc/Arc.java | 2 +- .../java/me/vrekt/arc/check/CheckManager.java | 6 +- .../java/me/vrekt/arc/check/CheckType.java | 7 +- .../java/me/vrekt/arc/check/moving/Speed.java | 29 +++- .../me/vrekt/arc/check/moving/WaterWalk.java | 146 ++++++++++++++++++ .../me/vrekt/arc/check/result/CancelType.java | 11 -- .../commands/ArcSummarySubCommand.java | 5 +- .../me/vrekt/arc/data/moving/MovingData.java | 63 ++++++++ .../vrekt/arc/exemption/ExemptionManager.java | 3 +- .../player/MovePlayerPacketListener.java | 21 ++- .../me/vrekt/arc/utility/MovingAccess.java | 4 +- src/main/resources/plugin.yml | 2 + 12 files changed, 271 insertions(+), 28 deletions(-) create mode 100644 src/main/java/me/vrekt/arc/check/moving/WaterWalk.java delete mode 100644 src/main/java/me/vrekt/arc/check/result/CancelType.java diff --git a/src/main/java/me/vrekt/arc/Arc.java b/src/main/java/me/vrekt/arc/Arc.java index 1eb1888..762d9c0 100644 --- a/src/main/java/me/vrekt/arc/Arc.java +++ b/src/main/java/me/vrekt/arc/Arc.java @@ -27,7 +27,7 @@ public final class Arc extends PluginBase { /** * IPL version */ - public static final String VERSION_STRING = "1.6.3-81721a-nukkit"; + public static final String VERSION_STRING = "1.6.3-81721b-nukkit"; /** * The instance of this class diff --git a/src/main/java/me/vrekt/arc/check/CheckManager.java b/src/main/java/me/vrekt/arc/check/CheckManager.java index 4be3eb7..fa2f241 100644 --- a/src/main/java/me/vrekt/arc/check/CheckManager.java +++ b/src/main/java/me/vrekt/arc/check/CheckManager.java @@ -5,10 +5,7 @@ import me.vrekt.arc.check.combat.FastClick; import me.vrekt.arc.check.combat.KillAura; import me.vrekt.arc.check.combat.Reach; -import me.vrekt.arc.check.moving.Flight; -import me.vrekt.arc.check.moving.MorePackets; -import me.vrekt.arc.check.moving.Phase; -import me.vrekt.arc.check.moving.Speed; +import me.vrekt.arc.check.moving.*; import me.vrekt.arc.check.player.FastUse; import me.vrekt.arc.configuration.ArcConfiguration; import me.vrekt.arc.configuration.Configurable; @@ -40,6 +37,7 @@ public void initializeAllChecks() { add(new KillAura()); add(new FastClick()); add(new Phase()); + add(new WaterWalk()); } /** diff --git a/src/main/java/me/vrekt/arc/check/CheckType.java b/src/main/java/me/vrekt/arc/check/CheckType.java index a7efd80..7862450 100644 --- a/src/main/java/me/vrekt/arc/check/CheckType.java +++ b/src/main/java/me/vrekt/arc/check/CheckType.java @@ -54,7 +54,12 @@ public enum CheckType { /** * Checks if the player is clicking too fast. */ - FAST_CLICK("FastClick", CheckCategory.COMBAT); + FAST_CLICK("FastClick", CheckCategory.COMBAT), + + /** + * Checks if the player is walking on water. + */ + WATER_WALK("WaterWalk", CheckCategory.MOVING); /** * The name diff --git a/src/main/java/me/vrekt/arc/check/moving/Speed.java b/src/main/java/me/vrekt/arc/check/moving/Speed.java index a8334b5..09ad44f 100644 --- a/src/main/java/me/vrekt/arc/check/moving/Speed.java +++ b/src/main/java/me/vrekt/arc/check/moving/Speed.java @@ -111,15 +111,20 @@ public void check(Player player, MovingData data) { data.setLastHorizontal(lastHorizontal); // Player is on-ground check normal speeds and stairs and stuff. - if (data.onGround() && data.onGroundTime() >= minimumOnGroundTime) { + if (data.onGround() && data.onGroundTime() >= minimumOnGroundTime && !data.inLiquid()) { runGroundChecks(player, data, result, from, to, setback, horizontal, base, vertical); } // Player is not on ground, mostly fix b-hop type speeds. - if (!data.onGround()) { + if (!data.onGround() && !data.inLiquid()) { runAirChecks(player, data, result, setback, horizontal); } + // Player is in liquid. + if (data.inLiquid()) { + runLiquidChecks(player, data, result, to, setback, horizontal); + } + stopTiming(player); } @@ -138,11 +143,12 @@ public void check(Player player, MovingData data) { private void runAirChecks(Player player, MovingData data, CheckResult result, Location setback, double horizontal) { // check if the player is moving too similar over time final double delta = Math.abs(data.getLastHorizontal() - horizontal); - if (delta <= inAirMinDelta) { + // TODO: Over compensating here, bypass. + if (delta <= inAirMinDelta && delta != 0.0) { // ignore cases where we are super far from ground. // TODO: This can cause bypasses. final double distance = MathUtil.distance(data.ground(), data.to()); - if (distance <= 2.8) { + if (distance <= 2.8 && distance > 1.2) { final int count = data.getInAirDeltaAmount() + 1; data.setInAirDeltaAmount(count); @@ -302,6 +308,21 @@ private void checkLowJumpMovement(Player player, MovingData data, CheckResult re } } + /** + * Check movement in liquids. + * TODO + * + * @param player the player + * @param data their data + * @param result the result + * @param to the to + * @param setback their setback + * @param horizontal the horizontal speed + */ + private void runLiquidChecks(Player player, MovingData data, CheckResult result, Location to, Location setback, double horizontal) { + // TODO: + } + /** * Return our base move speed. * diff --git a/src/main/java/me/vrekt/arc/check/moving/WaterWalk.java b/src/main/java/me/vrekt/arc/check/moving/WaterWalk.java new file mode 100644 index 0000000..77a9886 --- /dev/null +++ b/src/main/java/me/vrekt/arc/check/moving/WaterWalk.java @@ -0,0 +1,146 @@ +package me.vrekt.arc.check.moving; + +import cn.nukkit.Player; +import cn.nukkit.level.Location; +import me.vrekt.arc.check.Check; +import me.vrekt.arc.check.CheckType; +import me.vrekt.arc.check.result.CheckResult; +import me.vrekt.arc.data.moving.MovingData; +import me.vrekt.arc.utility.MovingAccess; +import me.vrekt.arc.utility.math.MathUtil; + +/** + * Checks if the player is walking on water. + */ +public final class WaterWalk extends Check { + + /** + * The time in liquid required to start checking. + * The max amount of times a player cannot be moving vertically in liquid. + * The max amount of small vertical movements allowed. + */ + private int timeInLiquidRequired, maxNoVerticalCount, maxSmallMovementVerticalCount; + + /** + * The min vertical ascend possible. + * The max setback distance. + */ + private double minVerticalAscend, maxSetbackDistance; + + public WaterWalk() { + super(CheckType.WATER_WALK); + enabled(true) + .cancel(true) + .cancelLevel(0) + .notify(true) + .notifyEvery(1) + .ban(false) + .kick(false) + .build(); + + addConfigurationValue("time-in-liquid-required", 3); + addConfigurationValue("max-no-vertical-count", 5); + addConfigurationValue("min-vertical-ascend", 0.1); + addConfigurationValue("max-small-vertical-movement-count", 5); + addConfigurationValue("max-setback-distance", 2); + + if (enabled()) load(); + } + + /** + * Check this player + * + * @param player the player + * @param data their data + */ + public void check(Player player, MovingData data) { + // TODO: Possible bypass with these flags set. + if (exempt(player) || player.isGliding()) return; + + // TODO: Possible bypass with these flags set. + if (player.isSwimming()) { + data.setLastSwimTime(System.currentTimeMillis()); + return; + } else if (System.currentTimeMillis() - data.getLastSwimTime() < 1000) return; + + final Location to = data.to(); + final boolean liquid = data.inLiquid(); + + // reset data if in liquid + if (!liquid) { + data.liquidTime(0); + data.waterLocation(null); + } + + if (liquid && !data.onGround() && data.getInAirTime() >= 5 && player.riding == null && !MovingAccess.isOnBoat(player)) { + final CheckResult result = new CheckResult(); + final double vertical = Math.floor((data.vertical()) * 100) / 100; + final int liquidTime = data.liquidTime() + 1; + data.liquidTime(liquidTime); + + // make sure we have had liquid time for a while + if (liquidTime > timeInLiquidRequired) { + Location water = data.waterLocation(); + + // reset water location for setback + if (water == null) { + water = to; + data.waterLocation(water); + } + + // basic check, if on ground and no vertical, flag. + if (vertical == 0.0) { + final int count = data.getNoVerticalCount() + 1; + data.setNoVerticalCount(count); + + if (count > maxNoVerticalCount) { + result.setFailed("No vertical movement in water.") + .withParameter("vertical", vertical) + .withParameter("count", count) + .withParameter("max", maxNoVerticalCount); + } + } else { + data.setNoVerticalCount(0); + + if (vertical < minVerticalAscend && data.ascending()) { + final int count = data.getLiquidSmallMovementCount() + 1; + data.setLiquidSmallMovementCount(count); + + if (count > maxSmallMovementVerticalCount) { + result.setFailed("Ascending too slowly in water") + .withParameter("v", vertical) + .withParameter("min", minVerticalAscend) + .withParameter("count", count) + .withParameter("max", maxSmallMovementVerticalCount); + } + } else { + data.setLiquidSmallMovementCount(0); + } + } + if (checkViolation(player, result)) { + if (data.ground() != null) { + final double distance = MathUtil.distance(data.ground(), data.to()); + player.teleport(distance > maxSetbackDistance ? data.from() : data.ground()); + } else { + player.teleport(data.from()); + } + } + } + } + + } + + @Override + public void reloadConfig() { + load(); + } + + @Override + public void load() { + timeInLiquidRequired = configuration.getInt("time-in-liquid-required"); + maxNoVerticalCount = configuration.getInt("max-no-vertical-count"); + maxSmallMovementVerticalCount = configuration.getInt("max-small-vertical-movement-count"); + minVerticalAscend = configuration.getDouble("min-vertical-ascend"); + maxSetbackDistance = configuration.getDouble("max-setback-distance"); + } +} diff --git a/src/main/java/me/vrekt/arc/check/result/CancelType.java b/src/main/java/me/vrekt/arc/check/result/CancelType.java deleted file mode 100644 index 84d2141..0000000 --- a/src/main/java/me/vrekt/arc/check/result/CancelType.java +++ /dev/null @@ -1,11 +0,0 @@ -package me.vrekt.arc.check.result; - -/** - * Represents how to cancel. - * Either from where they moved or back to the ground. - */ -public enum CancelType { - - FROM, GROUND - -} diff --git a/src/main/java/me/vrekt/arc/command/commands/ArcSummarySubCommand.java b/src/main/java/me/vrekt/arc/command/commands/ArcSummarySubCommand.java index e688df3..d87358a 100644 --- a/src/main/java/me/vrekt/arc/command/commands/ArcSummarySubCommand.java +++ b/src/main/java/me/vrekt/arc/command/commands/ArcSummarySubCommand.java @@ -53,7 +53,8 @@ public void execute(CommandSender sender, String[] arguments) { final int playerDevice = player.getLoginChainData().getDeviceOS(); final int playerPing = player.getPing(); - final String playerDeviceId = playerDevice == 7 ? "Windows" : "Unknown"; + // TODO: Mapping of devices. + final String playerDeviceId = playerDevice == 7 ? "Windows" : "Unknown Device"; final String checksBypassed = bypass.isEmpty() ? " cannot bypass any checks." : " can bypass " + ArrayUtils.toString(bypass); final String playerGameMode = player.getGamemode() == 0 ? "Survival" @@ -62,7 +63,7 @@ public void execute(CommandSender sender, String[] arguments) { : player.getGamemode() == 3 ? "Spectator" : "Survival"; - message.setMainColor(TextFormat.AQUA).setParameterColor(TextFormat.GOLD); + message.setMainColor(TextFormat.AQUA).setParameterColor(TextFormat.GRAY); message.messagePrefix("Viewing summary report for: ").parameter(player.getName()).newLine(); message.parameterPrefix(player.getName()).message(" is playing on ").parameter(playerDeviceId).newLine(); message.parameterPrefix(player.getName()).message(" is currently in ").parameter(playerGameMode).newLine(); diff --git a/src/main/java/me/vrekt/arc/data/moving/MovingData.java b/src/main/java/me/vrekt/arc/data/moving/MovingData.java index e569480..1eabd03 100644 --- a/src/main/java/me/vrekt/arc/data/moving/MovingData.java +++ b/src/main/java/me/vrekt/arc/data/moving/MovingData.java @@ -153,6 +153,21 @@ public static MovingData retrieveTemporary() { */ private int blockIceDeltaAmount, offModifierTime, inAirDeltaAmount; + /** + * The water location for distance tracking. + */ + private Location waterLocation; + + /** + * The amount of no distance changes + * Time in liquid, time out of. + * Amount of times small movement counts in liquid + * Amount of times no vertical in water. + */ + private int liquidTime, outOfLiquidTime, liquidSmallMovementCount, noVerticalCount; + + private long lastSwimTime; + public Location from() { return from; } @@ -530,4 +545,52 @@ public int getInAirDeltaAmount() { public void setInAirDeltaAmount(int inAirDeltaAmount) { this.inAirDeltaAmount = MathUtil.clampInt(inAirDeltaAmount, 0, 1000); } + + public int liquidTime() { + return liquidTime; + } + + public void liquidTime(int liquidTime) { + this.liquidTime = MathUtil.clampInt(liquidTime, 0, 100); + } + + public int getOutOfLiquidTime() { + return outOfLiquidTime; + } + + public void setOutOfLiquidTime(int outOfLiquidTime) { + this.outOfLiquidTime = MathUtil.clampInt(outOfLiquidTime, 0, 100); + } + + public Location waterLocation() { + return waterLocation; + } + + public void waterLocation(Location waterLocation) { + this.waterLocation = waterLocation; + } + + public int getLiquidSmallMovementCount() { + return liquidSmallMovementCount; + } + + public void setLiquidSmallMovementCount(int liquidSmallMovementCount) { + this.liquidSmallMovementCount = MathUtil.clampInt(liquidSmallMovementCount, 0, 100); + } + + public int getNoVerticalCount() { + return noVerticalCount; + } + + public void setNoVerticalCount(int noVerticalCount) { + this.noVerticalCount = MathUtil.clampInt(noVerticalCount, 0, 100); + } + + public long getLastSwimTime() { + return lastSwimTime; + } + + public void setLastSwimTime(long lastSwimTime) { + this.lastSwimTime = lastSwimTime; + } } diff --git a/src/main/java/me/vrekt/arc/exemption/ExemptionManager.java b/src/main/java/me/vrekt/arc/exemption/ExemptionManager.java index 2cba9a6..18848e4 100644 --- a/src/main/java/me/vrekt/arc/exemption/ExemptionManager.java +++ b/src/main/java/me/vrekt/arc/exemption/ExemptionManager.java @@ -48,7 +48,8 @@ public void onPlayerJoin(Player player) { * @param player player */ private void doJoinExemptions(Player player) { - // + // players will have an odd vertical upon joining, not sure why. + addExemption(player, CheckType.FLIGHT, 500); } /** diff --git a/src/main/java/me/vrekt/arc/listener/packet/player/MovePlayerPacketListener.java b/src/main/java/me/vrekt/arc/listener/packet/player/MovePlayerPacketListener.java index 00a9153..30d21c8 100644 --- a/src/main/java/me/vrekt/arc/listener/packet/player/MovePlayerPacketListener.java +++ b/src/main/java/me/vrekt/arc/listener/packet/player/MovePlayerPacketListener.java @@ -10,6 +10,7 @@ import me.vrekt.arc.check.moving.Flight; import me.vrekt.arc.check.moving.Phase; import me.vrekt.arc.check.moving.Speed; +import me.vrekt.arc.check.moving.WaterWalk; import me.vrekt.arc.data.moving.MovingData; import me.vrekt.arc.listener.packet.NukkitPacketHandler; import me.vrekt.arc.listener.packet.NukkitPacketListener; @@ -36,11 +37,17 @@ public final class MovePlayerPacketListener extends NukkitPacketListener { */ private final Phase phase; + /** + * The water walk check. + */ + private final WaterWalk waterWalk; + public MovePlayerPacketListener(NukkitPacketHandler handler) { super(handler); flight = Arc.getInstance().getCheckManager().getCheck(CheckType.FLIGHT); speed = Arc.getInstance().getCheckManager().getCheck(CheckType.SPEED); phase = Arc.getInstance().getCheckManager().getCheck(CheckType.PHASE); + waterWalk = Arc.getInstance().getCheckManager().getCheck(CheckType.WATER_WALK); } @Override @@ -48,19 +55,29 @@ public void onPacketReceiving(DataPacketReceiveEvent event) { final Player player = event.getPlayer(); if (Permissions.canBypassCategory(player, CheckCategory.MOVING)) return; - final MovingData data = MovingData.get(player); final MovePlayerPacket packet = (MovePlayerPacket) event.getPacket(); + if (!Double.isFinite(packet.x) + || !Double.isFinite(packet.y) + || !Double.isFinite(packet.z)) return; + final MovingData data = MovingData.get(player); final Location from = data.to() == null ? player.getLocation() : data.to(); final Location to = new Location(packet.x, packet.y - player.getEyeHeight(), packet.z, player.level); + final double delta = from.distanceSquared(to); + + if (delta > 100) { + // large movement, ignore. + player.teleport(from); + return; + } - final double delta = Math.pow(from.x - to.x, 2) + Math.pow(from.y - to.y, 2) + Math.pow(from.z - to.z, 2); if (player.getHealth() > 0 && (delta > 1f / 256)) { final boolean hasMoved = from.getX() != to.getX() || from.getY() != to.getY() || from.getZ() != to.getZ(); if (hasMoved) { MovingAccess.calculateMovement(player, data, from, to); if (flight.enabled()) flight.check(player, data); if (speed.enabled()) speed.check(player, data); + if(waterWalk.enabled()) waterWalk.check(player, data); // if (phase.enabled()) phase.check(player, data); } } diff --git a/src/main/java/me/vrekt/arc/utility/MovingAccess.java b/src/main/java/me/vrekt/arc/utility/MovingAccess.java index 8dfbd9c..2d54701 100644 --- a/src/main/java/me/vrekt/arc/utility/MovingAccess.java +++ b/src/main/java/me/vrekt/arc/utility/MovingAccess.java @@ -25,8 +25,8 @@ public final class MovingAccess { * @return {@code true} if so */ public static boolean onGround(Location location) { - final Block block = location.subtract(0, 0.5, 0).getLevelBlock(); - location.add(0, 0.5, 0); + final Block block = location.subtract(0, 1, 0).getLevelBlock(); + location.add(0, 1, 0); return BlockAccess.isConsideredGround(block) || BlockAccess.hasSolidGroundAt(location, location.getLevel(), 0.3, -0.1, 0.3); diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index f28bec5..1cc4989 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -44,6 +44,8 @@ permissions: description: Allows the player to bypass the Speed check. arc.bypass.moving.phase: description: Allows the player to bypass the Phase check. + arc.bypass.moving.waterwalk: + description: Allows the player to bypass the WaterWalk check. arc.bypass.block: description: Allows the player to bypass block related checks children: