diff --git a/src/main/java/top/infsky/timerecorder/anticheat/CheckManager.java b/src/main/java/top/infsky/timerecorder/anticheat/CheckManager.java index 247c474..2b8fa02 100644 --- a/src/main/java/top/infsky/timerecorder/anticheat/CheckManager.java +++ b/src/main/java/top/infsky/timerecorder/anticheat/CheckManager.java @@ -29,7 +29,8 @@ public CheckManager(List checks, TRPlayer player) { new AirPlaceA(player), new SpeedA(player), new SpeedB(player), - new HighJumpA(player) + new HighJumpA(player), + new NoSlowA(player) ), player); checkManager.onTeleport(); return checkManager; diff --git a/src/main/java/top/infsky/timerecorder/anticheat/TRPlayer.java b/src/main/java/top/infsky/timerecorder/anticheat/TRPlayer.java index b6579fe..08ec09f 100644 --- a/src/main/java/top/infsky/timerecorder/anticheat/TRPlayer.java +++ b/src/main/java/top/infsky/timerecorder/anticheat/TRPlayer.java @@ -31,9 +31,11 @@ public class TRPlayer { @Range(from = 0, to = 19) public List posHistory; public Vec3 lastOnGroundPos; public Vec3 lastInLiquidPos; + public Vec3 lastOnLiquidGroundPos; public boolean lastOnGround; public boolean hasSetback = false; public boolean jumping = false; + public boolean lastUsingItem = false; public TimeTaskManager timeTask = new TimeTaskManager(); @@ -58,6 +60,8 @@ public void update() { if (fabricPlayer.onGround()) { lastOnGroundPos = currentPos; jumping = false; + if (fabricPlayer.isInWater()) + lastOnLiquidGroundPos = currentPos; } if (fabricPlayer.isInWater() || fabricPlayer.isInLava()) { lastInLiquidPos = currentPos; @@ -68,6 +72,7 @@ public void update() { lastPos = currentPos; lastOnGround = fabricPlayer.onGround(); + lastUsingItem = fabricPlayer.isUsingItem(); } private void updatePoses() { diff --git a/src/main/java/top/infsky/timerecorder/anticheat/checks/HighJumpA.java b/src/main/java/top/infsky/timerecorder/anticheat/checks/HighJumpA.java index 8dc87cd..76d3e0a 100644 --- a/src/main/java/top/infsky/timerecorder/anticheat/checks/HighJumpA.java +++ b/src/main/java/top/infsky/timerecorder/anticheat/checks/HighJumpA.java @@ -15,14 +15,15 @@ public HighJumpA(TRPlayer player) { @Override public void _onTick() { - if (player.isJumping()) { + if (player.isJumping() && player.lastOnGroundPos != player.lastOnLiquidGroundPos) { if (player.currentPos.y() > highestY) highestY = player.currentPos.y(); val groundPrefixPos = new Vec3(0, player.lastOnGroundPos.y(), 0); val airPrefixPos = new Vec3(0, highestY, 0); - if (airPrefixPos.distanceTo(groundPrefixPos) > 1.25219 * (1 + player.fabricPlayer.getJumpBoostPower()) + CONFIG().getThreshold()) { - flag(); + final double jumpDistance = airPrefixPos.distanceTo(groundPrefixPos); + if (jumpDistance > 1.25219 * (1 + player.fabricPlayer.getJumpBoostPower()) + CONFIG().getThreshold()) { + flag(String.valueOf(jumpDistance)); setback(player.lastOnGroundPos); } } else highestY = Double.MIN_VALUE; diff --git a/src/main/java/top/infsky/timerecorder/anticheat/checks/NoSlowA.java b/src/main/java/top/infsky/timerecorder/anticheat/checks/NoSlowA.java new file mode 100644 index 0000000..7772254 --- /dev/null +++ b/src/main/java/top/infsky/timerecorder/anticheat/checks/NoSlowA.java @@ -0,0 +1,45 @@ +package top.infsky.timerecorder.anticheat.checks; + +import org.jetbrains.annotations.NotNull; +import top.infsky.timerecorder.anticheat.Check; +import top.infsky.timerecorder.anticheat.TRPlayer; +import top.infsky.timerecorder.anticheat.utils.PlayerMove; + +import java.util.List; + +import static top.infsky.timerecorder.anticheat.TRPlayer.CONFIG; + +public class NoSlowA extends Check { + public static final List SLOW_SPEED = List.of(2.56, 1.92, 1.6, 1.4, 1.36, 1.26, 1.18, 1.16); + public short itemUseTick = 0; + public short disableTick = 0; // 跳跃弱检测 + public NoSlowA(@NotNull TRPlayer player) { + super("NoSlowA", player); + } + + @Override + public void _onTick() { + if (!player.fabricPlayer.isUsingItem() || !player.lastUsingItem) { + itemUseTick = 0; + return; // 当连续两个tick使用物品才检查 + } + if (player.jumping) { + disableTick = 4; + return; + } + if (disableTick > 0) { + disableTick--; + return; + } + + final double secSpeed = PlayerMove.getXzSecSpeed(player.lastPos, player.currentPos); + + if (secSpeed > SLOW_SPEED.get(itemUseTick) * (1 + player.fabricPlayer.getSpeed()) + CONFIG().getThreshold()) { + flag(); + setback(player.lastPos); + player.fabricPlayer.stopUsingItem(); + badPacket(); + } + if (itemUseTick < SLOW_SPEED.size() - 1) itemUseTick++; + } +} diff --git a/src/main/java/top/infsky/timerecorder/anticheat/checks/SpeedA.java b/src/main/java/top/infsky/timerecorder/anticheat/checks/SpeedA.java index 6a951fe..045c951 100644 --- a/src/main/java/top/infsky/timerecorder/anticheat/checks/SpeedA.java +++ b/src/main/java/top/infsky/timerecorder/anticheat/checks/SpeedA.java @@ -1,10 +1,9 @@ package top.infsky.timerecorder.anticheat.checks; -import lombok.val; -import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; import top.infsky.timerecorder.anticheat.Check; import top.infsky.timerecorder.anticheat.TRPlayer; +import top.infsky.timerecorder.anticheat.utils.PlayerMove; import static top.infsky.timerecorder.anticheat.TRPlayer.CONFIG; @@ -28,21 +27,20 @@ public void _onTick() { // check if player is on ground (not in liquid or in water) if (player.lastPos == null || player.hasSetback || !player.fabricPlayer.onGround() || !player.lastOnGround || player.fabricPlayer.isInWater()) return; - val curPrefixPos = new Vec3(player.currentPos.x, 0, player.currentPos.z); - val lastPrefixPos = new Vec3(player.lastPos.x, 0, player.lastPos.z); - double maxTickSpeed; + double maxSecSpeed; if (jumpTick > 0) - maxTickSpeed = 0.37; + maxSecSpeed = 7.4; else if (player.fabricPlayer.isSprinting()) - maxTickSpeed = 0.2806; + maxSecSpeed = 5.612; else if (player.fabricPlayer.isSilent()) - maxTickSpeed = 0.06475; + maxSecSpeed = 1.295; else // walking - maxTickSpeed = 0.21585; + maxSecSpeed = 4.317; - if (curPrefixPos.distanceTo(lastPrefixPos) > (maxTickSpeed * (1 + player.fabricPlayer.getSpeed()) + CONFIG().getThreshold())) { - flag(String.valueOf(curPrefixPos.distanceTo(lastPrefixPos) * 20)); - setback(player.lastPos); + final double speed = PlayerMove.getXzSecSpeed(player.lastPos, player.currentPos); + if (speed > (maxSecSpeed * (1 + player.fabricPlayer.getSpeed()) + CONFIG().getThreshold())) { + flag(String.valueOf(speed)); +// setback(player.lastPos); } } diff --git a/src/main/java/top/infsky/timerecorder/anticheat/utils/PlayerMove.java b/src/main/java/top/infsky/timerecorder/anticheat/utils/PlayerMove.java new file mode 100644 index 0000000..582d47f --- /dev/null +++ b/src/main/java/top/infsky/timerecorder/anticheat/utils/PlayerMove.java @@ -0,0 +1,25 @@ +package top.infsky.timerecorder.anticheat.utils; + +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; +import top.infsky.timerecorder.Utils; + +public class PlayerMove { + public static double getXzTickSpeed(@NotNull Vec3 lastTick, @NotNull Vec3 currentTick) { + Vec3 prefixLast = new Vec3(lastTick.x(), 0, lastTick.z()); + Vec3 prefixCurrent = new Vec3(currentTick.x(), 0, currentTick.z()); + return prefixCurrent.distanceTo(prefixLast); + } + + public static double getXzSecSpeed(@NotNull Vec3 lastTick, @NotNull Vec3 currentTick) { + assert Utils.getSERVER() != null; + + final double tickSpeed = getXzTickSpeed(lastTick, currentTick); + final double tickTime = Utils.getSERVER().tickTimes[Utils.getSERVER().getTickCount() % 100] / 1000000.0; +// LogUtils.alert("tickTime", "debug", String.valueOf(tickTime)); + if (tickTime <= 50) + return tickSpeed * 20; + else + return tickSpeed * 1000 / tickTime; + } +}