Skip to content

Commit

Permalink
反作弊功能更新
Browse files Browse the repository at this point in the history
添加HighJumpA检查。
添加SpeedB检查。
修复一个误判。
修复一个崩溃bug。

已知误判:
- **FlightA** 鞘翅、三叉戟。
- **BlinkA** 状态效果。
- **SpeedA** 状态效果、道具。服务器以下雨天启动。
- **AirJumpA** blink时意外触发。
  • Loading branch information
xia-mc committed Mar 30, 2024
1 parent 627bb50 commit b48171c
Show file tree
Hide file tree
Showing 11 changed files with 150 additions and 24 deletions.
12 changes: 8 additions & 4 deletions src/main/java/top/infsky/timerecorder/anticheat/Check.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,18 @@ public Check(String checkName, @NotNull TRPlayer player) {

public final void flag() {
violations++;
LogUtils.alert(player.playerData.getName(), checkName, String.format("VL: %s", violations));
LogUtils.alert(player.playerData.getName(), checkName, String.format("(VL:%s)", violations));
}

public final void flag(String extraMsg) {
violations++;
LogUtils.alert(player.playerData.getName(), checkName, extraMsg);
LogUtils.alert(player.playerData.getName(), checkName, String.format("(VL:%s) %s", violations, extraMsg));
}

public final void setback(@NotNull Vec3 position) {
if (!CONFIG().isAllowSetback()) return;
player.hasSetback = true;
player.needToDoNextTick.add(() -> player.needToDoNextTick.add(() -> player.hasSetback = false));
player.timeTask.addTask(() -> player.hasSetback = false, 1);
player.fabricPlayer.moveTo(position);
player.fabricPlayer.teleportTo(position.x(), position.y(), position.z());
player.fabricPlayer.connection.resetPosition();
Expand All @@ -48,10 +48,14 @@ public final void setback(@NotNull CallbackInfo ci) {
if (!CONFIG().isAllowSetback()) return;
ci.cancel();
player.fabricPlayer.connection.resetPosition();
badPacket();
}

public final void badPacket() {
if (setbackFoodLevel == null)
setbackFoodLevel = player.fabricPlayer.getFoodData().getFoodLevel();
player.fabricPlayer.getFoodData().setFoodLevel(0);
player.needToDoNextTick.add(() -> {
player.timeTask.addTask(() -> {
player.fabricPlayer.getFoodData().setFoodLevel(setbackFoodLevel);
setbackFoodLevel = null;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
public class CheckManager {
public final TRPlayer player;
public List<Check> checks = new ArrayList<>();
public short disableTick;
public CheckManager(List<Check> checks, TRPlayer player) {
this.player = player;
this.checks.addAll(checks);
this.disableTick = 10;
}

@Contract("_ -> new")
Expand All @@ -25,13 +27,20 @@ public CheckManager(List<Check> checks, TRPlayer player) {
new BlinkA(player),
new AirJumpA(player),
new AirPlaceA(player),
new SpeedA(player)
new SpeedA(player),
new SpeedB(player),
new HighJumpA(player)
), player);
checkManager.onTeleport();
return checkManager;
}

public void update() {
if (disableTick > 0) {
disableTick--;
return;
}

if (player.fabricPlayer.isSpectator() || player.fabricPlayer.isCreative()) return;
for (Check check : checks) {
check._onTick();
Expand All @@ -51,6 +60,7 @@ public void onTeleport() {
}

public void onJump() {
player.jumping = true;
for (Check check : checks) {
check._onJump();
}
Expand Down
13 changes: 5 additions & 8 deletions src/main/java/top/infsky/timerecorder/anticheat/TRPlayer.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package top.infsky.timerecorder.anticheat;

import lombok.Getter;
import lombok.val;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Range;
import top.infsky.timerecorder.Utils;
import top.infsky.timerecorder.anticheat.utils.TimeTaskManager;
import top.infsky.timerecorder.config.AntiCheatConfig;
import top.infsky.timerecorder.config.ModConfig;
import top.infsky.timerecorder.data.PlayerData;
Expand All @@ -33,8 +33,9 @@ public class TRPlayer {
public Vec3 lastInLiquidPos;
public boolean lastOnGround;
public boolean hasSetback = false;
public boolean jumping = false;

public List<Runnable> needToDoNextTick = new LinkedList<>();
public TimeTaskManager timeTask = new TimeTaskManager();

public TRPlayer(@NotNull PlayerData playerData) {
this.fabricPlayer = (ServerPlayer) playerData.player;
Expand All @@ -56,19 +57,15 @@ public void update() {
updatePoses();
if (fabricPlayer.onGround()) {
lastOnGroundPos = currentPos;
jumping = false;
}
if (fabricPlayer.isInWater() || fabricPlayer.isInLava()) {
lastInLiquidPos = currentPos;
}
timeTask.onTick();

val preTask = needToDoNextTick;
for (Runnable task : preTask) {
task.run();
needToDoNextTick.remove(task);
}
manager.update();


lastPos = currentPos;
lastOnGround = fabricPlayer.onGround();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public void _onTick() {
}

if (player.fabricPlayer.onGround()) {
jumpTick = 1;
jumpTick = 1; // MC原版OnGround不可靠。方块边缘会误判。
setbackPos = player.lastOnGroundPos;
}

Expand All @@ -47,8 +47,8 @@ public void _onTick() {


if (!player.fabricPlayer.onGround() && jumpTick > 0
&& player.currentPos.y() - player.lastOnGroundPos.y() < 1.25219 * (1 + player.fabricPlayer.getJumpBoostPower()) + CONFIG().getThreshold()
&& player.currentPos.distanceTo(player.lastPos) < 5.612 * (1 + player.fabricPlayer.getSpeed()) + CONFIG().getThreshold() // 警惕跳跃弱检测
// && player.currentPos.y() - player.lastOnGroundPos.y() < 1.25219 * (1 + player.fabricPlayer.getJumpBoostPower()) + CONFIG().getThreshold()
// && player.currentPos.distanceTo(player.lastPos) < 5.612 * (1 + player.fabricPlayer.getSpeed()) + CONFIG().getThreshold() // 警惕跳跃弱检测
) {
jumpTick--;
} else if ((!player.fabricPlayer.isInWater() || !player.fabricPlayer.isInLava()) && liquidTick > 0
Expand All @@ -68,7 +68,7 @@ public void _onTick() {

@Override
public void _onTeleport() {
disableTick = 6;
disableTick = 2;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package top.infsky.timerecorder.anticheat.checks;

import lombok.val;
import net.minecraft.world.phys.Vec3;
import top.infsky.timerecorder.anticheat.Check;
import top.infsky.timerecorder.anticheat.TRPlayer;

import static top.infsky.timerecorder.anticheat.TRPlayer.CONFIG;

public class HighJumpA extends Check {
public double highestY = Double.MIN_VALUE;
public HighJumpA(TRPlayer player) {
super("HighJumpA", player);
}

@Override
public void _onTick() {
if (player.isJumping()) {
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();
setback(player.lastOnGroundPos);
}
} else highestY = Double.MIN_VALUE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public SpeedA(@NotNull TRPlayer player) {

@Override
public void _onTick() {
if (hasJumped && !player.lastOnGround && player.fabricPlayer.onGround()) {
if (hasJumped && !player.jumping) {
hasJumped = false;
jumpTick = 10;
return;
Expand Down
19 changes: 19 additions & 0 deletions src/main/java/top/infsky/timerecorder/anticheat/checks/SpeedB.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package top.infsky.timerecorder.anticheat.checks;

import top.infsky.timerecorder.anticheat.Check;
import top.infsky.timerecorder.anticheat.TRPlayer;

public class SpeedB extends Check {
public SpeedB(TRPlayer player) {
super("SpeedB", player);
}

@Override
public void _onTick() {
if (player.fabricPlayer.isSprinting() && player.fabricPlayer.getFoodData().getFoodLevel() <= 6) {
flag();
badPacket();
player.fabricPlayer.setSprinting(false);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package top.infsky.timerecorder.anticheat.utils;

import org.jetbrains.annotations.Range;

import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;

public class TimeTaskManager {
private final List<Queue<Runnable>> tasks;

public TimeTaskManager() {
this.tasks = new LinkedList<>();
}

public void addTask(Runnable task) {
addTask(task, 0);
}

public void addTask(Runnable task, @Range(from = 0, to = Integer.MIN_VALUE) int delay) {
try {
tasks.get(delay).add(task);
} catch (IndexOutOfBoundsException e) {
if (delay > tasks.size())
for (int i = tasks.size(); i <= delay; i++) {
tasks.add(new LinkedBlockingQueue<>());
}
tasks.add(delay, new LinkedBlockingQueue<>());
addTask(task, delay);
}
}

public void onTick() {
try {
for (Runnable task : tasks.remove(0)) {
task.run();
}
} catch (IndexOutOfBoundsException ignored) {}
}
}
5 changes: 0 additions & 5 deletions src/main/java/top/infsky/timerecorder/mixins/MixinPacket.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@ public void handleMovePlayer(ServerboundMovePlayerPacket packet, CallbackInfo ci
val trPlayer = Objects.requireNonNull(Utils.getPlayer(this.getPlayer().getUUID())).antiCheat;

trPlayer.manager.onPacketReceive(packet, ci);
if (getPlayer().onGround() && !packet.isOnGround()
// && packet.getY(getPlayer().getY()) - getPlayer().getY() > 0
) {
trPlayer.manager.onJump();
}
} catch (NullPointerException ignored) {}
}

Expand Down
29 changes: 29 additions & 0 deletions src/main/java/top/infsky/timerecorder/mixins/MixinPlayer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package top.infsky.timerecorder.mixins;


import com.mojang.authlib.GameProfile;
import lombok.val;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import top.infsky.timerecorder.Utils;

import java.util.Objects;

@Mixin(Player.class)
public class MixinPlayer {
@Shadow @Final private GameProfile gameProfile;

@Inject(method = "jumpFromGround", at = @At(value = "HEAD"))
public void jumpFromGround(CallbackInfo ci) {
try {
val trPlayer = Objects.requireNonNull(Utils.getPlayer(this.gameProfile.getId())).antiCheat;

trPlayer.manager.onJump();
} catch (NullPointerException ignored) {}
}
}
3 changes: 2 additions & 1 deletion src/main/resources/timerecorder.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"compatibilityLevel": "JAVA_17",
"mixins": [
"MixinCommand",
"MixinPacket"
"MixinPacket",
"MixinPlayer"
],
"injectors": {
"defaultRequire": 1
Expand Down

0 comments on commit b48171c

Please sign in to comment.