Added new Aim check and utils

- Fixed TickTimer not functioning
- Fixed generalCancel always cancelling
- Removed debug from places that I am not currently in need of debugging
- Attempting to fix login error when reloading when injecting packethandler
- Added sensitivity to playerInfo command
- Fixed runaway buffer fp on Fly (A)
This commit is contained in:
Dawson
2022-08-11 13:25:57 -04:00
parent 234744e98d
commit f75657744a
12 changed files with 684 additions and 31 deletions
+4 -3
View File
@@ -68,8 +68,6 @@ public class Anticheat extends JavaPlugin {
.setNameFormat("Anticheat Schedular")
.setUncaughtExceptionHandler((t, e) -> RunUtils.task(e::printStackTrace))
.build());
packetProcessor = new PacketProcessor();
HandlerAbstract.init();
commandManager = new BukkitCommandManager(this);
commandManager.enableUnstableAPI("help");
@@ -77,11 +75,14 @@ public class Anticheat extends JavaPlugin {
new CommandPropertiesManager(commandManager, getDataFolder(),
getResource("command-messages.properties"));
this.keepaliveProcessor = new KeepaliveProcessor();
packetProcessor = new PacketProcessor();
this.checkManager = new CheckManager();
this.playerRegistry = new PlayerRegistry();
this.keepaliveProcessor = new KeepaliveProcessor();
this.packetHandler = new PacketHandler();
HandlerAbstract.init();
alog(Color.Green + "Loading WorldInfo system...");
Bukkit.getWorlds().forEach(w -> worldInfoMap.put(w.getUID(), new WorldInfo(w)));
@@ -0,0 +1,99 @@
package dev.brighten.ac.check.impl.combat;
import dev.brighten.ac.check.Action;
import dev.brighten.ac.check.Check;
import dev.brighten.ac.check.CheckData;
import dev.brighten.ac.check.CheckType;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.TickTimer;
import java.util.List;
@CheckData(name = "Aim", type = CheckType.COMBAT)
public class Aim extends Check {
public Aim(APlayer player) {
super(player);
}
private float buffer;
protected Timer lastGrid = new TickTimer(3);
@Action
public void flying(WPacketPlayInFlying packet) {
if(!packet.isLooked()) return;
final float sens = getPlayer().getMovement().getSensitivityMcp(),
deltaYaw = Math.abs(getPlayer().getMovement().getDeltaYaw()),
deltaPitch = Math.abs(getPlayer().getMovement().getDeltaPitch());
final float deltaX = deltaYaw / getPlayer().getMovement().getYawMode();
final float deltaY = deltaPitch / getPlayer().getMovement().getPitchMode();
if(getPlayer().getMovement().getYawGcdList().size() < 40)
return;
final double gridX = getGrid(getPlayer().getMovement().getYawGcdList()),
gridY = getGrid(getPlayer().getMovement().getPitchGcdList());
if(gridX < 0.005 || gridY < 0.005) lastGrid.reset();
if(deltaX > 200 || deltaY > 200) {
if(buffer > 0) buffer--;
getPlayer().getBukkitPlayer().sendMessage("Unstable");
return;
}
if(getPlayer().getMovement().getPitchGCD() < 0.007
&& lastGrid.isPassed()
&& getPlayer().getMovement().getLastHighRate().isNotPassed(3)) {
if(deltaPitch < 10 && ++buffer > 8) {
flag("%s", getPlayer().getMovement().getPitchGCD());
}
getPlayer().getBukkitPlayer().sendMessage("Flagged b:" + buffer);
} else buffer = 0;
}
/*
* This is an attempt to reverse the logistics of cinematic camera without having to run a full on prediction using
* mouse filters. Otherwise, we would need to run more heavy calculations which is not really production friendly.
* It may be more accurate but it is not really worth it if in the end of the day we're eating server performance.
*/
protected static double getGrid(final List<Float> entry) {
/*
* We're creating the variables average min and max to start calculating the possibility of cinematic camera.
* Why does this work? Cinematic camera is essentially a slowly increasing slowdown (which is why cinematic camera
* becomes slower the more you use it) which in turn makes it so the min max and average are extremely close together.
*/
double average = 0.0;
double min = 0.0, max = 0.0;
/*
* These are simple min max calculations done manually for the sake of simplicity. We're using the numbers 0.0
* since we also want to account for the possibility of a negative number. If there are no negative numbers then
* there is absolutely no need for us to care about that number other than getting the max.
*/
for (final double number : entry) {
if (number < min) min = number;
if (number > max) max = number;
/*
* Instead of having a sum variable we can use an average variable which we divide
* right after the loop is over. Smart programming trick if you want to use it.
*/
average += number;
}
/*
* We're dividing the average by the length since this is the formula to getting the average.
* Specifically its (sum(n) / length(n)) = average(n) -- with n being the entry set we're analyzing.
*/
average /= entry.size();
/*
* This is going to estimate how close the average and the max were together with the possibility of a min
* variable which is going to represent a negative variable since the preset variable on min is 0.0.
*/
return (max - average) - min;
}
}
@@ -40,7 +40,6 @@ public class Reach extends Check {
if(packet.getAction() == WPacketPlayInUseEntity.EnumEntityUseAction.ATTACK
&& allowedEntityTypes.contains(packet.getEntity(getPlayer().getBukkitPlayer().getWorld()).getType())) {
attacks.add(packet.getEntity(getPlayer().getBukkitPlayer().getWorld()));
getPlayer().getBukkitPlayer().sendMessage("Attacked");
}
}
@@ -26,8 +26,8 @@ public class FlyA extends Check {
@Action
public void onFlying(WPacketPlayInFlying packet) {
if(!packet.isMoved() || (getPlayer().getMovement().getDeltaXZ() == 0
&& getPlayer().getMovement().getDeltaY() == 0)) return;
&& getPlayer().getMovement().getDeltaY() == 0))
return;
boolean onGround = getPlayer().getMovement().getTo().isOnGround(),
fromGround = getPlayer().getMovement().getFrom().isOnGround();
@@ -55,6 +55,7 @@ public class FlyA extends Check {
if(!getPlayer().getInfo().isGeneralCancel() && deltaPredict > 0.016) {
if(++buffer > 5) {
buffer = 5;
flag("dY=%.3f p=%.3f dx=%.3f", getPlayer().getMovement().getDeltaY(), predicted,
getPlayer().getMovement().getDeltaXZ());
}
@@ -35,10 +35,8 @@ public class Speed extends Check {
.toLocation(getPlayer().getBukkitPlayer().getWorld())
.subtract(0, 1, 0));
if (underBlock == null || lastUnderBlock == null) {
getPlayer().getBukkitPlayer().sendMessage("Null");
if (underBlock == null || lastUnderBlock == null)
return;
}
float friction = CraftMagicNumbers.getBlock(underBlock).frictionFactor,
lfriction = CraftMagicNumbers.getBlock(lastUnderBlock).frictionFactor;
@@ -92,6 +92,7 @@ public class AnticheatCommand extends BaseCommand {
sender.sendMessage(MiscUtils.line(Color.Dark_Gray));
sender.sendMessage(Color.translate("&6&lPing&8: &f" + player.getLagInfo().getTransPing() * 50 + "ms"));
sender.sendMessage(Color.translate("&6&lVersion&8: &f" + player.getPlayerVersion().name()));
sender.sendMessage(Color.translate("&6&lSensitivity&8: &f" + player.getMovement().getSensXPercent() + "%"));
sender.sendMessage(MiscUtils.line(Color.Dark_Gray));
});
}
@@ -19,6 +19,8 @@ import dev.brighten.ac.packet.handler.HandlerAbstract;
import dev.brighten.ac.utils.Tuple;
import dev.brighten.ac.utils.reflections.impl.MinecraftReflection;
import dev.brighten.ac.utils.reflections.types.WrappedMethod;
import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.MillisTimer;
import lombok.Getter;
import lombok.Setter;
import lombok.val;
@@ -52,6 +54,8 @@ public class APlayer {
@Getter
private int playerTick;
@Getter
private Timer creation = new MillisTimer();
@Getter
//TODO Actually grab real player version once finished implementing version grabber from Atlas
private ProtocolVersion playerVersion = ProtocolVersion.UNKNOWN;
@Getter
@@ -87,9 +91,11 @@ public class APlayer {
this.lagInfo = new LagInformation();
this.blockInformation = new BlockInformation(this);
// Grabbing the protocol version of the player.
Anticheat.INSTANCE.getScheduler().execute(() ->
playerVersion = ProtocolVersion.getVersion(ProtocolAPI.INSTANCE.getPlayerVersion(getBukkitPlayer())));
// Enabling alerts for players on join if they have the permissions to
if(getBukkitPlayer().hasPermission("anticheat.command.alerts")
|| getBukkitPlayer().hasPermission("anticheat.alerts")) {
Check.alertsEnabled.add(getUuid());
@@ -14,6 +14,7 @@ import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.val;
import org.bukkit.GameMode;
import org.bukkit.Location;
@@ -33,22 +34,35 @@ public class MovementHandler {
private double deltaX, deltaY, deltaZ, deltaXZ,
lDeltaX, lDeltaY, lDeltaZ, lDeltaXZ;
@Getter
private float deltaYaw, deltaPitch, lDeltaYaw, lDeltaPitch;
private float lookX, lookY, lastLookX, lastLookY;
@Getter
private float deltaYaw, deltaPitch, lDeltaYaw, lDeltaPitch, smoothYaw, smoothPitch, lsmoothYaw, lsmoothPitch, pitchGCD, lastPitchGCD, yawGCD, lastYawGCD;
private int moveTicks;
private final List<KLocation> posLocs = new ArrayList<>();
@Getter
private boolean checkMovement;
private boolean checkMovement, accurateYawData, cinematicMode;
@Getter
@Setter
private boolean excuseNextFlying;
@Getter
private final Timer lastTeleport = new TickTimer();
private final Timer lastTeleport = new TickTimer(), lastHighRate = new TickTimer();
private int teleportsToConfirm;
@Getter
private final LinkedList<Float> yawGcdList = new EvictingList<>(45),
pitchGcdList = new EvictingList<>(45);
@Getter
private float sensitivityX, sensitivityY, currentSensX, currentSensY, sensitivityMcp, yawMode, pitchMode;
@Getter
private int sensXPercent, sensYPercent;
@Getter
private TickTimer lastCinematic = new TickTimer(2);
private MouseFilter mxaxis = new MouseFilter(), myaxis = new MouseFilter();
private float smoothCamFilterX, smoothCamFilterY, smoothCamYaw, smoothCamPitch;
private Timer lastReset = new TickTimer(2), generalProcess = new TickTimer(3);
private final EvictingList<Integer> sensitivitySamples = new EvictingList<>(50);
public void process(WPacketPlayInFlying packet, long currentTime) {
@@ -82,6 +96,132 @@ public class MovementHandler {
checkForTeleports(packet);
if (packet.isLooked()) {
float deltaYaw = Math.abs(this.deltaYaw), lastDeltaYaw = Math.abs(this.lDeltaYaw);
final double differenceYaw = Math.abs(this.deltaYaw - lastDeltaYaw);
final double differencePitch = Math.abs(this.deltaPitch - this.lDeltaPitch);
final double joltYaw = Math.abs(differenceYaw - deltaYaw);
final double joltPitch = Math.abs(differencePitch - this.deltaPitch);
final float yawThreshold = Math.max(1.0f, deltaYaw / 2f),
pitchThreshold = Math.max(1.f, Math.abs(this.deltaPitch) / 2f);
if (joltYaw > yawThreshold && joltPitch > pitchThreshold) this.lastHighRate.reset();
this.lastPitchGCD = this.pitchGCD;
this.lastYawGCD = this.yawGCD;
this.yawGCD = MathUtils
.gcdSmall(this.deltaYaw, this.lDeltaYaw);
this.pitchGCD = MathUtils
.gcdSmall(this.deltaPitch, this.lDeltaPitch);
val origin = this.to.getLoc().clone();
origin.y+= player.getInfo().isSneaking() ? 1.54 : 1.62;
if(lastTeleport.isPassed(1)) {
predictionHandling:
{
float yawGcd = this.yawGCD,
pitchGcd = this.pitchGCD;
//Adding gcd of yaw and pitch.
if (this.yawGCD > 0.01 && this.yawGCD < 1.2) {
yawGcdList.add(yawGcd);
}
if (this.pitchGCD > 0.01 && this.pitchGCD < 1.2)
pitchGcdList.add(pitchGcd);
if(yawGcdList.size() < 20 || pitchGcdList.size() < 20) {
accurateYawData = false;
break predictionHandling;
}
accurateYawData = true;
//Making sure to get shit within the std for a more accurate result.
//Making sure to get shit within the std for a more accurate result.
currentSensX = getSensitivityFromYawGCD(yawGcd);
currentSensY = getSensitivityFromPitchGCD(pitchGcd);
if (lastReset.isPassed()) {
pitchMode = MathUtils.getMode(pitchGcdList);
lastReset.reset();
sensXPercent = sensToPercent(sensitivityX = getSensitivityFromYawGCD(yawMode));
sensYPercent = sensToPercent(sensitivityY = getSensitivityFromPitchGCD(pitchMode));
table: {
sensitivitySamples.add(Math.max(sensXPercent, sensYPercent));
if (sensitivitySamples.size() > 30) {
final long mode = MathUtils.getMode(sensitivitySamples);
sensitivityMcp = AimbotUtil.SENSITIVITY_MAP.getOrDefault((int) mode, -1.0F);
}
}
}
lastLookX = lookX;
lastLookY = lookY;
lookX = getExpiermentalDeltaX(player);
lookY = getExpiermentalDeltaY(player);
if ((this.pitchGCD < 0.006 && this.yawGCD < 0.006) && smoothCamFilterY < 1E6
&& smoothCamFilterX < 1E6 && player.getCreation().isPassed(1000L)) {
float sens = MovementHandler.percentToSens(95);
float f = sens * 0.6f + .2f;
float f1 = f * f * f * 8;
float f2 = lookX * f1;
float f3 = lookY * f1;
smoothCamFilterX = mxaxis.smooth(smoothCamYaw, .05f * f1);
smoothCamFilterY = myaxis.smooth(smoothCamPitch, .05f * f1);
this.smoothCamYaw += f2;
this.smoothCamPitch += f3;
f2 = smoothCamFilterX * 0.5f;
f3 = smoothCamFilterY * 0.5f;
//val clampedFrom = (Math.abs(this.from.yaw) > 360 ? this.from.yaw % 360 : this.from.yaw);
val clampedFrom = MathUtils.yawTo180F(getFrom().getLoc().yaw);
float pyaw = clampedFrom + f2 * .15f;
float ppitch = this.getFrom().getLoc().pitch - f3 * .15f;
this.lsmoothYaw = smoothYaw;
this.lsmoothPitch = smoothPitch;
this.smoothYaw = pyaw;
this.smoothPitch = ppitch;
float yaccel = Math.abs(this.deltaYaw) - Math.abs(this.lDeltaYaw),
pAccel = Math.abs(this.deltaPitch) - Math.abs(this.lDeltaPitch);
if (MathUtils.getDelta(smoothYaw, clampedFrom) > (yaccel > 0 ? (yaccel > 10 ? 2.5 : 1) : 0.3)
|| MathUtils.getDelta(smoothPitch, this.getFrom().getLoc().pitch)
> (pAccel > 0 ? (pAccel > 10 ? 2.5 : 1) : 0.3)) {
smoothCamYaw = smoothCamPitch = 0;
this.cinematicMode = false;
mxaxis.reset();
myaxis.reset();
} else this.cinematicMode = true;
} else {
mxaxis.reset();
myaxis.reset();
this.cinematicMode = false;
}
lastLookX = lookX;
lastLookY = lookY;
lookX = getExpiermentalDeltaX(player);
lookY = getExpiermentalDeltaY(player);
}
} else {
yawGcdList.clear();
pitchGcdList.clear();
}
}
player.getInfo().setCreative(player.getBukkitPlayer().getGameMode() == GameMode.CREATIVE
|| player.getBukkitPlayer().getGameMode() == GameMode.SPECTATOR);
@@ -103,27 +243,104 @@ public class MovementHandler {
/*
ata.playerInfo.generalCancel = data.getPlayer().getAllowFlight()
|| data.playerInfo.creative
|| this.creative
|| hasLevi
|| data.excuseNextFlying
|| data.getPlayer().isSleeping()
|| (data.playerInfo.lastGhostCollision.isNotPassed() && data.playerInfo.lastBlockPlace.isPassed(2))
|| data.playerInfo.doingTeleport
|| data.playerInfo.lastTeleportTimer.isNotPassed(1)
|| data.playerInfo.riptiding
|| data.playerInfo.gliding
|| data.playerInfo.vehicleTimer.isNotPassed(3)
|| data.playerInfo.lastPlaceLiquid.isNotPassed(5)
|| data.playerInfo.inVehicle
|| ((data.playerInfo.lastChunkUnloaded.isNotPassed(35) || data.playerInfo.doingBlockUpdate)
&& MathUtils.getDelta(-0.098, data.playerInfo.deltaY) < 0.0001)
|| timeStamp - data.playerInfo.lastRespawn < 2500L
|| data.playerInfo.lastToggleFlight.isNotPassed(40)
|| (this.lastGhostCollision.isNotPassed() && this.lastBlockPlace.isPassed(2))
|| this.doingTeleport
|| this.lastTeleportTimer.isNotPassed(1)
|| this.riptiding
|| this.gliding
|| this.vehicleTimer.isNotPassed(3)
|| this.lastPlaceLiquid.isNotPassed(5)
|| this.inVehicle
|| ((this.lastChunkUnloaded.isNotPassed(35) || this.doingBlockUpdate)
&& MathUtils.getDelta(-0.098, this.deltaY) < 0.0001)
|| timeStamp - this.lastRespawn < 2500L
|| this.lastToggleFlight.isNotPassed(40)
|| timeStamp - data.creation < 4000
|| Kauri.INSTANCE.lastTickLag.isNotPassed(5);
*/
}
private static float getDeltaX(float yawDelta, float gcd) {
return MathHelper.ceiling_float_int(yawDelta / gcd);
}
private static float getDeltaY(float pitchDelta, float gcd) {
return MathHelper.ceiling_float_int(pitchDelta / gcd);
}
public static float getExpiermentalDeltaX(APlayer data) {
float deltaPitch = data.getMovement().getDeltaYaw();
float sens = data.getMovement().sensitivityX;
float f = sens * 0.6f + .2f;
float calc = f * f * f * 8;
float result = deltaPitch / (calc * .15f);
return result;
}
public static float getExpiermentalDeltaY(APlayer data) {
float deltaPitch = data.getMovement().getDeltaPitch();
float sens = data.getMovement().sensitivityY;
float f = sens * 0.6f + .2f;
float calc = f * f * f * 8;
float result = deltaPitch / (calc * .15f);
return result;
}
public static int sensToPercent(float sensitivity) {
return MathHelper.floor_float(sensitivity / .5f * 100);
}
public static float percentToSens(int percent) {
return percent * .0070422534f;
}
public static float getSensitivityFromYawGCD(float gcd) {
return ((float) Math.cbrt(yawToF2(gcd) / 8f) - .2f) / .6f;
}
private static float getSensitivityFromPitchGCD(float gcd) {
return ((float)Math.cbrt(pitchToF3(gcd) / 8f) - .2f) / .6f;
}
private static float getF1FromYaw(float gcd) {
float f = getFFromYaw(gcd);
return f * f * f * 8;
}
private static float getFFromYaw(float gcd) {
float sens = getSensitivityFromYawGCD(gcd);
return sens * .6f + .2f;
}
private static float getFFromPitch(float gcd) {
float sens = getSensitivityFromPitchGCD(gcd);
return sens * .6f + .2f;
}
private static float getF1FromPitch(float gcd) {
float f = getFFromPitch(gcd);
return (float)Math.pow(f, 3) * 8;
}
private static float yawToF2(float yawDelta) {
return yawDelta / .15f;
}
private static float pitchToF3(float pitchDelta) {
int b0 = pitchDelta >= 0 ? 1 : -1; //Checking for inverted mouse.
return (pitchDelta / b0) / .15f;
}
public void addPosition(WPacketPlayOutPosition packet) {
int i = 0;
KLocation loc = new KLocation(packet.getX(), packet.getY(), packet.getZ(),
@@ -241,7 +458,7 @@ public class MovementHandler {
deltaY = to.getLoc().y - from.getLoc().y;
deltaZ = to.getLoc().z - from.getLoc().z;
deltaXZ = Math.hypot(deltaX, deltaZ); // Calculating here to cache since hypot() can be heavy.
deltaYaw = MathUtils.getAngleDelta(to.getLoc().yaw, from.getLoc().yaw);
deltaYaw = to.getLoc().yaw - from.getLoc().yaw;
deltaPitch = to.getLoc().pitch - from.getLoc().pitch;
}
}
@@ -6,6 +6,7 @@ import dev.brighten.ac.handler.thread.ThreadHandler;
import dev.brighten.ac.packet.handler.HandlerAbstract;
import dev.brighten.ac.packet.wrapper.PacketType;
import dev.brighten.ac.utils.Init;
import dev.brighten.ac.utils.RunUtils;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
@@ -74,10 +75,9 @@ public class JoinListener implements Listener {
@EventHandler
public void onJoin(PlayerJoinEvent event) {
System.out.println("Generating for " + event.getPlayer().getName());
APlayer player = Anticheat.INSTANCE.getPlayerRegistry().generate(event.getPlayer());
HandlerAbstract.getHandler().add(event.getPlayer());
RunUtils.taskLater(() -> HandlerAbstract.getHandler().add(event.getPlayer()), 3);
player.callEvent(event);
}
@@ -0,0 +1,324 @@
package dev.brighten.ac.utils;
import com.google.common.collect.Maps;
import java.util.List;
import java.util.Map;
public class AimbotUtil {
public static final Map<Integer, Float> SENSITIVITY_MAP = Maps.newHashMap();
static {
SENSITIVITY_MAP.put(1, 0.0070422534F);
SENSITIVITY_MAP.put(2, 0.014084507F);
SENSITIVITY_MAP.put(4, 0.02112676F);
SENSITIVITY_MAP.put(5, 0.028169014F);
SENSITIVITY_MAP.put(6, 0.0281690166F);
SENSITIVITY_MAP.put(7, 0.03521127F);
SENSITIVITY_MAP.put(8, 0.04225352F);
SENSITIVITY_MAP.put(9, 0.049295776F);
SENSITIVITY_MAP.put(10, 0.0492957736F);
SENSITIVITY_MAP.put(11, 0.056338027F);
SENSITIVITY_MAP.put(12, 0.06338028F);
SENSITIVITY_MAP.put(14, 0.07042254F);
SENSITIVITY_MAP.put(15, 0.07746479F);
SENSITIVITY_MAP.put(16, 0.08450704F);
SENSITIVITY_MAP.put(18, 0.09154929F);
SENSITIVITY_MAP.put(19, 0.09859155F);
SENSITIVITY_MAP.put(21, 0.1056338F);
SENSITIVITY_MAP.put(22, 0.112676054F);
SENSITIVITY_MAP.put(23, 0.11971831F);
SENSITIVITY_MAP.put(25, 0.12676056F);
SENSITIVITY_MAP.put(26, 0.13380282F);
SENSITIVITY_MAP.put(28, 0.14084508F);
SENSITIVITY_MAP.put(29, 0.14788732F);
SENSITIVITY_MAP.put(30, 0.15492958F);
SENSITIVITY_MAP.put(32, 0.16197184F);
SENSITIVITY_MAP.put(33, 0.16901408F);
SENSITIVITY_MAP.put(35, 0.17605634F);
SENSITIVITY_MAP.put(36, 0.18309858F);
SENSITIVITY_MAP.put(38, 0.19014084F);
SENSITIVITY_MAP.put(39, 0.1971831F);
SENSITIVITY_MAP.put(40, 0.20422535F);
SENSITIVITY_MAP.put(42, 0.2112676F);
SENSITIVITY_MAP.put(43, 0.21830986F);
SENSITIVITY_MAP.put(45, 0.22535211F);
SENSITIVITY_MAP.put(46, 0.23239437F);
SENSITIVITY_MAP.put(47, 0.23943663F);
SENSITIVITY_MAP.put(49, 0.24647887F);
SENSITIVITY_MAP.put(50, 0.2535211F);
SENSITIVITY_MAP.put(52, 0.26056337F);
SENSITIVITY_MAP.put(53, 0.26760563F);
SENSITIVITY_MAP.put(54, 0.2746479F);
SENSITIVITY_MAP.put(56, 0.28169015F);
SENSITIVITY_MAP.put(57, 0.28873238F);
SENSITIVITY_MAP.put(59, 0.29577464F);
SENSITIVITY_MAP.put(60, 0.3028169F);
SENSITIVITY_MAP.put(61, 0.30985916F);
SENSITIVITY_MAP.put(63, 0.31690142F);
SENSITIVITY_MAP.put(64, 0.32394367F);
SENSITIVITY_MAP.put(66, 0.3309859F);
SENSITIVITY_MAP.put(67, 0.33802816F);
SENSITIVITY_MAP.put(68, 0.34507042F);
SENSITIVITY_MAP.put(70, 0.35211268F);
SENSITIVITY_MAP.put(71, 0.35915494F);
SENSITIVITY_MAP.put(73, 0.36619717F);
SENSITIVITY_MAP.put(74, 0.37323943F);
SENSITIVITY_MAP.put(76, 0.3802817F);
SENSITIVITY_MAP.put(77, 0.38732395F);
SENSITIVITY_MAP.put(78, 0.3943662F);
SENSITIVITY_MAP.put(80, 0.40140846F);
SENSITIVITY_MAP.put(81, 0.4084507F);
SENSITIVITY_MAP.put(83, 0.41549295F);
SENSITIVITY_MAP.put(84, 0.4225352F);
SENSITIVITY_MAP.put(85, 0.42957747F);
SENSITIVITY_MAP.put(87, 0.43661973F);
SENSITIVITY_MAP.put(88, 0.44366196F);
SENSITIVITY_MAP.put(90, 0.45070422F);
SENSITIVITY_MAP.put(91, 0.45774648F);
SENSITIVITY_MAP.put(92, 0.46478873F);
SENSITIVITY_MAP.put(94, 0.471831F);
SENSITIVITY_MAP.put(95, 0.47887325F);
SENSITIVITY_MAP.put(97, 0.48591548F);
SENSITIVITY_MAP.put(98, 0.49295774F);
SENSITIVITY_MAP.put(100, 0.5F);
SENSITIVITY_MAP.put(101, 0.5070422F);
SENSITIVITY_MAP.put(102, 0.5140845F);
SENSITIVITY_MAP.put(104, 0.52112675F);
SENSITIVITY_MAP.put(105, 0.52816904F);
SENSITIVITY_MAP.put(107, 0.53521127F);
SENSITIVITY_MAP.put(108, 0.5422535F);
SENSITIVITY_MAP.put(109, 0.5492958F);
SENSITIVITY_MAP.put(111, 0.556338F);
SENSITIVITY_MAP.put(112, 0.5633803F);
SENSITIVITY_MAP.put(114, 0.57042253F);
SENSITIVITY_MAP.put(115, 0.57746476F);
SENSITIVITY_MAP.put(116, 0.58450705F);
SENSITIVITY_MAP.put(118, 0.5915493F);
SENSITIVITY_MAP.put(119, 0.59859157F);
SENSITIVITY_MAP.put(121, 0.6056338F);
SENSITIVITY_MAP.put(122, 0.6126761F);
SENSITIVITY_MAP.put(123, 0.6197183F);
SENSITIVITY_MAP.put(125, 0.62676054F);
SENSITIVITY_MAP.put(126, 0.63380283F);
SENSITIVITY_MAP.put(128, 0.64084506F);
SENSITIVITY_MAP.put(129, 0.647887350F);
SENSITIVITY_MAP.put(130, 0.6549296F);
SENSITIVITY_MAP.put(132, 0.6619718F);
SENSITIVITY_MAP.put(133, 0.6690141F);
SENSITIVITY_MAP.put(135, 0.6760563F);
SENSITIVITY_MAP.put(136, 0.6830986F);
SENSITIVITY_MAP.put(138, 0.69014084F);
SENSITIVITY_MAP.put(139, 0.6971831F);
SENSITIVITY_MAP.put(140, 0.70422536F);
SENSITIVITY_MAP.put(142, 0.7112676F);
SENSITIVITY_MAP.put(143, 0.7183099F);
SENSITIVITY_MAP.put(145, 0.7253521F);
SENSITIVITY_MAP.put(146, 0.73239434F);
SENSITIVITY_MAP.put(147, 0.7394366F);
SENSITIVITY_MAP.put(149, 0.74647886F);
SENSITIVITY_MAP.put(150, 0.75352114F);
SENSITIVITY_MAP.put(152, 0.7605634F);
SENSITIVITY_MAP.put(153, 0.76760566F);
SENSITIVITY_MAP.put(154, 0.7746479F);
SENSITIVITY_MAP.put(156, 0.7816901F);
SENSITIVITY_MAP.put(157, 0.7887324F);
SENSITIVITY_MAP.put(159, 0.79577464F);
SENSITIVITY_MAP.put(160, 0.8028169F);
SENSITIVITY_MAP.put(161, 0.80985916F);
SENSITIVITY_MAP.put(163, 0.8169014F);
SENSITIVITY_MAP.put(164, 0.8239437F);
SENSITIVITY_MAP.put(166, 0.8309859F);
SENSITIVITY_MAP.put(167, 0.8380282F);
SENSITIVITY_MAP.put(169, 0.8450704F);
SENSITIVITY_MAP.put(170, 0.85211265F);
SENSITIVITY_MAP.put(171, 0.85915494F);
SENSITIVITY_MAP.put(173, 0.86619717F);
SENSITIVITY_MAP.put(174, 0.87323946F);
SENSITIVITY_MAP.put(176, 0.8802817F);
SENSITIVITY_MAP.put(177, 0.8873239F);
SENSITIVITY_MAP.put(178, 0.8943662F);
SENSITIVITY_MAP.put(180, 0.90140843F);
SENSITIVITY_MAP.put(181, 0.9084507F);
SENSITIVITY_MAP.put(183, 0.91549295F);
SENSITIVITY_MAP.put(184, 0.92253524F);
SENSITIVITY_MAP.put(185, 0.92957747F);
SENSITIVITY_MAP.put(187, 0.9366197F);
SENSITIVITY_MAP.put(188, 0.943662F);
SENSITIVITY_MAP.put(190, 0.9507042F);
SENSITIVITY_MAP.put(191, 0.9577465F);
SENSITIVITY_MAP.put(192, 0.96478873F);
SENSITIVITY_MAP.put(194, 0.97183096F);
SENSITIVITY_MAP.put(195, 0.97887325F);
SENSITIVITY_MAP.put(197, 0.9859155F);
SENSITIVITY_MAP.put(198, 0.9929578F);
SENSITIVITY_MAP.put(200, 1.0F);
}
/*
* Essentially what we're doing here is enclosing the possible rotations the player
* would've made in a normal framed scenario. The problem with the method we're using
* to verify the player's rotation (prediction) has one problem. And that problem is
* frame updates or as the client calls them "partial ticks". With this method, we can
* directly check if the player's rotation was in the range of possible values, and we can
* get that range with a simple limit check by complying the prediction vs the rotation
*
* Essentially it accounts for rotations that couldn't have been accurately predicted because
* they got updated many times outside of the tick.
*/
public static boolean enclosed(final float a, final float b, final float x) {
final float distance = MathUtils.getAngleDelta(a, b);
return MathUtils.getAngleDelta(a, x) < distance && MathUtils.getAngleDelta(b, x) < distance;
}
/*
* This gets the players sensitivity through reversing the GCD of the player which
* is the constant of the past 40 rotations, directly using minecraft math to achieve that.
*
* // Update the mouse position per frame
* this.mouseHelper.updateXY();
*
* // Grab the new deltaXY mouse values made
* final int deltaX = mouseHelper.getX();
* final int deltaY = mouseHelper.getY();
*
* // Run the sensitivity formula to construct the new yaw/pitch values
* final float sensitivityFormat = (float) sensitivity * 0.6F + 0.2F;
* final float sensitivityProduct = var132 * var132 * var132 * 8.0F;
*
* // Run the construction formula for yaw and pitch
* final float constructedYaw = (float) deltaX * sensitivityFormat;
* final float constructedPitch = (float) deltaY * sensitivityFormat
*
* // Account for rotation slowdown using the 0.15 as a constant number
* final float productYaw = Math.abs(rotationYaw) + constructedYaw * 0.15
* final float productPitch = Math.abs(rotationPitch) + constructedPitch * 0.15
*
* // Account for inversion
* this.rotationYaw = productYaw * inverseYaw;
* this.rotationPitch = productPitch * inversePitch;
*/
public static float getSensitivityFromYawGCD(float gcd) {
return ((float)Math.cbrt(yawToF2(gcd) / 8f) - .2f) / .6f;
}
public static float getSensitivityFromPitchGCD(float gcd) {
return ((float)Math.cbrt(pitchToF3(gcd) / 8f) - .2f) / .6f;
}
private static float yawToF2(float yawDelta) {
return yawDelta / .15f;
}
private static float pitchToF3(float pitchDelta) {
int b0 = pitchDelta >= 0 ? 1 : -1; //Checking for inverted mouse.
return (pitchDelta / b0) / .15f;
}
/*
* This is going to be used for our inverse method for rotations since the method we are currently
* using for inverse is a little inaccurate in some places due to the implementation of the game.
* This should have a non existent margin of error since it will always be accurate to the degree.
*/
private static float toRegularCircle(float angles) {
angles %= 360.F;
return angles < 0 ? angles + 360.F : angles;
}
public static int getInverseValue(final float current, final float previous, final InverseType type) {
int result;
/*
* We're not using a switch statement since there is only really two possibilities so a switch
* statement for my taste would simply be a little messy.
*/
if (type == InverseType.YAW) {
final float distance = MathUtils.getAngleDelta(previous, current);
/*
* We're expressing it as a regular circle since there is not a real limit to how the yaw is expressed
* meaning if we do the check dynamically like we used to, it will fail when resetting or on larger rotations
*/
final float circleX = toRegularCircle(previous);
final float circleY = toRegularCircle(current);
/*
* This is the valid expression to the delta which is going to help us understand the direction
* the player moved their head to get a more valid reading on their inversion.
*/
final double polarX = MathUtils.getAngleDelta(circleX + distance, circleY);
final double polarY = MathUtils.getAngleDelta(circleX - distance, circleY);
/*
* This is simply printing the result regularly without any issues. Simply, if a direction change,
* print -1 which will change the "way" we're running the prediction, otherwise print 1 which wont change it
*/
result = polarX < polarY ? 1 : -1;
}
/*
* This is the check for the pitch variant of this. This has to be checked differently since one is
* a vertical value when the other one is an expression of a circle. They are not the same.
*/
else {
final float distance = current - previous;
/*
* The check for pitch is the same we did before. It is much simpler since the rotation does not need
* to be expressed in the likes of a circle since it is clamped normally from the client. So the method is
* not as complex in comparison to the one we have for yaw. However, this should work fine as mentioned.
*/
result = distance > 0 ? 1 : -1;
}
return result;
}
/*
* This is an attempt to reverse the logistics of cinematic camera without having to run a full on prediction using
* mouse filters. Otherwise, we would need to run more heavy calculations which is not really production friendly.
* It may be more accurate but it is not really worth it if in the end of the day we're eating server performance.
*/
public static double getGrid(final List<Float> entry) {
/*
* We're creating the variables average min and max to start calculating the possibility of cinematic camera.
* Why does this work? Cinematic camera is essentially a slowly increasing slowdown (which is why cinematic camera
* becomes slower the more you use it) which in turn makes it so the min max and average are extremely close together.
*/
double average = 0.0;
double min = 0.0, max = 0.0;
/*
* These are simple min max calculations done manually for the sake of simplicity. We're using the numbers 0.0
* since we also want to account for the possibility of a negative number. If there are no negative numbers then
* there is absolutely no need for us to care about that number other than getting the max.
*/
for (final double number : entry) {
if (number < min) min = number;
if (number > max) max = number;
/*
* Instead of having a sum variable we can use an average variable which we divide
* right after the loop is over. Smart programming trick if you want to use it.
*/
average += number;
}
/*
* We're dividing the average by the length since this is the formula to getting the average.
* Specifically its (sum(n) / length(n)) = average(n) -- with n being the entry set we're analyzing.
*/
average /= entry.size();
/*
* This is going to estimate how close the average and the max were together with the possibility of a min
* variable which is going to represent a negative variable since the preset variable on min is 0.0.
*/
return (max - average) - min;
}
public enum InverseType {
YAW,
PITCH
}
}
@@ -26,6 +26,13 @@ public class MathUtils {
return playerMoved(from.toVector(), to.toVector());
}
public static float gcdSmall(float current, float previous) {
if(current < previous) return gcdSmall(Math.abs(previous), Math.abs(current));
//The larger number has to be first.
return (Math.abs(previous) <= 0.001f) ? current : gcdSmall(previous,
current - (float)Math.floor(current / previous) * previous);
}
public static double getDistanceWithoutRoot(KLocation one, KLocation two) {
double deltaX = one.x - two.x, deltaY = one.y - two.y, deltaZ = one.z - two.z;
@@ -10,7 +10,7 @@ public class TickTimer implements Timer {
public TickTimer(long defaultPassed) {
this.defaultPassed = defaultPassed;
currentStamp = Anticheat.INSTANCE.getCurrentTick();
currentStamp = Anticheat.INSTANCE.getKeepaliveProcessor().tick;
}
public TickTimer() {
@@ -49,7 +49,7 @@ public class TickTimer implements Timer {
@Override
public long getPassed() {
return Anticheat.INSTANCE.getCurrentTick()- currentStamp;
return Anticheat.INSTANCE.getKeepaliveProcessor().tick - currentStamp;
}
@Override
@@ -62,6 +62,6 @@ public class TickTimer implements Timer {
if(getPassed() <= 1) resetStreak++;
else resetStreak = 0;
currentStamp = Anticheat.INSTANCE.getCurrentTick();
currentStamp = Anticheat.INSTANCE.getKeepaliveProcessor().tick;
}
}