mirror of
https://github.com/funkemunky/KauriV3.git
synced 2026-05-31 05:51:55 +00:00
New Speed check and lots of new stuff implemented
This commit is contained in:
@@ -58,7 +58,13 @@
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>com.google.common</pattern>
|
||||
<shadedPattern>dev.brighten.ac.com.google.common</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
@@ -103,6 +109,12 @@
|
||||
<version>8.5.6</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>31.1-jre</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm</artifactId>
|
||||
|
||||
@@ -2,28 +2,35 @@ package dev.brighten.ac;
|
||||
|
||||
import co.aikar.commands.BaseCommand;
|
||||
import co.aikar.commands.BukkitCommandManager;
|
||||
import dev.brighten.ac.check.CheckManager;
|
||||
import dev.brighten.ac.data.PlayerRegistry;
|
||||
import dev.brighten.ac.handler.PacketHandler;
|
||||
import dev.brighten.ac.handler.keepalive.KeepaliveProcessor;
|
||||
import dev.brighten.ac.packet.handler.HandlerAbstract;
|
||||
import dev.brighten.ac.packet.listener.PacketProcessor;
|
||||
import dev.brighten.ac.utils.*;
|
||||
import dev.brighten.ac.utils.math.RollingAverageDouble;
|
||||
import dev.brighten.ac.utils.objects.RemoteClassLoader;
|
||||
import dev.brighten.ac.utils.reflections.Reflections;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedClass;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedField;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedMethod;
|
||||
import dev.brighten.ac.utils.timer.Timer;
|
||||
import dev.brighten.ac.utils.timer.impl.TickTimer;
|
||||
import lombok.Getter;
|
||||
import lombok.experimental.PackagePrivate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
@Getter
|
||||
@Init
|
||||
@@ -34,7 +41,18 @@ public class Anticheat extends JavaPlugin {
|
||||
private ScheduledExecutorService scheduler;
|
||||
private PacketProcessor packetProcessor;
|
||||
private BukkitCommandManager commandManager;
|
||||
private int currentTicks;
|
||||
private CheckManager checkManager;
|
||||
private PlayerRegistry playerRegistry;
|
||||
private KeepaliveProcessor keepaliveProcessor;
|
||||
private PacketHandler packetHandler;
|
||||
private int currentTick;
|
||||
private Deque<Runnable> onTickEnd = new LinkedList<>();
|
||||
private ServerInjector injector;
|
||||
//Lag Information
|
||||
private Timer lastTickLag;
|
||||
private long lastTick;
|
||||
@PackagePrivate
|
||||
private RollingAverageDouble tps = new RollingAverageDouble(4, 20);
|
||||
|
||||
@ConfigSetting(path = "logging", name = "verbose")
|
||||
private static boolean verboseLogging = true;
|
||||
@@ -48,23 +66,43 @@ public class Anticheat extends JavaPlugin {
|
||||
|
||||
commandManager = new BukkitCommandManager(this);
|
||||
|
||||
this.checkManager = new CheckManager();
|
||||
this.playerRegistry = new PlayerRegistry();
|
||||
this.keepaliveProcessor = new KeepaliveProcessor();
|
||||
this.packetHandler = new PacketHandler();
|
||||
|
||||
injector = new ServerInjector();
|
||||
try {
|
||||
injector.inject();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
initializeScanner(getClass(), this,
|
||||
null,
|
||||
true,
|
||||
true);
|
||||
|
||||
new BukkitRunnable() {
|
||||
public void run() {
|
||||
currentTicks++;
|
||||
}
|
||||
}.runTaskTimer(this, 1L, 1L);
|
||||
}
|
||||
|
||||
public void onDisable() {
|
||||
scheduler.shutdown();
|
||||
commandManager.unregisterCommands();
|
||||
|
||||
// Unregistering packet listeners for players
|
||||
Bukkit.getOnlinePlayers().forEach(HandlerAbstract.getHandler()::remove);
|
||||
|
||||
HandlerList.unregisterAll(this);
|
||||
packetProcessor.shutdown();
|
||||
checkManager = null;
|
||||
|
||||
// Unregistering APlayer objects
|
||||
playerRegistry.unregisterAll();
|
||||
playerRegistry = null;
|
||||
try {
|
||||
injector.eject();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void initializeScanner(Class<? extends Plugin> mainClass, Plugin plugin, ClassLoader loader,
|
||||
@@ -193,4 +231,33 @@ public class Anticheat extends JavaPlugin {
|
||||
else MiscUtils.printToConsole(log);
|
||||
}
|
||||
}
|
||||
|
||||
public double getTps() {
|
||||
return this.tps.getAverage();
|
||||
}
|
||||
|
||||
public void runTpsTask() {
|
||||
lastTickLag = new TickTimer();
|
||||
AtomicInteger ticks = new AtomicInteger();
|
||||
AtomicLong lastTimeStamp = new AtomicLong(0);
|
||||
RunUtils.taskTimer(() -> {
|
||||
ticks.getAndIncrement();
|
||||
currentTick++;
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
if(currentTime - lastTick > 120) {
|
||||
lastTickLag.reset();
|
||||
}
|
||||
if(ticks.get() >= 10) {
|
||||
ticks.set(0);
|
||||
tps.add(500D / (currentTime - lastTimeStamp.get()) * 20);
|
||||
lastTimeStamp.set(currentTime);
|
||||
}
|
||||
lastTick = currentTime;
|
||||
}, this, 1L, 1L);
|
||||
}
|
||||
|
||||
public void onTickEnd(Runnable runnable) {
|
||||
onTickEnd.add(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package dev.brighten.ac.check;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Action {
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package dev.brighten.ac.check;
|
||||
|
||||
import dev.brighten.ac.Anticheat;
|
||||
import dev.brighten.ac.data.APlayer;
|
||||
import dev.brighten.ac.utils.Color;
|
||||
import dev.brighten.ac.utils.MathUtils;
|
||||
import dev.brighten.ac.utils.MiscUtils;
|
||||
import dev.brighten.ac.utils.timer.Timer;
|
||||
import dev.brighten.ac.utils.timer.impl.MillisTimer;
|
||||
import lombok.Getter;
|
||||
import lombok.val;
|
||||
import net.md_5.bungee.api.chat.HoverEvent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
public abstract class Check {
|
||||
|
||||
private final APlayer player;
|
||||
|
||||
private final CheckData checkData;
|
||||
private int vl;
|
||||
private long lastFlagRun;
|
||||
private Timer lastAlert = new MillisTimer();
|
||||
|
||||
public Check(APlayer player) {
|
||||
this.player = player;
|
||||
this.checkData = getClass().getAnnotation(CheckData.class);
|
||||
}
|
||||
|
||||
private String formatAlert(String toFormat, String info) {
|
||||
return addPlaceHolders(Color.translate(toFormat.replace("%desc%", String.join("\n",
|
||||
MiscUtils
|
||||
.splitIntoLine("", 20))))
|
||||
.replace("%info%", info));
|
||||
}
|
||||
|
||||
private String addPlaceHolders(String string) {
|
||||
return string.replace("%player%", player.getBukkitPlayer().getName())
|
||||
.replace("%check%", checkData.name())
|
||||
.replace("%name%", player.getBukkitPlayer().getName())
|
||||
.replace("%vl%", String.valueOf(MathUtils.round(vl, 1)));
|
||||
}
|
||||
|
||||
public void flag(boolean devAlerts, int resetVLTime, String information, Object... variables) {
|
||||
vl++;
|
||||
Anticheat.INSTANCE.getScheduler().execute(() -> {
|
||||
if(Anticheat.INSTANCE.getTps() < 18)
|
||||
vl = 0;
|
||||
|
||||
if(System.currentTimeMillis() - lastFlagRun < 50L) return;
|
||||
lastFlagRun = System.currentTimeMillis();
|
||||
|
||||
final String finalInformation = String.format(information, variables);
|
||||
|
||||
boolean dev = devAlerts || Anticheat.INSTANCE.getTps() < 18;
|
||||
final String info = finalInformation
|
||||
.replace("%p", String.valueOf(player.getLagInfo().getTransPing()))
|
||||
.replace("%t", String.valueOf(MathUtils.round(Anticheat.INSTANCE.getTps(), 2)));
|
||||
//if(vl > 0) Anticheat.INSTANCE.loggerManager.addLog(player, this, info);
|
||||
|
||||
if (true) {
|
||||
//Sending Discord webhook alert
|
||||
|
||||
List<TextComponent> components = new ArrayList<>();
|
||||
|
||||
if(dev) {
|
||||
components.add(new TextComponent(createTxt("&8[&cDev&8] ")));
|
||||
}
|
||||
val text = createTxt("&8[&4!&8] &f%player% &7flagged &f%check%" +
|
||||
" &8(&ex%vl%&8)", info);
|
||||
|
||||
text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponent[] {
|
||||
createTxt("&eDescription&8: &f%desc%" +
|
||||
"\n&eInfo: &f%info%\n&r\n&7&oClick to teleport to player.", info)}));
|
||||
|
||||
components.add(text);
|
||||
|
||||
TextComponent[] toSend = components.toArray(new TextComponent[0]);
|
||||
|
||||
player.getBukkitPlayer().spigot().sendMessage(toSend);
|
||||
lastAlert.reset();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private TextComponent createTxt(String txt) {
|
||||
return createTxt(txt, "");
|
||||
}
|
||||
private TextComponent createTxt(String txt, String info) {
|
||||
return new TextComponent(TextComponent.fromLegacyText(Color.translate(formatAlert(txt, info))));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dev.brighten.ac.check;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CheckData {
|
||||
String name();
|
||||
CheckType type();
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package dev.brighten.ac.check;
|
||||
|
||||
import dev.brighten.ac.Anticheat;
|
||||
import dev.brighten.ac.utils.ClassScanner;
|
||||
import dev.brighten.ac.utils.Tuple;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedClass;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedMethod;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Getter
|
||||
public class CheckManager {
|
||||
private final List<CheckStatic> checkClasses = new ArrayList<>();
|
||||
private final Map<Tuple<String, Class<?>>, WrappedMethod[]> events = new HashMap<>();
|
||||
|
||||
public CheckManager() {
|
||||
for (WrappedClass aClass : ClassScanner.getClasses(CheckData.class,
|
||||
"dev.brighten.ac.check.impl")) {
|
||||
addCheck(aClass);
|
||||
}
|
||||
}
|
||||
|
||||
public void addCheck(WrappedClass checkClass) {
|
||||
CheckStatic check = new CheckStatic(checkClass);
|
||||
|
||||
if(!check.getCheckClass().isAnnotationPresent(CheckData.class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CheckData checkData = check.getCheckClass().getAnnotation(CheckData.class);
|
||||
|
||||
Anticheat.INSTANCE.alog(true, "&7Adding check to CheckManager: " + checkData.name());
|
||||
|
||||
synchronized (events) {
|
||||
// Loop through all the methods in Check that contain @Action annotation by Class
|
||||
check.getEvents().forEach((actionClass, methods) -> {
|
||||
// Check if array is already cached for Class and return Array if so, if not create new Array
|
||||
events.compute(new Tuple<String, Class<?>>(checkData.name(), actionClass), (packetClass, array) -> {
|
||||
if(array == null) array = new WrappedMethod[0];
|
||||
|
||||
// Adding preexisting cached WrappedMethod into List for further additions
|
||||
List<WrappedMethod> methodList = new ArrayList<>(Arrays.asList(array));
|
||||
|
||||
// Adding all precached Check-specific WrappedMethod into global cache of WrappedMethods.
|
||||
methodList.addAll(methods);
|
||||
|
||||
System.out.println("Registering " + packetClass.toString());
|
||||
|
||||
// Returning newly created array for use in detections.
|
||||
return methodList.toArray(new WrappedMethod[0]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
checkClasses.add(check);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package dev.brighten.ac.check;
|
||||
|
||||
import dev.brighten.ac.data.APlayer;
|
||||
import dev.brighten.ac.packet.wrapper.WPacket;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedClass;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedConstructor;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedMethod;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.server.v1_8_R3.Packet;
|
||||
import org.bukkit.event.Event;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CheckStatic {
|
||||
@Getter
|
||||
private final WrappedClass checkClass;
|
||||
private WrappedConstructor initConst;
|
||||
@Getter
|
||||
private final Map<Class<?>, List<WrappedMethod>> events = new HashMap<>();
|
||||
|
||||
public CheckStatic(WrappedClass checkClass) {
|
||||
this.checkClass = checkClass;
|
||||
processClass();
|
||||
}
|
||||
|
||||
private void processClass() {
|
||||
initConst = checkClass.getConstructor(APlayer.class);
|
||||
for (WrappedMethod method : checkClass.getDeclaredMethods()) {
|
||||
if(!method.isAnnotationPresent(Action.class)
|
||||
|| method.getParameters().length == 0) continue;
|
||||
Class<?> type = method.getParameterTypes()[0];
|
||||
|
||||
if(Packet.class.isAssignableFrom(type)
|
||||
|| WPacket.class.isAssignableFrom(type) || Event.class.isAssignableFrom(type)) {
|
||||
events.compute(type, (key, list) -> {
|
||||
if(list == null) list = new ArrayList<>();
|
||||
|
||||
list.add(method);
|
||||
return list;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Check playerInit(APlayer player) {
|
||||
return initConst.newInstance(player);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.brighten.ac.check;
|
||||
|
||||
public enum CheckType {
|
||||
COMBAT,
|
||||
MOVEMENT,
|
||||
BLOCK,
|
||||
INTERACT,
|
||||
ORDER
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.brighten.ac.check.impl.join;
|
||||
|
||||
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 org.bukkit.Bukkit;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
|
||||
@CheckData(name = "Join", type = CheckType.ORDER)
|
||||
public class JoinCheck extends Check {
|
||||
public JoinCheck(APlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Action
|
||||
public void onJoin(PlayerJoinEvent event) {
|
||||
Bukkit.broadcastMessage("Player joined server: " + getPlayer().getBukkitPlayer().getName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
package dev.brighten.ac.check.impl.speed;
|
||||
|
||||
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.ProtocolVersion;
|
||||
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
|
||||
import dev.brighten.ac.utils.BlockUtils;
|
||||
import dev.brighten.ac.utils.MathHelper;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.util.CraftMagicNumbers;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
@CheckData(name = "Speed", type = CheckType.MOVEMENT)
|
||||
public class Speed extends Check {
|
||||
private boolean lastLastClientGround;
|
||||
private float buffer;
|
||||
|
||||
private static boolean[] TRUE_FALSE = new boolean[]{true, false};
|
||||
private static float[] VALUES = new float[]{-0.98f, 0f, 0.98f};
|
||||
|
||||
public Speed(APlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Action
|
||||
public void onFlying(WPacketPlayInFlying packet) {
|
||||
|
||||
Block underBlock = BlockUtils.getBlock(getPlayer().getMovement().getTo().getLoc()
|
||||
.toLocation(getPlayer().getBukkitPlayer().getWorld())
|
||||
.subtract(0, 1, 0)),
|
||||
lastUnderBlock = BlockUtils.getBlock(getPlayer().getMovement().getFrom().getLoc()
|
||||
.toLocation(getPlayer().getBukkitPlayer().getWorld())
|
||||
.subtract(0, 1, 0));
|
||||
|
||||
if (underBlock == null || lastUnderBlock == null) {
|
||||
getPlayer().getBukkitPlayer().sendMessage("Null");
|
||||
return;
|
||||
}
|
||||
|
||||
float friction = CraftMagicNumbers.getBlock(underBlock).frictionFactor,
|
||||
lfriction = CraftMagicNumbers.getBlock(lastUnderBlock).frictionFactor;
|
||||
|
||||
check:
|
||||
{
|
||||
if (!packet.isMoved()
|
||||
/*|| getPlayer().playerInfo.generalCancel
|
||||
|| getPlayer().playerInfo.onLadder
|
||||
|| getPlayer().playerInfo.lastEntityCollision.isNotPassed(2)
|
||||
|| getPlayer().playerInfo.lastVelocity.isNotPassed(1)*/
|
||||
|| getPlayer().getBlockInformation().inLiquid
|
||||
|| getPlayer().getBlockInformation().collidesHorizontally) {
|
||||
break check;
|
||||
}
|
||||
double smallestDelta = Double.MAX_VALUE;
|
||||
|
||||
double pmotionx = 0, pmotionz = 0;
|
||||
boolean onGround = getPlayer().getMovement().getFrom().isOnGround();
|
||||
loop:
|
||||
{
|
||||
for (int f = -1; f < 2; f++) {
|
||||
for (int s = -1; s < 2; s++) {
|
||||
for (boolean sprinting : TRUE_FALSE) {
|
||||
for (int fastMath = 0; fastMath <= 2; fastMath++) {
|
||||
for (boolean attack : TRUE_FALSE) {
|
||||
for (boolean using : TRUE_FALSE) {
|
||||
for (boolean sneaking : TRUE_FALSE) {
|
||||
for (boolean jumped : TRUE_FALSE) {
|
||||
|
||||
float forward = f, strafe = s;
|
||||
|
||||
if (sneaking) {
|
||||
forward *= 0.3;
|
||||
strafe *= 0.3;
|
||||
}
|
||||
|
||||
if (using) {
|
||||
forward *= 0.2;
|
||||
strafe *= 0.2;
|
||||
}
|
||||
|
||||
//Multiplying by 0.98 like in client
|
||||
forward *= 0.9800000190734863F;
|
||||
strafe *= 0.9800000190734863F;
|
||||
|
||||
double aiMoveSpeed = getPlayer().getBukkitPlayer().getWalkSpeed() / 2;
|
||||
|
||||
float drag = 0.91f;
|
||||
double lmotionX = getPlayer().getMovement().getLDeltaX(),
|
||||
lmotionZ = getPlayer().getMovement().getLDeltaZ();
|
||||
|
||||
//The "1" will effectively remove lastFriction from the equation
|
||||
lmotionX *= (lastLastClientGround ? lfriction : 1) * 0.9100000262260437D;
|
||||
lmotionZ *= (lastLastClientGround ? lfriction : 1) * 0.9100000262260437D;
|
||||
|
||||
//Running multiplication done after previous prediction
|
||||
if (getPlayer().getPlayerVersion().isOrAbove(ProtocolVersion.V1_9)) {
|
||||
if (Math.abs(lmotionX) < 0.003)
|
||||
lmotionX = 0;
|
||||
if (Math.abs(lmotionZ) < 0.003)
|
||||
lmotionZ = 0;
|
||||
} else {
|
||||
if (Math.abs(lmotionX) < 0.005)
|
||||
lmotionX = 0;
|
||||
if (Math.abs(lmotionZ) < 0.005)
|
||||
lmotionZ = 0;
|
||||
}
|
||||
|
||||
// Attack slowdown
|
||||
if (attack) {
|
||||
lmotionX *= 0.6;
|
||||
lmotionZ *= 0.6;
|
||||
}
|
||||
|
||||
if (sprinting) aiMoveSpeed += aiMoveSpeed * 0.30000001192092896D;
|
||||
|
||||
if (getPlayer().getPotionHandler().hasPotionEffect(PotionEffectType.SPEED))
|
||||
aiMoveSpeed += (getPlayer().getPotionHandler().getEffectByType(PotionEffectType.SPEED)
|
||||
.get()
|
||||
.getAmplifier() + 1) * (double) 0.20000000298023224D * aiMoveSpeed;
|
||||
if (getPlayer().getPotionHandler().hasPotionEffect(PotionEffectType.SLOW))
|
||||
aiMoveSpeed += (getPlayer().getPotionHandler().getEffectByType(PotionEffectType.SLOW)
|
||||
.get()
|
||||
.getAmplifier() + 1) * (double) -0.15000000596046448D * aiMoveSpeed;
|
||||
|
||||
float f5;
|
||||
if (onGround) {
|
||||
drag *= friction;
|
||||
|
||||
f5 = (float) (aiMoveSpeed * (0.16277136F / (drag * drag * drag)));
|
||||
|
||||
if (sprinting && jumped) {
|
||||
float rot = getPlayer().getMovement().getTo().getLoc().yaw * 0.017453292F;
|
||||
lmotionX -= sin(fastMath, rot) * 0.2F;
|
||||
lmotionZ += cos(fastMath, rot) * 0.2F;
|
||||
}
|
||||
|
||||
} else f5 = sprinting ? 0.025999999F : 0.02f;
|
||||
|
||||
if (getPlayer().getPlayerVersion().isOrAbove(ProtocolVersion.V1_9)) {
|
||||
double keyedMotion = forward * forward + strafe * strafe;
|
||||
|
||||
if (keyedMotion >= 1.0E-4F) {
|
||||
keyedMotion = f5 / Math.max(1.0, Math.sqrt(keyedMotion));
|
||||
forward *= keyedMotion;
|
||||
strafe *= keyedMotion;
|
||||
|
||||
final float yawSin = sin(fastMath,
|
||||
getPlayer().getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F),
|
||||
yawCos = cos(fastMath,
|
||||
getPlayer().getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F);
|
||||
|
||||
lmotionX += (strafe * yawCos - forward * yawSin);
|
||||
lmotionZ += (forward * yawCos + strafe * yawSin);
|
||||
}
|
||||
} else {
|
||||
float keyedMotion = forward * forward + strafe * strafe;
|
||||
|
||||
if (keyedMotion >= 1.0E-4F) {
|
||||
keyedMotion = f5 / Math.max(1.0f, MathHelper.sqrt_float(keyedMotion));
|
||||
forward *= keyedMotion;
|
||||
strafe *= keyedMotion;
|
||||
|
||||
final float yawSin = sin(fastMath,
|
||||
getPlayer().getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F),
|
||||
yawCos = cos(fastMath,
|
||||
getPlayer().getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F);
|
||||
|
||||
lmotionX += (strafe * yawCos - forward * yawSin);
|
||||
lmotionZ += (forward * yawCos + strafe * yawSin);
|
||||
}
|
||||
}
|
||||
|
||||
double diffX = getPlayer().getMovement().getDeltaX() - lmotionX,
|
||||
diffZ = getPlayer().getMovement().getDeltaZ() - lmotionZ;
|
||||
double delta = (diffX * diffX) + (diffZ * diffZ);
|
||||
|
||||
if (delta < smallestDelta) {
|
||||
smallestDelta = delta;
|
||||
pmotionx = lmotionX;
|
||||
pmotionz = lmotionZ;
|
||||
|
||||
if (delta < 1E-15) {
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double pmotion = Math.hypot(pmotionx, pmotionz);
|
||||
|
||||
if (getPlayer().getMovement().getDeltaXZ() > pmotion && smallestDelta > 1E-4 && getPlayer().getMovement().getDeltaXZ() > 0.1) {
|
||||
if (++buffer > 3) {
|
||||
buffer = Math.min(3.5f, buffer); //Ensuring we don't have a run-away buffer
|
||||
flag(false,0, "smallest=%s b=%.1f to=%s dxz=%.2f", smallestDelta, buffer, getPlayer().getMovement().getTo().getLoc(), getPlayer().getMovement().getDeltaXZ());
|
||||
}
|
||||
} else if (buffer > 0) buffer -= 0.1f;
|
||||
|
||||
//getPlayer().getBukkitPlayer().sendMessage(String.format("smallest=%s b=%.1f to=%s dxz=%.2f", smallestDelta, buffer, getPlayer().getMovement().getTo().getLoc(), getPlayer().getMovement().getDeltaXZ()));
|
||||
|
||||
//debug("smallest=%s b=%.1f", smallestDelta, buffer);
|
||||
}
|
||||
lastLastClientGround = getPlayer().getMovement().getFrom().isOnGround();
|
||||
}
|
||||
|
||||
private static final float[] SIN_TABLE_FAST = new float[4096], SIN_TABLE_FAST_NEW = new float[4096];
|
||||
private static final float[] SIN_TABLE = new float[65536];
|
||||
private static final float radToIndex = roundToFloat(651.8986469044033D);
|
||||
|
||||
public static float sin(int type, float value) {
|
||||
switch(type) {
|
||||
case 0:
|
||||
default: {
|
||||
return SIN_TABLE[(int) (value * 10430.378F) & 65535];
|
||||
}
|
||||
case 1: {
|
||||
return SIN_TABLE_FAST[(int) (value * 651.8986F) & 4095];
|
||||
}
|
||||
case 2: {
|
||||
return SIN_TABLE_FAST_NEW[(int)(value * radToIndex) & 4095];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static float cos(int type, float value) {
|
||||
switch (type) {
|
||||
case 0:
|
||||
default:
|
||||
return SIN_TABLE[(int) (value * 10430.378F + 16384.0F) & 65535];
|
||||
case 1:
|
||||
return SIN_TABLE_FAST[(int) ((value + ((float) Math.PI / 2F)) * 651.8986F) & 4095];
|
||||
case 2:
|
||||
return SIN_TABLE_FAST_NEW[(int)(value * radToIndex + 1024.0F) & 4095];
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
for (int i = 0; i < 65536; ++i)
|
||||
{
|
||||
SIN_TABLE[i] = (float)Math.sin((double)i * Math.PI * 2.0D / 65536.0D);
|
||||
}
|
||||
|
||||
for (int j = 0; j < 4096; ++j)
|
||||
{
|
||||
SIN_TABLE_FAST[j] = (float)Math.sin((double)(((float)j + 0.5F) / 4096.0F * ((float)Math.PI * 2F)));
|
||||
}
|
||||
|
||||
for (int l = 0; l < 360; l += 90)
|
||||
{
|
||||
SIN_TABLE_FAST[(int)((float)l * 11.377778F) & 4095] = (float)Math.sin((double)((float)l * 0.017453292F));
|
||||
}
|
||||
|
||||
for (int j = 0; j < SIN_TABLE_FAST_NEW.length; ++j)
|
||||
{
|
||||
SIN_TABLE_FAST_NEW[j] = roundToFloat(Math.sin((double)j * Math.PI * 2.0D / 4096.0D));
|
||||
}
|
||||
}
|
||||
|
||||
private static float roundToFloat(double d)
|
||||
{
|
||||
return (float)((double)Math.round(d * 1.0E8D) / 1.0E8D);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package dev.brighten.ac.data;
|
||||
|
||||
import dev.brighten.ac.Anticheat;
|
||||
import dev.brighten.ac.check.Check;
|
||||
import dev.brighten.ac.check.CheckStatic;
|
||||
import dev.brighten.ac.data.handlers.BlockInformation;
|
||||
import dev.brighten.ac.data.handlers.GeneralInformation;
|
||||
import dev.brighten.ac.data.handlers.LagInformation;
|
||||
import dev.brighten.ac.data.handlers.MovementHandler;
|
||||
import dev.brighten.ac.data.obj.InstantAction;
|
||||
import dev.brighten.ac.data.obj.NormalAction;
|
||||
import dev.brighten.ac.handler.PotionHandler;
|
||||
import dev.brighten.ac.handler.keepalive.KeepAlive;
|
||||
import dev.brighten.ac.packet.ProtocolVersion;
|
||||
import dev.brighten.ac.packet.handler.HandlerAbstract;
|
||||
import dev.brighten.ac.utils.Tuple;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedMethod;
|
||||
import lombok.Getter;
|
||||
import lombok.val;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayOutTransaction;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
||||
public class APlayer {
|
||||
@Getter
|
||||
private final Player bukkitPlayer;
|
||||
private final List<Check> checks = new ArrayList<>();
|
||||
@Getter
|
||||
private MovementHandler movement;
|
||||
@Getter
|
||||
private PotionHandler potionHandler;
|
||||
@Getter
|
||||
private GeneralInformation info;
|
||||
@Getter
|
||||
private LagInformation lagInfo;
|
||||
@Getter
|
||||
private BlockInformation blockInformation;
|
||||
@Getter
|
||||
private int playerTick;
|
||||
@Getter
|
||||
//TODO Actually grab real player version once finished implementing version grabber from Atlas
|
||||
private ProtocolVersion playerVersion = ProtocolVersion.V1_8_9;
|
||||
|
||||
public final Map<Short, Tuple<InstantAction, Consumer<InstantAction>>> instantTransaction = new HashMap<>();
|
||||
public final List<NormalAction> keepAliveStamps = new ArrayList<>();
|
||||
|
||||
public APlayer(Player player) {
|
||||
this.bukkitPlayer = player;
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
for (CheckStatic check : Anticheat.INSTANCE.getCheckManager().getCheckClasses()) {
|
||||
checks.add(check.playerInit(this));
|
||||
}
|
||||
this.movement = new MovementHandler(this);
|
||||
this.potionHandler = new PotionHandler(this);
|
||||
this.info = new GeneralInformation();
|
||||
this.lagInfo = new LagInformation();
|
||||
this.blockInformation = new BlockInformation(this);
|
||||
}
|
||||
|
||||
protected void unload() {
|
||||
checks.clear();
|
||||
this.info = null;
|
||||
this.lagInfo = null;
|
||||
this.movement = null;
|
||||
}
|
||||
|
||||
public void callEvent(Event event) {
|
||||
for (Check check : checks) {
|
||||
WrappedMethod[] methods = Anticheat.INSTANCE.getCheckManager().getEvents()
|
||||
.get(new Tuple<String, Class<?>>(check.getCheckData().name(), event.getClass()));
|
||||
|
||||
if(methods != null) {
|
||||
for (WrappedMethod method : methods) {
|
||||
method.invoke(check, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO When using WPacket wrappers only, make this strictly WPacket param based only
|
||||
public void callPacket(Object packet) {
|
||||
for (Check check : checks) {
|
||||
WrappedMethod[] methods = Anticheat.INSTANCE.getCheckManager().getEvents()
|
||||
.get(new Tuple<String, Class<?>>(check.getCheckData().name(), packet.getClass()));
|
||||
|
||||
if(methods != null) {
|
||||
|
||||
for (WrappedMethod method :
|
||||
methods) {
|
||||
method.invoke(check, packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int runKeepaliveAction(Consumer<KeepAlive> action) {
|
||||
return runKeepaliveAction(action, 0);
|
||||
}
|
||||
|
||||
public int runKeepaliveAction(Consumer<KeepAlive> action, int later) {
|
||||
int id = Anticheat.INSTANCE.getKeepaliveProcessor().currentKeepalive.start + later;
|
||||
|
||||
keepAliveStamps.add(new NormalAction(id, action));
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
public void runInstantAction(Consumer<InstantAction> runnable) {
|
||||
runInstantAction(runnable, false);
|
||||
}
|
||||
|
||||
public void runInstantAction(Consumer<InstantAction> runnable, boolean flush) {
|
||||
short startId = (short) ThreadLocalRandom.current().nextInt(Short.MIN_VALUE, Short.MAX_VALUE),
|
||||
endId = (short)(startId + 1);
|
||||
|
||||
//Ensuring we don't have any duplicate IDS
|
||||
val map = Anticheat.INSTANCE.getKeepaliveProcessor().keepAlives.asMap();
|
||||
while (map.containsKey(startId)
|
||||
|| map.containsKey(endId)) {
|
||||
startId = (short) ThreadLocalRandom.current().nextInt(Short.MIN_VALUE, Short.MAX_VALUE);
|
||||
endId = (short)(startId + (short)1);
|
||||
}
|
||||
|
||||
InstantAction startAction = new InstantAction(startId, endId, false);
|
||||
instantTransaction.put(startId, new Tuple<>(startAction, runnable));
|
||||
|
||||
HandlerAbstract.getHandler().sendPacket(this, new PacketPlayOutTransaction(0, startId, false));
|
||||
|
||||
short finalEndId = endId, finalStartId = startId;
|
||||
Anticheat.INSTANCE.onTickEnd(() -> {
|
||||
InstantAction endAction = new InstantAction(finalStartId, finalEndId, true);
|
||||
instantTransaction.put(finalEndId, new Tuple<>(endAction, runnable));
|
||||
|
||||
HandlerAbstract.getHandler()
|
||||
.sendPacket(this, new PacketPlayOutTransaction(0, finalEndId, false));
|
||||
});
|
||||
}
|
||||
|
||||
public void addPlayerTick() {
|
||||
playerTick++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package dev.brighten.ac.data;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PlayerRegistry {
|
||||
|
||||
public PlayerRegistry() {
|
||||
Bukkit.getOnlinePlayers().forEach(this::generate);
|
||||
}
|
||||
public final Int2ObjectMap<APlayer> aplayerMap = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>());
|
||||
|
||||
public Optional<APlayer> getPlayer(UUID uuid) {
|
||||
return Optional.of(aplayerMap.get(uuid.hashCode()));
|
||||
}
|
||||
|
||||
public APlayer generate(Player player) {
|
||||
if(aplayerMap.containsKey(player.getUniqueId().hashCode())) {
|
||||
unregister(player.getUniqueId());
|
||||
}
|
||||
|
||||
synchronized (aplayerMap) {
|
||||
APlayer aplayer = new APlayer(player);
|
||||
aplayerMap.put(player.getUniqueId().hashCode(), aplayer);
|
||||
return aplayer;
|
||||
}
|
||||
}
|
||||
|
||||
public void unregister(UUID uuid) {
|
||||
synchronized (aplayerMap) {
|
||||
Optional.of(aplayerMap.remove(uuid.hashCode())).ifPresent(APlayer::unload);
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterAll() {
|
||||
synchronized (aplayerMap) {
|
||||
aplayerMap.forEach((key, val) -> val.unload());
|
||||
aplayerMap.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,368 @@
|
||||
package dev.brighten.ac.data.handlers;
|
||||
|
||||
import dev.brighten.ac.Anticheat;
|
||||
import dev.brighten.ac.data.APlayer;
|
||||
import dev.brighten.ac.packet.ProtocolVersion;
|
||||
import dev.brighten.ac.utils.*;
|
||||
import dev.brighten.ac.utils.world.BlockData;
|
||||
import dev.brighten.ac.utils.world.CollisionBox;
|
||||
import dev.brighten.ac.utils.world.EntityData;
|
||||
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
|
||||
public class BlockInformation {
|
||||
private APlayer player;
|
||||
public boolean onClimbable, onSlab, onStairs, onHalfBlock, inLiquid, inLava, inWater, inWeb, onSlime, onIce,
|
||||
onSoulSand, blocksAbove, collidesVertically, bedNear, collidesHorizontally, blocksNear, inBlock, miscNear,
|
||||
collidedWithEntity, roseBush, inPortal, blocksBelow, pistonNear, fenceBelow, inScaffolding, inHoney;
|
||||
public float currentFriction, fromFriction;
|
||||
public CollisionHandler
|
||||
handler = new CollisionHandler(new ArrayList<>(), new ArrayList<>(), new KLocation(0,0,0), null);
|
||||
public final List<SimpleCollisionBox> aboveCollisions = Collections.synchronizedList(new ArrayList<>()),
|
||||
belowCollisions = Collections.synchronizedList(new ArrayList<>());
|
||||
public final List<Block> blocks = Collections.synchronizedList(new ArrayList<>());
|
||||
private static EnumMap<Material, XMaterial> matchMaterial = new EnumMap<>(Material.class);
|
||||
//Caching material
|
||||
private final Material cobweb = XMaterial.COBWEB.parseMaterial(),
|
||||
rosebush = XMaterial.ROSE_BUSH.parseMaterial(),
|
||||
scaffolding = XMaterial.SCAFFOLDING.parseMaterial(),
|
||||
honey = XMaterial.HONEY_BLOCK.parseMaterial();
|
||||
|
||||
static {
|
||||
for (Material mat : Material.values()) {
|
||||
matchMaterial.put(mat, XMaterial.matchXMaterial(mat));
|
||||
}
|
||||
}
|
||||
|
||||
public static XMaterial getXMaterial(Material material) {
|
||||
return matchMaterial.getOrDefault(material, null);
|
||||
}
|
||||
|
||||
public BlockInformation(APlayer objectData) {
|
||||
this.player = objectData;
|
||||
}
|
||||
|
||||
public void runCollisionCheck() {
|
||||
if(!Anticheat.INSTANCE.isEnabled())
|
||||
return;
|
||||
|
||||
double dy = player.getMovement().getDeltaY();
|
||||
double dh = player.getMovement().getDeltaXZ();
|
||||
|
||||
blocks.clear();
|
||||
|
||||
player.getInfo().setServerGround(false);
|
||||
player.getInfo().setNearGround(false);
|
||||
onClimbable = fenceBelow
|
||||
= inScaffolding = inHoney
|
||||
= onSlab = onStairs = onHalfBlock = inLiquid = inLava = inWater = inWeb = onSlime = pistonNear
|
||||
= onIce = onSoulSand = blocksAbove = collidesVertically = bedNear = collidesHorizontally =
|
||||
blocksNear = inBlock = miscNear = collidedWithEntity = blocksBelow = inPortal = false;
|
||||
|
||||
if(dy > 10) dy = 10;
|
||||
else if(dy < -10) dy = -10;
|
||||
if(dh > 10) dh = 10;
|
||||
|
||||
int startX = Location.locToBlock(player.getMovement().getTo().getLoc().x - 1 - dh);
|
||||
int endX = Location.locToBlock(player.getMovement().getTo().getLoc().x + 1 + dh);
|
||||
int startY = Location.locToBlock(player.getMovement().getTo().getLoc().y - Math.max(0.6, 0.6 + Math.abs(dy)));
|
||||
int endY = Location.locToBlock(player.getMovement().getTo().getLoc().y + Math.max(2.1, 2.1 + Math.abs(dy)));
|
||||
int startZ = Location.locToBlock(player.getMovement().getTo().getLoc().z - 1 - dh);
|
||||
int endZ = Location.locToBlock(player.getMovement().getTo().getLoc().z + 1 + dh);
|
||||
|
||||
SimpleCollisionBox waterBox = player.getMovement().getTo().getBox().copy().expand(0, -.38, 0);
|
||||
|
||||
waterBox.xMin = MathHelper.floor_double(waterBox.xMin);
|
||||
waterBox.yMin = MathHelper.floor_double(waterBox.yMin);
|
||||
waterBox.zMin = MathHelper.floor_double(waterBox.zMin);
|
||||
waterBox.xMax = MathHelper.floor_double(waterBox.xMax + 1.);
|
||||
waterBox.yMax = MathHelper.floor_double(waterBox.yMax + 1.);
|
||||
waterBox.zMax = MathHelper.floor_double(waterBox.zMax + 1.);
|
||||
|
||||
SimpleCollisionBox lavaBox = player.getMovement().getTo().getBox().copy().expand(-.1f, -.4f, -.1f);
|
||||
|
||||
lavaBox.xMin = MathHelper.floor_double(waterBox.xMin);
|
||||
lavaBox.yMin = MathHelper.floor_double(waterBox.yMin);
|
||||
lavaBox.zMin = MathHelper.floor_double(waterBox.zMin);
|
||||
lavaBox.xMax = MathHelper.floor_double(waterBox.xMax + 1.);
|
||||
lavaBox.yMax = MathHelper.floor_double(waterBox.yMax + 1.);
|
||||
lavaBox.zMax = MathHelper.floor_double(waterBox.zMax + 1.);
|
||||
|
||||
SimpleCollisionBox normalBox = player.getMovement().getTo().getBox().copy();
|
||||
|
||||
inWater = MiscUtils.isInMaterialBB(player.getBukkitPlayer().getWorld(), waterBox, Materials.WATER);
|
||||
inLava = MiscUtils.isInMaterialBB(player.getBukkitPlayer().getWorld(), lavaBox, Materials.LAVA);
|
||||
inLiquid = inWater || inLava;
|
||||
|
||||
player.getInfo().setWorldLoaded(true);
|
||||
player.getInfo().setLastServerGround(player.getInfo().isServerGround());
|
||||
synchronized (belowCollisions) {
|
||||
belowCollisions.clear();
|
||||
}
|
||||
synchronized (aboveCollisions) {
|
||||
aboveCollisions.clear();
|
||||
}
|
||||
final World world = player.getBukkitPlayer().getWorld();
|
||||
int it = 9 * 9;
|
||||
start:
|
||||
for (int chunkx = startX >> 4; chunkx <= endX >> 4; ++chunkx) {
|
||||
int cx = chunkx << 4;
|
||||
|
||||
for (int chunkz = startZ >> 4; chunkz <= endZ >> 4; ++chunkz) {
|
||||
if (!world.isChunkLoaded(chunkx, chunkz)) {
|
||||
player.getInfo().setWorldLoaded(false);
|
||||
continue;
|
||||
}
|
||||
Chunk chunk = world.getChunkAt(chunkx, chunkz);
|
||||
if (chunk != null) {
|
||||
int cz = chunkz << 4;
|
||||
int xstart = Math.max(startX, cx);
|
||||
int xend = Math.min(endX, cx + 16);
|
||||
int zstart = Math.max(startZ, cz);
|
||||
int zend = Math.min(endZ, cz + 16);
|
||||
|
||||
for (int x = xstart; x <= xend; ++x) {
|
||||
for (int z = zstart; z <= zend; ++z) {
|
||||
for (int y = Math.max(-50, startY); y <= endY; ++y) {
|
||||
if (it-- <= 0) {
|
||||
break start;
|
||||
}
|
||||
if(y > 400 || y < -50) continue;
|
||||
Block block = chunk.getBlock(x & 15, y, z & 15);
|
||||
final Material type = block.getType();
|
||||
if (type != Material.AIR) {
|
||||
blocks.add(block);
|
||||
|
||||
CollisionBox blockBox = BlockData.getData(type)
|
||||
.getBox(block, player.getPlayerVersion());
|
||||
|
||||
if(blockBox.isCollided(normalBox)) {
|
||||
if(type.equals(cobweb))
|
||||
inWeb = true;
|
||||
else if(type.equals(scaffolding)) inScaffolding = true;
|
||||
else if(type.equals(honey)) inHoney = true;
|
||||
}
|
||||
|
||||
if(type.equals(rosebush))
|
||||
roseBush = true;
|
||||
|
||||
if(normalBox.copy().offset(0, 0.6f, 0).isCollided(blockBox))
|
||||
blocksAbove = true;
|
||||
|
||||
if(normalBox.copy().expand(1, -0.0001, 1).isIntersected(blockBox))
|
||||
blocksNear = true;
|
||||
|
||||
if(normalBox.copy().expand(0.1, 0, 0.1)
|
||||
.offset(0, 1,0).isCollided(blockBox)) {
|
||||
synchronized (aboveCollisions) {
|
||||
blockBox.downCast(aboveCollisions);
|
||||
}
|
||||
}
|
||||
|
||||
if(normalBox.copy().expand(0.1, 0, 0.1).offset(0, -1, 0)
|
||||
.isCollided(blockBox)) {
|
||||
synchronized (belowCollisions) {
|
||||
blockBox.downCast(belowCollisions);
|
||||
}
|
||||
|
||||
if(Materials.checkFlag(type, Materials.FENCE)
|
||||
|| Materials.checkFlag(type, Materials.WALL)) {
|
||||
fenceBelow = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(Materials.checkFlag(type, Materials.SOLID)) {
|
||||
SimpleCollisionBox groundBox = normalBox.copy()
|
||||
.offset(0, -.49, 0).expandMax(0, -1.2, 0);
|
||||
|
||||
XMaterial blockMaterial = getXMaterial(type);
|
||||
|
||||
if(normalBox.copy().expand(0.4, 0, 0.4).expandMin(0, -1, 0)
|
||||
.isIntersected(blockBox))
|
||||
blocksBelow = true;
|
||||
|
||||
if(normalBox.isIntersected(blockBox)) inBlock = true;
|
||||
|
||||
SimpleCollisionBox box = player.getMovement().getTo().getBox().copy();
|
||||
|
||||
box.expand(Math.abs(player.getMovement().getDeltaX()) + 0.1, -0.001,
|
||||
Math.abs(player.getMovement().getDeltaZ()) + 0.1);
|
||||
if (blockBox.isCollided(box))
|
||||
collidesHorizontally = true;
|
||||
|
||||
box = player.getMovement().getTo().getBox().copy();
|
||||
box.expand(0, 0.1, 0);
|
||||
|
||||
if (blockBox.isCollided(box))
|
||||
collidesVertically = true;
|
||||
|
||||
if(groundBox.copy().expandMin(0, -0.8, 0).expand(0.2, 0, 0.2)
|
||||
.isIntersected(blockBox))
|
||||
player.getInfo().setNearGround(true);
|
||||
|
||||
if(groundBox.isCollided(blockBox)) {
|
||||
player.getInfo().setServerGround(true);
|
||||
|
||||
if(blockMaterial != null)
|
||||
switch (blockMaterial) {
|
||||
case ICE:
|
||||
case BLUE_ICE:
|
||||
case FROSTED_ICE:
|
||||
case PACKED_ICE: {
|
||||
onIce = true;
|
||||
break;
|
||||
}
|
||||
case SOUL_SAND: {
|
||||
onSoulSand = true;
|
||||
break;
|
||||
}
|
||||
case SLIME_BLOCK: {
|
||||
onSlime = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(player.getMovement().getDeltaY() > 0
|
||||
&& player.getPlayerVersion().isBelow(ProtocolVersion.V1_14)
|
||||
&& Materials.checkFlag(type, Materials.LADDER)
|
||||
&& normalBox.copy().expand(0.2f, 0, 0.2f)
|
||||
.isCollided(blockBox)) {
|
||||
onClimbable = true;
|
||||
}
|
||||
|
||||
if(blockMaterial != null) {
|
||||
switch (blockMaterial) {
|
||||
case PISTON:
|
||||
case PISTON_HEAD:
|
||||
case MOVING_PISTON:
|
||||
case STICKY_PISTON: {
|
||||
if(normalBox.copy().expand(0.5, 0.5, 0.5)
|
||||
.isCollided(blockBox))
|
||||
pistonNear = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(groundBox.copy().expand(0.5, 0.3, 0.5).isCollided(blockBox)) {
|
||||
if(Materials.checkFlag(type, Materials.SLABS))
|
||||
onSlab = true;
|
||||
else
|
||||
if(Materials.checkFlag(type, Materials.STAIRS))
|
||||
onStairs = true;
|
||||
else
|
||||
if(blockMaterial != null)
|
||||
switch(blockMaterial) {
|
||||
case CAKE:
|
||||
case BREWING_STAND:
|
||||
case FLOWER_POT:
|
||||
case PLAYER_HEAD:
|
||||
case PLAYER_WALL_HEAD:
|
||||
case SKELETON_SKULL:
|
||||
case CREEPER_HEAD:
|
||||
case DRAGON_HEAD:
|
||||
case ZOMBIE_HEAD:
|
||||
case ZOMBIE_WALL_HEAD:
|
||||
case CREEPER_WALL_HEAD:
|
||||
case DRAGON_WALL_HEAD:
|
||||
case WITHER_SKELETON_SKULL:
|
||||
case LANTERN:
|
||||
case SKELETON_WALL_SKULL:
|
||||
case WITHER_SKELETON_WALL_SKULL:
|
||||
case SNOW: {
|
||||
miscNear = true;
|
||||
break;
|
||||
}
|
||||
case BLACK_BED:
|
||||
case BLUE_BED:
|
||||
case BROWN_BED:
|
||||
case CYAN_BED:
|
||||
case GRAY_BED:
|
||||
case GREEN_BED:
|
||||
case LIME_BED:
|
||||
case MAGENTA_BED:
|
||||
case ORANGE_BED:
|
||||
case PINK_BED:
|
||||
case PURPLE_BED:
|
||||
case RED_BED:
|
||||
case WHITE_BED:
|
||||
case YELLOW_BED:
|
||||
case LIGHT_BLUE_BED:
|
||||
case LIGHT_GRAY_BED: {
|
||||
bedNear = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(blockBox.isCollided(normalBox)) {
|
||||
XMaterial blockMaterial = getXMaterial(type);
|
||||
|
||||
if(blockMaterial != null)
|
||||
switch(blockMaterial) {
|
||||
case END_PORTAL:
|
||||
case NETHER_PORTAL: {
|
||||
inPortal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!player.getInfo().isWorldLoaded())
|
||||
return;
|
||||
|
||||
CollisionHandler handler = new CollisionHandler(blocks,
|
||||
player.getInfo().getNearbyEntities(),
|
||||
player.getMovement().getTo().getLoc(), player);
|
||||
|
||||
//Bukkit.broadcastMessage("chigga4");
|
||||
|
||||
for (Entity entity : handler.getEntities()) {
|
||||
CollisionBox entityBox = EntityData.getEntityBox(entity.getLocation(), entity);
|
||||
|
||||
if(entityBox == null) continue;
|
||||
|
||||
if(entityBox.isCollided(normalBox.copy().offset(0, -.1, 0)))
|
||||
player.getInfo().setServerGround(true);
|
||||
|
||||
if(entityBox.isCollided(normalBox))
|
||||
collidedWithEntity = true;
|
||||
}
|
||||
|
||||
//Bukkit.broadcastMessage("chigga5");
|
||||
onHalfBlock = onSlab || onStairs || miscNear || bedNear;
|
||||
|
||||
if((player.getMovement().getDeltaY() <= 0 || player.getPlayerVersion().isOrAbove(ProtocolVersion.V1_14))
|
||||
&& !onClimbable) {
|
||||
onClimbable = player.getInfo().getBlockOnTo().isPresent()
|
||||
&& BlockUtils.isClimbableBlock(player.getInfo().getBlockOnTo().get());
|
||||
}
|
||||
|
||||
handler.setSize(0.6f, 1.8f);
|
||||
handler.setOffset(0f);
|
||||
|
||||
this.handler.getEntities().clear();
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public SimpleCollisionBox getBox() {
|
||||
return new SimpleCollisionBox(player.getMovement().getTo().getLoc().toVector(), player.getMovement().getTo().getLoc().toVector())
|
||||
.expand(0.3, 0,0.3).expandMax(0, 1.8, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package dev.brighten.ac.data.handlers;
|
||||
|
||||
import dev.brighten.ac.utils.PastLocation;
|
||||
import dev.brighten.ac.utils.timer.Timer;
|
||||
import dev.brighten.ac.utils.timer.impl.TickTimer;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class GeneralInformation {
|
||||
private Optional<Block> blockOnTo, blockBelow;
|
||||
private Timer lastMove = new TickTimer();
|
||||
private LivingEntity target;
|
||||
private boolean serverGround, lastServerGround, nearGround, worldLoaded;
|
||||
private List<Entity> nearbyEntities = Collections.emptyList();
|
||||
private PastLocation targetPastLocation;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package dev.brighten.ac.data.handlers;
|
||||
|
||||
import dev.brighten.ac.utils.timer.Timer;
|
||||
import dev.brighten.ac.utils.timer.impl.MillisTimer;
|
||||
import dev.brighten.ac.utils.timer.impl.TickTimer;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class LagInformation {
|
||||
private Timer lastPingDrop = new TickTimer(), lastClientTransaction = new MillisTimer();
|
||||
private long transPing, lastTransPing;
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package dev.brighten.ac.data.handlers;
|
||||
|
||||
import dev.brighten.ac.data.APlayer;
|
||||
import dev.brighten.ac.data.obj.CMove;
|
||||
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
|
||||
import dev.brighten.ac.utils.BlockUtils;
|
||||
import dev.brighten.ac.utils.MathUtils;
|
||||
import dev.brighten.ac.utils.objects.evicting.EvictingList;
|
||||
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class MovementHandler {
|
||||
|
||||
private final APlayer player;
|
||||
|
||||
@Getter
|
||||
private final CMove to = new CMove(), from = new CMove();
|
||||
@Getter
|
||||
private double deltaX, deltaY, deltaZ, deltaXZ,
|
||||
lDeltaX, lDeltaY, lDeltaZ, lDeltaXZ;
|
||||
@Getter
|
||||
private float deltaYaw, deltaPitch, lDeltaYaw, lDeltaPitch;
|
||||
private int moveTicks;
|
||||
|
||||
private int teleportsToConfirm;
|
||||
|
||||
private LinkedList<Float> yawGcdList = new EvictingList<>(45),
|
||||
pitchGcdList = new EvictingList<>(45);
|
||||
|
||||
|
||||
public void process(WPacketPlayInFlying packet, long currentTime) {
|
||||
player.getPotionHandler().onFlying(packet);
|
||||
if(moveTicks > 0) {
|
||||
updateLocations(packet);
|
||||
|
||||
// Updating block locations
|
||||
player.getInfo().setBlockOnTo(BlockUtils
|
||||
.getBlockAsync(to.getLoc().toLocation(player.getBukkitPlayer().getWorld())));
|
||||
player.getInfo().setBlockBelow(BlockUtils
|
||||
.getBlockAsync(to.getLoc().toLocation(player.getBukkitPlayer().getWorld())
|
||||
.subtract(0,1,0)));
|
||||
|
||||
if(packet.isMoved()) {
|
||||
// Updating player bounding box
|
||||
player.getInfo().getLastMove().reset();
|
||||
}
|
||||
|
||||
player.getBlockInformation().runCollisionCheck();
|
||||
}
|
||||
|
||||
|
||||
moveTicks++; //Must be end of code
|
||||
}
|
||||
|
||||
/**
|
||||
* Updating the "to" and "from" location to current location.
|
||||
* Resetting position tracking; meant primarily for instant teleports.
|
||||
* @param location Location
|
||||
*/
|
||||
public void moveTo(Location location) {
|
||||
to.getLoc().x = from.getLoc().x = location.getX();
|
||||
to.getLoc().y = from.getLoc().y = location.getY();
|
||||
to.getLoc().z = from.getLoc().z = location.getZ();
|
||||
to.getLoc().yaw = from.getLoc().yaw = location.getYaw();
|
||||
to.getLoc().pitch = from.getLoc().pitch = location.getPitch();
|
||||
|
||||
deltaX = deltaY = deltaZ = deltaXZ
|
||||
= lDeltaX = lDeltaY = lDeltaZ
|
||||
= lDeltaXZ = 0;
|
||||
|
||||
deltaYaw = lDeltaYaw =
|
||||
deltaPitch = lDeltaPitch = 0;
|
||||
moveTicks = 0;
|
||||
//doingTeleport = inventoryOpen = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting the to and from to current location only if the player either moved or looked.
|
||||
* @param packet WPacketPlayInFlyingh
|
||||
*/
|
||||
private void setTo(WPacketPlayInFlying packet) {
|
||||
to.setWorld(player.getBukkitPlayer().getWorld());
|
||||
if(packet.isMoved()) {
|
||||
to.getLoc().x = packet.getX();
|
||||
to.getLoc().y = packet.getY();
|
||||
to.getLoc().z = packet.getZ();
|
||||
}
|
||||
if(packet.isLooked()) {
|
||||
to.getLoc().yaw = packet.getYaw();
|
||||
to.getLoc().pitch = packet.getPitch();
|
||||
}
|
||||
to.setBox(new SimpleCollisionBox(to.getLoc(), 0.6, 1.8));
|
||||
to.setOnGround(packet.isOnGround());
|
||||
}
|
||||
|
||||
/**
|
||||
* If from location is null, update to loc after to is set, otherwise, update to before from.
|
||||
* Updates the location of player and its general delta movement.
|
||||
* @param packet WPacketPlayInFlying
|
||||
*/
|
||||
private void updateLocations(WPacketPlayInFlying packet) {
|
||||
from.setLoc(to);
|
||||
setTo(packet);
|
||||
|
||||
lDeltaX = deltaX;
|
||||
lDeltaY = deltaY;
|
||||
lDeltaZ = deltaZ;
|
||||
lDeltaXZ = deltaXZ;
|
||||
lDeltaYaw = deltaYaw;
|
||||
lDeltaPitch = deltaPitch;
|
||||
|
||||
deltaX = to.getLoc().x - from.getLoc().x;
|
||||
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);
|
||||
deltaPitch = to.getLoc().pitch - from.getLoc().pitch;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package dev.brighten.ac.data.obj;
|
||||
|
||||
import dev.brighten.ac.utils.KLocation;
|
||||
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.World;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class CMove {
|
||||
private KLocation loc = new KLocation(0,0,0,0,0);
|
||||
private World world;
|
||||
private SimpleCollisionBox box;
|
||||
private boolean onGround;
|
||||
public void setLoc(CMove move) {
|
||||
this.loc = move.getLoc().clone();
|
||||
this.world = move.getWorld();
|
||||
this.box = move.getBox();
|
||||
this.onGround = move.isOnGround();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package dev.brighten.ac.data.obj;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public class InstantAction {
|
||||
private final short startId, endId;
|
||||
private final boolean end;
|
||||
private final long stamp = System.currentTimeMillis();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package dev.brighten.ac.data.obj;
|
||||
|
||||
import dev.brighten.ac.handler.keepalive.KeepAlive;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class NormalAction {
|
||||
public int stamp;
|
||||
public Consumer<KeepAlive> action;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package dev.brighten.ac.handler;
|
||||
|
||||
import dev.brighten.ac.Anticheat;
|
||||
import dev.brighten.ac.data.APlayer;
|
||||
import dev.brighten.ac.data.obj.NormalAction;
|
||||
import dev.brighten.ac.packet.wrapper.WPacket;
|
||||
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
|
||||
import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutEntityEffect;
|
||||
import lombok.val;
|
||||
import net.minecraft.server.v1_8_R3.Packet;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayInTransaction;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Optional;
|
||||
|
||||
public class PacketHandler {
|
||||
public void process(APlayer player, Packet packetObject) {
|
||||
if(packetObject instanceof PacketPlayInTransaction) {
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
PacketPlayInTransaction packet = (PacketPlayInTransaction) packetObject;
|
||||
|
||||
if(packet.a() == 0) {
|
||||
if(Anticheat.INSTANCE.getKeepaliveProcessor().keepAlives.getIfPresent(packet.b()) != null) {
|
||||
Anticheat.INSTANCE.getKeepaliveProcessor().addResponse(player, packet.b());
|
||||
|
||||
val optional = Anticheat.INSTANCE.getKeepaliveProcessor().getResponse(player);
|
||||
|
||||
int current = Anticheat.INSTANCE.getKeepaliveProcessor().tick;
|
||||
|
||||
optional.ifPresent(ka -> {
|
||||
player.addPlayerTick();
|
||||
|
||||
player.getLagInfo().setLastTransPing(player.getLagInfo().getTransPing());
|
||||
player.getLagInfo().setTransPing(current - ka.start);
|
||||
|
||||
if(player.instantTransaction.size() > 0) {
|
||||
synchronized (player.instantTransaction) {
|
||||
Deque<Short> toRemove = new LinkedList<>();
|
||||
player.instantTransaction.forEach((key, tuple) -> {
|
||||
if((currentTimeMillis - tuple.one.getStamp())
|
||||
> player.getLagInfo().getTransPing() * 52L + 750L) {
|
||||
tuple.two.accept(tuple.one);
|
||||
toRemove.add(key);
|
||||
}
|
||||
});
|
||||
Short key = null;
|
||||
while((key = toRemove.poll()) != null) {
|
||||
player.instantTransaction.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(Math.abs(player.getLagInfo().getLastTransPing() - player.getLagInfo().getTransPing()) > 1) {
|
||||
player.getLagInfo().getLastPingDrop().reset();
|
||||
}
|
||||
|
||||
ka.getReceived(player.getBukkitPlayer().getUniqueId()).ifPresent(r -> {
|
||||
r.receivedStamp = currentTimeMillis;
|
||||
});
|
||||
|
||||
for (NormalAction action : player.keepAliveStamps) {
|
||||
if(action.stamp > ka.start) continue;
|
||||
|
||||
action.action.accept(ka);
|
||||
player.keepAliveStamps.remove(action);
|
||||
}
|
||||
});
|
||||
player.getLagInfo().getLastClientTransaction().reset();
|
||||
} else {
|
||||
Optional.ofNullable(player.instantTransaction.remove(packet.b()))
|
||||
.ifPresent(t -> t.two.accept(t.one));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
player.callPacket(packetObject);
|
||||
}
|
||||
|
||||
public void process(APlayer player, WPacket packetObject) {
|
||||
|
||||
if(packetObject instanceof WPacketPlayInFlying) {
|
||||
WPacketPlayInFlying packet = (WPacketPlayInFlying) packetObject;
|
||||
|
||||
player.getMovement().process(packet, System.currentTimeMillis());
|
||||
} else if(packetObject instanceof WPacketPlayOutEntityEffect) {
|
||||
WPacketPlayOutEntityEffect packet = (WPacketPlayOutEntityEffect) packetObject;
|
||||
|
||||
player.getPotionHandler().onPotionEffect(packet);
|
||||
}
|
||||
|
||||
player.callPacket(packetObject);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package dev.brighten.ac.handler;
|
||||
|
||||
import dev.brighten.ac.data.APlayer;
|
||||
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
|
||||
import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutEntityEffect;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.val;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class PotionHandler {
|
||||
private final APlayer data;
|
||||
|
||||
public List<PotionEffect> potionEffects = new CopyOnWriteArrayList<>();
|
||||
|
||||
public void onFlying(WPacketPlayInFlying packet) {
|
||||
for (PotionEffect effect : potionEffects) {
|
||||
if(data.getBukkitPlayer().hasPotionEffect(effect.getType())) continue;
|
||||
|
||||
data.runKeepaliveAction(d -> data.getPotionHandler().potionEffects.remove(effect));
|
||||
}
|
||||
}
|
||||
|
||||
public void onPotionEffect(WPacketPlayOutEntityEffect packet) {
|
||||
data.runKeepaliveAction(d -> {
|
||||
val type = PotionEffectType.getById(packet.getEffectId());
|
||||
data.getPotionHandler().potionEffects.stream().filter(pe -> pe.getType().equals(type))
|
||||
.forEach(data.getPotionHandler().potionEffects::remove);
|
||||
data.getPotionHandler().potionEffects
|
||||
.add(new PotionEffect(type, packet.getDuration(), packet.getAmplifier(),
|
||||
(packet.getFlags() & 1) == 1));
|
||||
});
|
||||
}
|
||||
|
||||
public boolean hasPotionEffect(PotionEffectType type) {
|
||||
for (PotionEffect potionEffect : potionEffects) {
|
||||
if(potionEffect.getType().equals(type))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Optional<PotionEffect> getEffectByType(PotionEffectType type) {
|
||||
for (PotionEffect potionEffect : potionEffects) {
|
||||
if(potionEffect.getType().equals(type))
|
||||
return Optional.of(potionEffect);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package dev.brighten.ac.handler.keepalive;
|
||||
|
||||
import dev.brighten.ac.Anticheat;
|
||||
import dev.brighten.ac.data.APlayer;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class KeepAlive {
|
||||
|
||||
public final int start;
|
||||
public final short id;
|
||||
public long startStamp;
|
||||
|
||||
public KeepAlive(int start, short id) {
|
||||
this.start = start;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public final Map<UUID, KAReceived> receivedKeepalive = new HashMap<>();
|
||||
|
||||
public void received(APlayer player) {
|
||||
receivedKeepalive.put(player.getBukkitPlayer().getUniqueId(),
|
||||
new KAReceived(player, Anticheat.INSTANCE.getKeepaliveProcessor().tick));
|
||||
}
|
||||
|
||||
public Optional<KAReceived> getReceived(UUID uuid) {
|
||||
return Optional.ofNullable(receivedKeepalive.getOrDefault(uuid, null));
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public static class KAReceived {
|
||||
public final APlayer data;
|
||||
public final int stamp;
|
||||
public long receivedStamp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package dev.brighten.ac.handler.keepalive;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import dev.brighten.ac.Anticheat;
|
||||
import dev.brighten.ac.data.APlayer;
|
||||
import dev.brighten.ac.packet.handler.HandlerAbstract;
|
||||
import dev.brighten.ac.utils.RunUtils;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayOutTransaction;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class KeepaliveProcessor implements Runnable {
|
||||
|
||||
private BukkitTask task;
|
||||
|
||||
public KeepAlive currentKeepalive = new KeepAlive(0, (short)0);
|
||||
public int tick;
|
||||
public int totalPlayers, laggyPlayers;
|
||||
|
||||
public final Cache<Short, KeepAlive> keepAlives = CacheBuilder.newBuilder().concurrencyLevel(4)
|
||||
.expireAfterWrite(15, TimeUnit.SECONDS).build();
|
||||
|
||||
final Int2ObjectMap<Short> lastResponses = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>());
|
||||
|
||||
public KeepaliveProcessor() {
|
||||
start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
tick++;
|
||||
synchronized (keepAlives) {
|
||||
short id = (short) (tick > Short.MAX_VALUE ? tick % Short.MAX_VALUE : tick);
|
||||
|
||||
//Ensuring we don't have any duplicate IDS
|
||||
|
||||
currentKeepalive = new KeepAlive(tick, id);
|
||||
keepAlives.put(currentKeepalive.id, currentKeepalive);
|
||||
}
|
||||
|
||||
currentKeepalive.startStamp = System.currentTimeMillis();
|
||||
totalPlayers = laggyPlayers = 0;
|
||||
for (APlayer value : Anticheat.INSTANCE.getPlayerRegistry().aplayerMap.values()) {
|
||||
totalPlayers++;
|
||||
|
||||
if(value.getLagInfo().getLastPingDrop().isNotPassed(2)
|
||||
|| value.getLagInfo().getLastClientTransaction().isPassed(135L)) laggyPlayers++;
|
||||
|
||||
if(value.getInfo().getTarget() != null) {
|
||||
value.getInfo().getTargetPastLocation().addLocation(value.getInfo()
|
||||
.getTarget().getLocation());
|
||||
}
|
||||
|
||||
PacketPlayOutTransaction transaction = new PacketPlayOutTransaction(0, currentKeepalive.id, false);
|
||||
|
||||
HandlerAbstract.getHandler().sendPacket(value.getBukkitPlayer(), transaction);
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<KeepAlive> getKeepByTick(int tick) {
|
||||
return keepAlives.asMap().values().stream().filter(ka -> ka.start == tick).findFirst();
|
||||
}
|
||||
|
||||
public Optional<KeepAlive> getKeepById(short id) {
|
||||
return Optional.ofNullable(keepAlives.getIfPresent(id));
|
||||
}
|
||||
|
||||
public Optional<KeepAlive> getResponse(APlayer data) {
|
||||
if(!lastResponses.containsKey(data.getBukkitPlayer().getUniqueId().hashCode()))
|
||||
return Optional.empty();
|
||||
|
||||
return getKeepById(lastResponses.get(data.getBukkitPlayer().getUniqueId().hashCode()));
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if(task == null) {
|
||||
task = RunUtils.taskTimer(this, Anticheat.INSTANCE, 20L, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
public void addResponse(APlayer data, short id) {
|
||||
getKeepById(id).ifPresent(ka -> {
|
||||
lastResponses.put(data.getBukkitPlayer().getUniqueId().hashCode(), (Short)id);
|
||||
ka.received(data);
|
||||
});
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if(task != null) {
|
||||
task.cancel();
|
||||
task = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,48 @@
|
||||
package dev.brighten.ac.listener;
|
||||
|
||||
import dev.brighten.ac.Anticheat;
|
||||
import dev.brighten.ac.data.APlayer;
|
||||
import dev.brighten.ac.packet.handler.HandlerAbstract;
|
||||
import dev.brighten.ac.packet.wrapper.PacketType;
|
||||
import dev.brighten.ac.packet.wrapper.WPacket;
|
||||
import dev.brighten.ac.utils.Init;
|
||||
import dev.brighten.ac.utils.RunUtils;
|
||||
import net.minecraft.server.v1_8_R3.Packet;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Init
|
||||
public class JoinListener implements Listener {
|
||||
|
||||
public JoinListener() {
|
||||
Anticheat.INSTANCE.getPacketProcessor().processAsync(Anticheat.INSTANCE, EventPriority.NORMAL, event -> {
|
||||
if(event.getType().equals(PacketType.BLOCK_DIG)) {
|
||||
Optional<APlayer> aplayer = Anticheat.INSTANCE.getPlayerRegistry()
|
||||
.getPlayer(event.getPlayer().getUniqueId());
|
||||
|
||||
event.getPlayer().sendMessage("BlockDig:");
|
||||
}
|
||||
aplayer.ifPresent(player -> {
|
||||
if(event.getPacket() instanceof WPacket) {
|
||||
Anticheat.INSTANCE.getPacketHandler().process(player, (WPacket) event.getPacket());
|
||||
} else {
|
||||
Anticheat.INSTANCE.getPacketHandler().process(player, (Packet) event.getPacket());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onJoin(PlayerJoinEvent event) {
|
||||
APlayer player = Anticheat.INSTANCE.getPlayerRegistry().generate(event.getPlayer());
|
||||
RunUtils.taskLater(() -> HandlerAbstract.getHandler().add(event.getPlayer()), 4L);
|
||||
|
||||
player.callEvent(event);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onLeave(PlayerQuitEvent event) {
|
||||
HandlerAbstract.getHandler().remove(event.getPlayer());
|
||||
public void onQuit(PlayerQuitEvent event) {
|
||||
Anticheat.INSTANCE.getPlayerRegistry().unregister(event.getPlayer().getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.brighten.ac.packet.handler;
|
||||
|
||||
import dev.brighten.ac.data.APlayer;
|
||||
import dev.brighten.ac.packet.ProtocolVersion;
|
||||
import dev.brighten.ac.utils.reflections.Reflections;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedClass;
|
||||
@@ -14,7 +15,7 @@ public abstract class HandlerAbstract {
|
||||
fieldNetworkManager = Reflections.getNMSClass("PlayerConnection").getFieldByName("networkManager"),
|
||||
fieldPlayerConnection = Reflections.getNMSClass("EntityPlayer").getFieldByName("playerConnection");
|
||||
|
||||
static String handlerName = "brigten-ac-packets";
|
||||
static String handlerName = "brighten-ac-packets";
|
||||
|
||||
@Getter
|
||||
private static HandlerAbstract handler;
|
||||
@@ -30,4 +31,8 @@ public abstract class HandlerAbstract {
|
||||
public abstract void add(Player player);
|
||||
|
||||
public abstract void remove(Player player);
|
||||
|
||||
public abstract void sendPacket(Player player, Object packet);
|
||||
|
||||
public abstract void sendPacket(APlayer player, Object packet);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.brighten.ac.packet.handler;
|
||||
|
||||
import dev.brighten.ac.Anticheat;
|
||||
import dev.brighten.ac.data.APlayer;
|
||||
import dev.brighten.ac.packet.wrapper.PacketType;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedClass;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedField;
|
||||
@@ -58,6 +59,16 @@ public class LegacyHandler extends HandlerAbstract {
|
||||
channel.eventLoop().execute(() -> channel.pipeline().remove(handlerName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(Player player, Object packet) {
|
||||
getChannel(player).pipeline().writeAndFlush(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(APlayer player, Object packet) {
|
||||
sendPacket(player.getBukkitPlayer(), packet);
|
||||
}
|
||||
|
||||
private Channel getChannel(Player player) {
|
||||
synchronized (channelCache) {
|
||||
return channelCache.computeIfAbsent(player.getName(), name -> {
|
||||
|
||||
@@ -2,6 +2,7 @@ package dev.brighten.ac.packet.handler;
|
||||
|
||||
import com.google.common.collect.MapMaker;
|
||||
import dev.brighten.ac.Anticheat;
|
||||
import dev.brighten.ac.data.APlayer;
|
||||
import dev.brighten.ac.packet.wrapper.PacketType;
|
||||
import dev.brighten.ac.utils.reflections.Reflections;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedField;
|
||||
@@ -58,6 +59,16 @@ public class ModernHandler extends HandlerAbstract {
|
||||
channel.eventLoop().execute(() -> channel.pipeline().remove(handlerName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(Player player, Object packet) {
|
||||
getChannel(player).pipeline().writeAndFlush(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(APlayer player, Object packet) {
|
||||
sendPacket(player.getBukkitPlayer(), packet);
|
||||
}
|
||||
|
||||
private Channel getChannel(Player player) {
|
||||
synchronized (channelCache) {
|
||||
return channelCache.computeIfAbsent(player.getName(), name -> {
|
||||
@@ -78,8 +89,11 @@ public class ModernHandler extends HandlerAbstract {
|
||||
int index = name.lastIndexOf(".");
|
||||
String packetName = name.substring(index + 1);
|
||||
|
||||
boolean allowed = Anticheat.INSTANCE.getPacketProcessor().call(player, msg, PacketType
|
||||
.getByPacketId(packetName).orElse(PacketType.NONE));
|
||||
PacketType type = PacketType
|
||||
.getByPacketId(packetName).orElse(PacketType.NONE);
|
||||
|
||||
boolean allowed = Anticheat.INSTANCE.getPacketProcessor().call(player, PacketType.processType(type, msg),
|
||||
type);
|
||||
|
||||
if(allowed) {
|
||||
super.channelRead(ctx, msg);
|
||||
|
||||
@@ -7,12 +7,20 @@ import lombok.Setter;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public class PacketInfo {
|
||||
@Getter
|
||||
private final Player player;
|
||||
private final Object packet;
|
||||
@Getter
|
||||
private final PacketType type;
|
||||
@Getter
|
||||
private final long timestamp;
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean cancelled;
|
||||
|
||||
public <T> T getPacket() {
|
||||
return (T) packet;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package dev.brighten.ac.packet.listener;
|
||||
|
||||
import dev.brighten.ac.Anticheat;
|
||||
import dev.brighten.ac.packet.ProtocolVersion;
|
||||
import dev.brighten.ac.packet.handler.HandlerAbstract;
|
||||
import dev.brighten.ac.packet.listener.functions.PacketListener;
|
||||
import dev.brighten.ac.packet.wrapper.PacketConverter;
|
||||
import dev.brighten.ac.packet.wrapper.PacketType;
|
||||
@@ -11,7 +10,6 @@ import dev.brighten.ac.utils.MiscUtils;
|
||||
import dev.brighten.ac.utils.RunUtils;
|
||||
import lombok.Getter;
|
||||
import lombok.val;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
@@ -184,6 +182,5 @@ public class PacketProcessor {
|
||||
public void shutdown() {
|
||||
processors.clear();
|
||||
asyncProcessors.clear();
|
||||
Bukkit.getOnlinePlayers().forEach(HandlerAbstract.getHandler()::remove);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
package dev.brighten.ac.packet.packet;
|
||||
|
||||
public interface WPacket {
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.brighten.ac.packet.wrapper;
|
||||
|
||||
import dev.brighten.ac.packet.wrapper.in.*;
|
||||
import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutEntityEffect;
|
||||
|
||||
public interface PacketConverter {
|
||||
WPacketPlayInFlying processFlying(Object object);
|
||||
@@ -15,4 +16,8 @@ public interface PacketConverter {
|
||||
WPacketPlayInBlockPlace processBlockPlace(Object object);
|
||||
|
||||
WPacketPlayInCloseWindow processCloseWindow(Object object);
|
||||
|
||||
WPacketPlayInEntityAction processEntityAction(Object object);
|
||||
|
||||
WPacketPlayOutEntityEffect processEntityEffect(Object object);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.brighten.ac.packet.wrapper;
|
||||
|
||||
import dev.brighten.ac.Anticheat;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Optional;
|
||||
@@ -26,6 +27,10 @@ public enum PacketType {
|
||||
|
||||
CLOSE_WINDOW("PacketPlayInCloseWindow"),
|
||||
|
||||
ENTITY_ACTION("PacketPlayInEntityAction"),
|
||||
|
||||
ENTITY_EFFECT("PacketPlayOutEntityEffect"),
|
||||
|
||||
NONE();
|
||||
|
||||
PacketType(String... packetIds) {
|
||||
@@ -92,5 +97,36 @@ public enum PacketType {
|
||||
public static final String STATUS_START = "PacketStatusInStart";
|
||||
public static final String LOGIN_START = "PacketLoginInStart";
|
||||
}
|
||||
|
||||
public static Object processType(PacketType type, Object object) {
|
||||
PacketConverter convert = Anticheat.INSTANCE.getPacketProcessor().getPacketConverter();
|
||||
|
||||
switch (type) {
|
||||
case FLYING: {
|
||||
return convert.processFlying(object);
|
||||
}
|
||||
case CHAT:
|
||||
break;
|
||||
case BLOCK_DIG:
|
||||
return convert.processBlockDig(object);
|
||||
case USE_ENTITY:
|
||||
return convert.processUseEntity(object);
|
||||
case BLOCK_PLACE:
|
||||
return convert.processBlockPlace(object);
|
||||
case CLOSE_WINDOW:
|
||||
return convert.processCloseWindow(object);
|
||||
case ARM_ANIMATION:
|
||||
return convert.processAnimation(object);
|
||||
case ENTITY_ACTION:
|
||||
return convert.processEntityAction(object);
|
||||
case CLIENT_ABILITIES:
|
||||
return convert.processAbilities(object);
|
||||
case ENTITY_EFFECT:
|
||||
return convert.processEntityEffect(object);
|
||||
default:
|
||||
return object;
|
||||
}
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package dev.brighten.ac.packet.wrapper.impl;
|
||||
import dev.brighten.ac.packet.wrapper.PacketConverter;
|
||||
import dev.brighten.ac.packet.wrapper.in.*;
|
||||
import dev.brighten.ac.packet.wrapper.objects.WrappedEnumDirection;
|
||||
import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutEntityEffect;
|
||||
import dev.brighten.ac.utils.math.IntVector;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedClass;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedField;
|
||||
@@ -67,7 +68,7 @@ public class Processor_18 implements PacketConverter {
|
||||
BlockPosition pos = packet.a();
|
||||
|
||||
return WPacketPlayInBlockPlace.builder().blockPos(new IntVector(pos.getX(), pos.getY(), pos.getZ()))
|
||||
.direction(WrappedEnumDirection.values()[packet.getFace()])
|
||||
.direction(WrappedEnumDirection.values()[Math.min(packet.getFace(), 5)])
|
||||
.itemStack(CraftItemStack.asCraftMirror(packet.getItemStack()))
|
||||
.vecX(packet.d()).vecY(packet.e()).vecZ(packet.f())
|
||||
.build();
|
||||
@@ -75,11 +76,39 @@ public class Processor_18 implements PacketConverter {
|
||||
|
||||
|
||||
private static final WrappedClass classCloseWindow = new WrappedClass(PacketPlayInCloseWindow.class);
|
||||
private static final WrappedField fieldWindowId = classAbilities.getFieldByType(int.class, 0);
|
||||
private static final WrappedField fieldWindowId = classCloseWindow.getFieldByType(int.class, 0);
|
||||
@Override
|
||||
public WPacketPlayInCloseWindow processCloseWindow(Object object) {
|
||||
PacketPlayInCloseWindow packet = (PacketPlayInCloseWindow) object;
|
||||
|
||||
return WPacketPlayInCloseWindow.builder().id(fieldWindowId.get(packet)).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WPacketPlayInEntityAction processEntityAction(Object object) {
|
||||
PacketPlayInEntityAction packet = (PacketPlayInEntityAction) object;
|
||||
|
||||
return WPacketPlayInEntityAction.builder().action(WPacketPlayInEntityAction.EnumPlayerAction
|
||||
.valueOf(packet.b().name())).build();
|
||||
}
|
||||
|
||||
private static final WrappedClass classEntityEffect = new WrappedClass(PacketPlayOutEntityEffect.class);
|
||||
private static final WrappedField fieldEntityId2, fieldEffectId, fieldAmplifier, fieldDuration, fieldFlags;
|
||||
|
||||
static {
|
||||
fieldEntityId2 = classEntityEffect.getFieldByType(Integer.TYPE, 0);
|
||||
fieldEffectId = classEntityEffect.getFieldByType(Byte.TYPE, 0);
|
||||
fieldAmplifier = classEntityEffect.getFieldByType(Byte.TYPE, 1);
|
||||
fieldDuration = classEntityEffect.getFieldByType(Integer.TYPE, 1);
|
||||
fieldFlags = classEntityEffect.getFieldByType(Byte.TYPE, 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WPacketPlayOutEntityEffect processEntityEffect(Object object) {
|
||||
return WPacketPlayOutEntityEffect.builder().effectId(fieldEffectId.get(object))
|
||||
.amplifier(fieldAmplifier.get(object))
|
||||
.flags(fieldFlags.get(object))
|
||||
.entityId(fieldEntityId2.get(object))
|
||||
.duration(fieldDuration.get(object)).build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package dev.brighten.ac.packet.wrapper.in;
|
||||
|
||||
import dev.brighten.ac.packet.wrapper.PacketType;
|
||||
import dev.brighten.ac.packet.wrapper.WPacket;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Builder
|
||||
@Getter
|
||||
public class WPacketPlayInEntityAction implements WPacket {
|
||||
|
||||
private EnumPlayerAction action;
|
||||
|
||||
@Override
|
||||
public PacketType getPacketType() {
|
||||
return PacketType.ENTITY_ACTION;
|
||||
}
|
||||
|
||||
public static enum EnumPlayerAction {
|
||||
START_SNEAKING,
|
||||
STOP_SNEAKING,
|
||||
STOP_SLEEPING,
|
||||
START_SPRINTING,
|
||||
STOP_SPRINTING,
|
||||
RIDING_JUMP,
|
||||
OPEN_INVENTORY;
|
||||
|
||||
private EnumPlayerAction() {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@ public class WPacketPlayInUseEntity implements WPacket {
|
||||
return PacketType.USE_ENTITY;
|
||||
}
|
||||
|
||||
|
||||
public enum EnumHand {
|
||||
MAIN_HAND, OFF_HAND;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package dev.brighten.ac.utils;
|
||||
|
||||
import dev.brighten.ac.Anticheat;
|
||||
import dev.brighten.ac.utils.reflections.Reflections;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedClass;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.tree.AnnotationNode;
|
||||
@@ -8,6 +11,7 @@ import org.objectweb.asm.tree.ClassNode;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
@@ -18,6 +22,7 @@ import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
@@ -39,6 +44,125 @@ public class ClassScanner {
|
||||
return scanFile(file, urls);
|
||||
}
|
||||
|
||||
public static Set<WrappedClass> getClasses(Class<? extends Annotation> annotationClass,
|
||||
String packageName) {
|
||||
return scanFile(annotationClass).stream().filter(pkg -> pkg.startsWith(packageName))
|
||||
.map(Reflections::getClass).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public static Set<WrappedClass> getClasses(Class<? extends Annotation> annotationClass) {
|
||||
return scanFile(annotationClass).stream().map(Reflections::getClass).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public static Set<String> scanFile(Class<? extends Annotation> annotationClass) {
|
||||
return scanFile(annotationClass, new URL[]{Anticheat.class.getProtectionDomain().getCodeSource().getLocation()});
|
||||
}
|
||||
|
||||
public static Set<String> scanFile(Class<? extends Annotation> annotationClass, URL[] urls) {
|
||||
Set<URI> sources = new HashSet<>();
|
||||
Set<String> plugins = new HashSet<>();
|
||||
|
||||
|
||||
for (URL url : urls) {
|
||||
if (!url.getProtocol().equals("file")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
URI source;
|
||||
try {
|
||||
source = url.toURI();
|
||||
} catch (URISyntaxException e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sources.add(source)) {
|
||||
scanPath(Paths.get(source), annotationClass, plugins);
|
||||
}
|
||||
}
|
||||
|
||||
return plugins;
|
||||
}
|
||||
|
||||
private static void scanPath(Path path, Class<? extends Annotation> annotationClass, Set<String> plugins) {
|
||||
if (Files.exists(path)) {
|
||||
if (Files.isDirectory(path)) {
|
||||
scanDirectory(path, annotationClass, plugins);
|
||||
} else {
|
||||
scanZip(path, annotationClass, plugins);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void scanDirectory(Path dir, Class<? extends Annotation> annotationClass, final Set<String> plugins) {
|
||||
try {
|
||||
Files.walkFileTree(dir, newHashSet(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
|
||||
new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
|
||||
if (CLASS_FILE.matches(path.getFileName())) {
|
||||
try (InputStream in = Files.newInputStream(path)) {
|
||||
String plugin = findClass(in, annotationClass);
|
||||
if (plugin != null) {
|
||||
plugins.add(plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String findClass(InputStream in, Class<? extends Annotation> annotationClass) {
|
||||
try {
|
||||
ClassReader reader = new ClassReader(in);
|
||||
ClassNode classNode = new ClassNode();
|
||||
reader.accept(classNode, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
|
||||
String className = classNode.name.replace('/', '.');
|
||||
final String anName = annotationClass.getName().replace(".", "/");
|
||||
if (classNode.visibleAnnotations != null) {
|
||||
for (Object node : classNode.visibleAnnotations) {
|
||||
AnnotationNode annotation = (AnnotationNode) node;
|
||||
if (annotation.desc
|
||||
.equals("L" + anName + ";"))
|
||||
return className;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//Bukkit.getLogger().info("Failed to scan: " + in.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void scanZip(Path path, Class<? extends Annotation> annotationClass, Set<String> plugins) {
|
||||
if (!ARCHIVE.matches(path.getFileName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
try (ZipFile zip = new ZipFile(path.toFile())) {
|
||||
Enumeration<? extends ZipEntry> entries = zip.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = entries.nextElement();
|
||||
if (entry.isDirectory() || !entry.getName().endsWith(".class")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try (InputStream in = zip.getInputStream(entry)) {
|
||||
String plugin = findClass(in, annotationClass);
|
||||
if (plugin != null) {
|
||||
plugins.add(plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> scanFile(String file, Class<?> clazz) {
|
||||
return scanFile(file, new URL[]{clazz.getProtectionDomain().getCodeSource().getLocation()});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
package dev.brighten.ac.utils;
|
||||
|
||||
import dev.brighten.ac.data.APlayer;
|
||||
import dev.brighten.ac.packet.ProtocolVersion;
|
||||
import dev.brighten.ac.utils.world.BlockData;
|
||||
import dev.brighten.ac.utils.world.CollisionBox;
|
||||
import dev.brighten.ac.utils.world.EntityData;
|
||||
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Getter
|
||||
public class
|
||||
CollisionHandler {
|
||||
private List<Block> blocks;
|
||||
private List<Entity> entities;
|
||||
private APlayer data;
|
||||
private KLocation location;
|
||||
private List<Triad<Double[], Integer, Consumer<Boolean>>> intersects = new ArrayList<>(),
|
||||
collides = new ArrayList<>();
|
||||
|
||||
private double width, height;
|
||||
private double shift;
|
||||
@Setter
|
||||
private boolean single = false;
|
||||
@Setter
|
||||
private boolean debugging;
|
||||
|
||||
public CollisionHandler(List<Block> blocks, Collection<Entity> entities, KLocation to, APlayer data) {
|
||||
this.blocks = blocks;
|
||||
this.entities = new ArrayList<>(entities);
|
||||
this.location = to;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void setSize(double width, double height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public void setOffset(double shift) {
|
||||
this.shift = shift;
|
||||
}
|
||||
|
||||
public boolean containsFlag(int bitmask) {
|
||||
for (Block b : blocks) {
|
||||
if (Materials.checkFlag(b.getType(), bitmask)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(EntityType type) {
|
||||
return entities.stream().anyMatch(e -> e.getType() == type);
|
||||
}
|
||||
|
||||
public void intersectsWithFuture(int bitMask, Consumer<Boolean> intersects) {
|
||||
String bitMaskString = String.valueOf(bitMask) + "%%__NONCE__%%";
|
||||
this.intersects.add(new Triad<>(new Double[] {width, height, shift}, bitMask, intersects));
|
||||
}
|
||||
|
||||
public void collidesWithFuture(int bitMask, Consumer<Boolean> collides) {
|
||||
this.collides.add(new Triad<>(new Double[] {width, height, shift}, bitMask, collides));
|
||||
}
|
||||
|
||||
public boolean isCollidedWithEntity(SimpleCollisionBox box) {
|
||||
for(Entity entity : entities) {
|
||||
if(EntityData.getEntityBox(entity.getLocation(), entity).isCollided(box))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isCollidedWithEntity() {
|
||||
SimpleCollisionBox playerBox = new SimpleCollisionBox()
|
||||
.offset(location.x, location.y, location.z)
|
||||
.expandMin(0, shift, 0)
|
||||
.expandMax(0, height, 0)
|
||||
.expand(width / 2, 0, width / 2);
|
||||
|
||||
return isCollidedWithEntity(playerBox);
|
||||
}
|
||||
|
||||
public List<CollisionBox> getCollisionBoxes(SimpleCollisionBox playerBox) {
|
||||
List<CollisionBox> collided = new ArrayList<>();
|
||||
|
||||
for (Block b : blocks) {
|
||||
Material material = b.getType();
|
||||
|
||||
CollisionBox box;
|
||||
if((box = BlockData.getData(material).getBox(b, ProtocolVersion.getGameVersion())).isCollided(playerBox)) {
|
||||
collided.add(box);
|
||||
}
|
||||
}
|
||||
|
||||
for(Entity entity : entities) {
|
||||
CollisionBox box = EntityData.getEntityBox(entity.getLocation(), entity);
|
||||
if(box.isCollided(playerBox))
|
||||
collided.add(box);
|
||||
}
|
||||
|
||||
return collided;
|
||||
}
|
||||
public List<CollisionBox> getCollisionBoxes() {
|
||||
SimpleCollisionBox playerBox = new SimpleCollisionBox()
|
||||
.offset(location.x, location.y, location.z)
|
||||
.expandMin(0, shift, 0)
|
||||
.expandMax(0, height, 0)
|
||||
.expand(width / 2, 0, width / 2);
|
||||
|
||||
return getCollisionBoxes(playerBox);
|
||||
}
|
||||
|
||||
public boolean isCollidedWith(CollisionBox box) {
|
||||
SimpleCollisionBox playerBox = new SimpleCollisionBox()
|
||||
.offset(location.x, location.y, location.z)
|
||||
.expandMin(0, shift, 0)
|
||||
.expandMax(0, height, 0)
|
||||
.expand(width / 2, 0, width / 2);
|
||||
|
||||
return box.isCollided(playerBox);
|
||||
}
|
||||
|
||||
public boolean isCollidedWith(SimpleCollisionBox playerBox, Material... materials) {
|
||||
for (Block b : blocks) {
|
||||
Location block = b.getLocation();
|
||||
Material material = b.getType();
|
||||
|
||||
if (materials.length == 0 || MiscUtils.contains(materials, material)) {
|
||||
if (BlockData.getData(material).getBox(b, ProtocolVersion.getGameVersion()).isCollided(playerBox))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(materials.length == 0) {
|
||||
for(Entity entity : entities) {
|
||||
if(EntityData.getEntityBox(entity.getLocation(), entity).isCollided(playerBox))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
public boolean isCollidedWith(Material... materials) {
|
||||
SimpleCollisionBox playerBox = new SimpleCollisionBox()
|
||||
.offset(location.x, location.y, location.z)
|
||||
.expandMin(0, shift, 0)
|
||||
.expandMax(0, height, 0)
|
||||
.expand(width / 2, 0, width / 2);
|
||||
|
||||
return isCollidedWith(playerBox, materials);
|
||||
}
|
||||
|
||||
public void runFutures() {
|
||||
Triad<Double[], Integer, Consumer<Boolean>> value = null;
|
||||
Queue<Consumer<Boolean>> successful = new LinkedList<>();
|
||||
//To remove objects
|
||||
Queue<Triad<Double[], Integer, Consumer<Boolean>>> collisionRemove = new LinkedList<>(),
|
||||
intersectsRemove = new LinkedList<>();
|
||||
|
||||
for (Block b : blocks) {
|
||||
Location block = b.getLocation();
|
||||
Material material = b.getType();
|
||||
for (Triad<Double[], Integer, Consumer<Boolean>> intersect : intersects) {
|
||||
if(!Materials.checkFlag(material, intersect.second)) continue;
|
||||
|
||||
SimpleCollisionBox playerBox = new SimpleCollisionBox()
|
||||
.offset(location.x, location.y, location.z)
|
||||
.expandMin(0, intersect.first[2], 0)
|
||||
.expandMax(0, intersect.first[1], 0)
|
||||
.expand(intersect.first[0] / 2, 0, intersect.first[0] / 2);
|
||||
|
||||
if (BlockData.getData(material).getBox(b, ProtocolVersion.getGameVersion()).isIntersected(playerBox)) {
|
||||
successful.add(intersect.third);
|
||||
intersectsRemove.add(intersect);
|
||||
}
|
||||
}
|
||||
for (Triad<Double[], Integer, Consumer<Boolean>> collides : collides) {
|
||||
if(!Materials.checkFlag(material, collides.second)) continue;
|
||||
|
||||
SimpleCollisionBox playerBox = new SimpleCollisionBox()
|
||||
.offset(location.x, location.y, location.z)
|
||||
.expandMin(0, collides.first[2], 0)
|
||||
.expandMax(0, collides.first[1], 0)
|
||||
.expand(collides.first[0] / 2, 0, collides.first[0] / 2);
|
||||
|
||||
if (BlockData.getData(material).getBox(b, ProtocolVersion.getGameVersion()).isCollided(playerBox)) {
|
||||
successful.add(collides.third);
|
||||
intersectsRemove.add(collides);
|
||||
}
|
||||
}
|
||||
|
||||
while((value = intersectsRemove.poll()) != null) {
|
||||
intersects.remove(value);
|
||||
}
|
||||
while((value = collisionRemove.poll()) != null) {
|
||||
collides.remove(value);
|
||||
}
|
||||
}
|
||||
collides.clear();
|
||||
intersects.clear();
|
||||
|
||||
Consumer<Boolean> consumer = null;
|
||||
while((consumer = successful.poll()) != null) {
|
||||
consumer.accept(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package dev.brighten.ac.utils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public abstract class HookedListWrapper<T> extends ListWrapper<T> {
|
||||
public HookedListWrapper(List<T> base) {
|
||||
super(base);
|
||||
}
|
||||
|
||||
// We can use the List#size call to execute some code
|
||||
public abstract void onSize();
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
this.onSize();
|
||||
return this.base.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return this.base.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return this.base.contains(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return this.listIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return this.base.toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T o) {
|
||||
return this.base.add(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
return this.base.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection c) {
|
||||
return this.base.addAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, Collection c) {
|
||||
return this.base.addAll(index, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
this.base.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(int index) {
|
||||
return this.base.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T set(int index, T element) {
|
||||
return this.base.set(index, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int index, T element) {
|
||||
this.base.add(index, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T remove(int index) {
|
||||
return this.base.remove(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Object o) {
|
||||
return this.base.indexOf(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(Object o) {
|
||||
return this.base.lastIndexOf(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<T> listIterator() {
|
||||
return this.base.listIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<T> listIterator(int index) {
|
||||
return this.base.listIterator(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> subList(int fromIndex, int toIndex) {
|
||||
return this.base.subList(fromIndex, toIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection c) {
|
||||
return this.base.retainAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection c) {
|
||||
return this.base.removeAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection c) {
|
||||
return this.base.containsAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray(Object[] a) {
|
||||
return this.base.toArray(a);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class KLocation {
|
||||
public double x, y, z;
|
||||
public float yaw, pitch;
|
||||
@@ -55,4 +57,29 @@ public class KLocation {
|
||||
public KLocation clone() {
|
||||
return new KLocation(x, y, z, yaw, pitch, timeStamp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
KLocation kLocation = (KLocation) o;
|
||||
return Double.compare(kLocation.x, x) == 0 && Double.compare(kLocation.y, y) == 0 && Double.compare(kLocation.z, z) == 0 && Float.compare(kLocation.yaw, yaw) == 0 && Float.compare(kLocation.pitch, pitch) == 0 && timeStamp == kLocation.timeStamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, y, z, yaw, pitch, timeStamp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "KLocation{" +
|
||||
"x=" + x +
|
||||
", y=" + y +
|
||||
", z=" + z +
|
||||
", yaw=" + yaw +
|
||||
", pitch=" + pitch +
|
||||
", timeStamp=" + timeStamp +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.brighten.ac.utils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ListWrapper<T> implements List<T> {
|
||||
protected final List<T> base;
|
||||
|
||||
public ListWrapper(List<T> base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
public List<T> getBase() {
|
||||
return this.base;
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,14 @@ import dev.brighten.ac.utils.reflections.impl.CraftReflection;
|
||||
import dev.brighten.ac.utils.reflections.impl.MinecraftReflection;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedClass;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedField;
|
||||
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.command.SimpleCommandMap;
|
||||
@@ -42,6 +46,54 @@ public class MiscUtils {
|
||||
return toCheck.toLowerCase().contains(contains.toLowerCase());
|
||||
}
|
||||
|
||||
public static boolean isInMaterialBB(World world, SimpleCollisionBox entityBox, XMaterial xmaterial) {
|
||||
int startX = MathHelper.floor_double(entityBox.xMin);
|
||||
int startY = MathHelper.floor_double(entityBox.yMin);
|
||||
int startZ = MathHelper.floor_double(entityBox.zMin);
|
||||
int endX = MathHelper.floor_double(entityBox.xMax + 1D);
|
||||
int endY = MathHelper.floor_double(entityBox.yMax + 1D);
|
||||
int endZ = MathHelper.floor_double(entityBox.zMax + 1D);
|
||||
|
||||
for(int x = startX ; x < endX ; x++) {
|
||||
for(int y = startY ; y < endY ; y++) {
|
||||
for(int z = startZ ; z < endZ ; z++) {
|
||||
Location loc = new Location(world, x, y, z);
|
||||
Optional<Block> op = BlockUtils.getBlockAsync(loc);
|
||||
|
||||
if(op.isPresent()) {
|
||||
if(XMaterial.matchXMaterial(op.get().getType()).equals(xmaterial))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isInMaterialBB(World world, SimpleCollisionBox entityBox, int bitmask) {
|
||||
int startX = MathHelper.floor_double(entityBox.xMin);
|
||||
int startY = MathHelper.floor_double(entityBox.yMin);
|
||||
int startZ = MathHelper.floor_double(entityBox.zMin);
|
||||
int endX = MathHelper.floor_double(entityBox.xMax + 1D);
|
||||
int endY = MathHelper.floor_double(entityBox.yMax + 1D);
|
||||
int endZ = MathHelper.floor_double(entityBox.zMax + 1D);
|
||||
|
||||
for(int x = startX ; x < endX ; x++) {
|
||||
for(int y = startY ; y < endY ; y++) {
|
||||
for(int z = startZ ; z < endZ ; z++) {
|
||||
Location loc = new Location(world, x, y, z);
|
||||
Optional<Block> op = BlockUtils.getBlockAsync(loc);
|
||||
|
||||
if(op.isPresent()) {
|
||||
if(Materials.checkFlag(op.get().getType(), bitmask))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static <T> List<T> combineLists(List<T> one, List<T> two) {
|
||||
List<T> newList = new ArrayList<>();
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package dev.brighten.ac.utils;
|
||||
|
||||
public class MouseFilter {
|
||||
public float x;
|
||||
public float y;
|
||||
public float z;
|
||||
|
||||
/**
|
||||
* Smooths mouse input
|
||||
*/
|
||||
public float smooth(float p_76333_1_, float p_76333_2_) {
|
||||
this.x += p_76333_1_;
|
||||
p_76333_1_ = (this.x - this.y) * p_76333_2_;
|
||||
this.z += (p_76333_1_ - this.z) * 0.5F;
|
||||
|
||||
if (p_76333_1_ > 0.0F && p_76333_1_ > this.z || p_76333_1_ < 0.0F && p_76333_1_ < this.z) {
|
||||
p_76333_1_ = this.z;
|
||||
}
|
||||
|
||||
this.y += p_76333_1_;
|
||||
return p_76333_1_;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
this.x = 0.0F;
|
||||
this.y = 0.0F;
|
||||
this.z = 0.0F;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package dev.brighten.ac.utils;
|
||||
|
||||
import dev.brighten.ac.Anticheat;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PastLocation {
|
||||
public final LinkedList<KLocation> previousLocations = new LinkedList<>();
|
||||
|
||||
public KLocation getPreviousLocation(int time) {
|
||||
synchronized (previousLocations) {
|
||||
return (this.previousLocations.stream()
|
||||
.min(Comparator.comparing(loc -> Math.abs(time - loc.timeStamp)))
|
||||
.orElse(this.previousLocations.getFirst()));
|
||||
}
|
||||
}
|
||||
|
||||
public List<KLocation> getEstimatedLocation(int currentTime, int ping, int delta) {
|
||||
synchronized (previousLocations) {
|
||||
int tick = currentTime - ping;
|
||||
|
||||
List<KLocation> locs = new ArrayList<>();
|
||||
|
||||
for (KLocation previousLocation : previousLocations) {
|
||||
if (Math.abs(tick - previousLocation.timeStamp) <= delta) {
|
||||
locs.add(previousLocation.clone());
|
||||
}
|
||||
}
|
||||
return locs;
|
||||
}
|
||||
}
|
||||
|
||||
public List<KLocation> getEstimatedLocationByIndex(int ping, int minAdd, int maxAdd) {
|
||||
synchronized (previousLocations) {
|
||||
|
||||
List<KLocation> locs = new ArrayList<>();
|
||||
|
||||
int size = previousLocations.size() - 1;
|
||||
int max = Math.min(size, size - ping + maxAdd),
|
||||
min = Math.max(0, size - Math.max(1, ping) - minAdd);
|
||||
|
||||
for (int i = max; i > min; i--) {
|
||||
locs.add(previousLocations.get(i));
|
||||
}
|
||||
return locs;
|
||||
}
|
||||
}
|
||||
|
||||
public List<KLocation> getEstimatedLocation(long time, long ping) {
|
||||
synchronized (previousLocations) {
|
||||
return this.previousLocations.stream()
|
||||
.filter(loc -> time - loc.timeStamp > 0
|
||||
&& time - loc.timeStamp <= ping + (ping < 50 ? 100 : 50))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
public List<KLocation> getPreviousRange(long delta) {
|
||||
synchronized (previousLocations) {
|
||||
long stamp = System.currentTimeMillis();
|
||||
|
||||
return this.previousLocations.stream()
|
||||
.filter(loc -> stamp - loc.timeStamp < delta)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
public void addLocation(Location location) {
|
||||
synchronized (previousLocations) {
|
||||
if (previousLocations.size() >= 20)
|
||||
previousLocations.removeFirst();
|
||||
|
||||
KLocation loc = new KLocation(location);
|
||||
loc.timeStamp = Anticheat.INSTANCE.getKeepaliveProcessor().tick;
|
||||
previousLocations.add(loc);
|
||||
}
|
||||
}
|
||||
|
||||
public Deque<KLocation> getPreviousLocations() {
|
||||
return previousLocations;
|
||||
}
|
||||
|
||||
public void addLocation(KLocation location) {
|
||||
KLocation loc = location.clone();
|
||||
loc.timeStamp = Anticheat.INSTANCE.getKeepaliveProcessor().tick;
|
||||
synchronized (previousLocations) {
|
||||
if (previousLocations.size() >= 20)
|
||||
previousLocations.removeFirst();
|
||||
|
||||
previousLocations.add(loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package dev.brighten.ac.utils;
|
||||
|
||||
import dev.brighten.ac.Anticheat;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
@SuppressWarnings({"ConstantConditions", "unchecked"})
|
||||
public final class ReflectionUtil {
|
||||
private static final Unsafe UNSAFE = ReflectionUtil.getUnsafeInstance();
|
||||
|
||||
private static Unsafe getUnsafeInstance() {
|
||||
try {
|
||||
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
unsafeField.setAccessible(true);
|
||||
return (Unsafe) unsafeField.get(null);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
Anticheat.INSTANCE.getLogger().severe("Could not locate Unsafe object!");
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Field get(Class<?> oClass, Class<?> type, int index) throws NoSuchFieldException {
|
||||
int i = 0;
|
||||
for (Field field : oClass.getDeclaredFields()) {
|
||||
if (field.getType() == type) {
|
||||
if (i == index) {
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
throw new NoSuchFieldException("Could not find field of class " + type.getName() + " with index " + index);
|
||||
}
|
||||
|
||||
public static Field getFieldByClassNames(Class<?> clazz, String... simpleNames) throws NoSuchFieldException {
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
String typeSimpleName = field.getType().getSimpleName();
|
||||
for (String name : simpleNames) {
|
||||
if (name.equals(typeSimpleName)) {
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new NoSuchFieldException("Could not find field in class " + clazz.getName() + " with names " + Arrays.toString(simpleNames));
|
||||
}
|
||||
|
||||
public static Field getFieldByType(Class<?> clazz, Class<?> type) throws NoSuchFieldException {
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
Class<?> foundType = field.getType();
|
||||
if (type.isAssignableFrom(foundType)) {
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
}
|
||||
}
|
||||
|
||||
throw new NoSuchFieldException("Could not find field in class " + clazz.getName() + " with type " + type.getName());
|
||||
}
|
||||
|
||||
public static Method getMethodByName(Class<?> clazz, String name) throws NoSuchMethodException {
|
||||
for (Method method : clazz.getDeclaredMethods()) {
|
||||
if (name.equals(method.getName())) {
|
||||
method.setAccessible(true);
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
||||
throw new NoSuchMethodException("Could not find method in class " + clazz.getName() + " with name " + name);
|
||||
}
|
||||
|
||||
public static Class<?> getSuperClassByName(Class<?> clazz, String simpleName) {
|
||||
if (!clazz.getSimpleName().equals(simpleName)) {
|
||||
Class<?> superClazz;
|
||||
while((superClazz = clazz.getSuperclass()) != null) {
|
||||
if (superClazz.getSimpleName().equals(simpleName)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return superClazz;
|
||||
} else {
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> void setUnsafe(Object object, Field field, T value) {
|
||||
ReflectionUtil.UNSAFE.putObject(object, ReflectionUtil.UNSAFE.objectFieldOffset(field), value);
|
||||
}
|
||||
|
||||
public static <T> T instantiateUnsafe(Class<T> clazz) throws Exception{
|
||||
return (T) ReflectionUtil.UNSAFE.allocateInstance(clazz);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package dev.brighten.ac.utils;
|
||||
|
||||
import dev.brighten.ac.Anticheat;
|
||||
import dev.brighten.ac.utils.reflections.impl.CraftReflection;
|
||||
import dev.brighten.ac.utils.reflections.impl.MinecraftReflection;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class ServerInjector {
|
||||
private static final Collection<String> TICKABLE_CLASS_NAMES = Arrays.asList("IUpdatePlayerListBox", "ITickable", "Runnable");
|
||||
private Field hookedField;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public void inject() throws Exception {
|
||||
// Start end of tick injection
|
||||
Object server = CraftReflection.getMinecraftServer();
|
||||
Class<?> serverClass = MinecraftReflection.minecraftServer.getParent();
|
||||
|
||||
// Inject our hooked list for end of tick
|
||||
for (Field field : serverClass.getDeclaredFields()) {
|
||||
try {
|
||||
if (field.getType().equals(List.class)) {
|
||||
// Check if type parameters match one of the tickable class names used throughout different versions
|
||||
Class<?> genericType = (Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
|
||||
if (!ServerInjector.TICKABLE_CLASS_NAMES.contains(genericType.getSimpleName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
field.setAccessible(true);
|
||||
|
||||
// Use a list wrapper to check when the size method is called
|
||||
HookedListWrapper<?> wrapper = new HookedListWrapper<Object>((List) field.get(server)) {
|
||||
@Override
|
||||
public void onSize() {
|
||||
Runnable toRun = null;
|
||||
|
||||
while((toRun = Anticheat.INSTANCE.getOnTickEnd().poll()) != null) {
|
||||
toRun.run();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ReflectionUtil.setUnsafe(server, field, wrapper);
|
||||
this.hookedField = field;
|
||||
break;
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void eject() throws Exception {
|
||||
// Replace hooked wrapper with original
|
||||
if (this.hookedField != null) {
|
||||
Object server = CraftReflection.getMinecraftServer();
|
||||
|
||||
HookedListWrapper<?> hookedListWrapper = (HookedListWrapper<?>) this.hookedField.get(server);
|
||||
|
||||
ReflectionUtil.setUnsafe(server, this.hookedField, hookedListWrapper.getBase());
|
||||
this.hookedField = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package dev.brighten.ac.utils;
|
||||
|
||||
|
||||
import dev.brighten.ac.Anticheat;
|
||||
|
||||
public class TickTimer {
|
||||
private int ticks = Anticheat.INSTANCE.getCurrentTicks(), defaultPassed;
|
||||
|
||||
public TickTimer(int defaultPassed) {
|
||||
this.defaultPassed = defaultPassed;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
ticks = Anticheat.INSTANCE.getCurrentTicks();
|
||||
}
|
||||
|
||||
public boolean hasPassed() {
|
||||
return Anticheat.INSTANCE.getCurrentTicks() - ticks > defaultPassed;
|
||||
}
|
||||
|
||||
public boolean hasPassed(int amount) {
|
||||
return Anticheat.INSTANCE.getCurrentTicks() - ticks > amount;
|
||||
}
|
||||
|
||||
public boolean hasNotPassed() {
|
||||
return Anticheat.INSTANCE.getCurrentTicks() - ticks <= defaultPassed;
|
||||
}
|
||||
|
||||
public boolean hasNotPassed(int amount) {
|
||||
return Anticheat.INSTANCE.getCurrentTicks() - ticks <= amount;
|
||||
}
|
||||
|
||||
public int getPassed() {
|
||||
return Anticheat.INSTANCE.getCurrentTicks() - ticks;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package dev.brighten.ac.utils;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Triad<A, B, C> {
|
||||
public A first;
|
||||
public B second;
|
||||
public C third;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Triad<?, ?, ?> triad = (Triad<?, ?, ?>) o;
|
||||
return Objects.equals(first, triad.first) && Objects.equals(second, triad.second) && Objects.equals(third, triad.third);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(first, second, third);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package dev.brighten.ac.utils;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@NoArgsConstructor
|
||||
public class Tuple<A, B> {
|
||||
public A one;
|
||||
@@ -11,4 +13,25 @@ public class Tuple<A, B> {
|
||||
this.one = one;
|
||||
this.two = two;
|
||||
}
|
||||
|
||||
public boolean equals(Object object) {
|
||||
if (object instanceof Tuple) {
|
||||
Tuple toCompare = (Tuple) object;
|
||||
|
||||
return one.equals(toCompare.one) && two.equals(toCompare.two);
|
||||
} else return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Tuple{" +
|
||||
"one=" + one +
|
||||
", two=" + two +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(one, two);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package dev.brighten.ac.utils.reflections;
|
||||
|
||||
import dev.brighten.ac.packet.ProtocolVersion;
|
||||
import dev.brighten.ac.utils.ClassScanner;
|
||||
import dev.brighten.ac.utils.objects.QuadFunction;
|
||||
import dev.brighten.ac.utils.objects.TriFunction;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedClass;
|
||||
@@ -22,18 +21,14 @@ import java.lang.invoke.LambdaMetafactory;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Getter
|
||||
public class Reflections {
|
||||
private static final String craftBukkitString;
|
||||
private static final String netMinecraftServerString;
|
||||
private static MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
private static Set<String> classNames;
|
||||
public static String OBC_PREFIX = Bukkit.getServer().getClass().getPackage().getName();
|
||||
public static String VERSION = OBC_PREFIX.replace("org.bukkit.craftbukkit", "")
|
||||
.replace(".", "");
|
||||
@@ -42,13 +37,6 @@ public class Reflections {
|
||||
String version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
|
||||
craftBukkitString = "org.bukkit.craftbukkit." + version + ".";
|
||||
netMinecraftServerString = "net.minecraft.server." + version + ".";
|
||||
|
||||
try {
|
||||
classNames = ClassScanner.scanFile2(null,
|
||||
Class.forName("org.bukkit.craftbukkit.Main"));
|
||||
} catch(ClassNotFoundException e) {
|
||||
classNames = Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean classExists(String name) {
|
||||
@@ -69,18 +57,14 @@ public class Reflections {
|
||||
try {
|
||||
return getClass(netMinecraftServerString + name);
|
||||
} catch(Throwable e) {
|
||||
Pattern toTest = Pattern.compile("\\." + name.replace("$", ".") + "$");
|
||||
for (String className : classNames) {
|
||||
if(!className.startsWith("net.minecraft")) continue;
|
||||
|
||||
if(toTest.matcher(className).find()) {
|
||||
return getClass(className);
|
||||
}
|
||||
}
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
}
|
||||
|
||||
public void hi() {
|
||||
System.out.println("hi");
|
||||
}
|
||||
|
||||
public static WrappedClass getClass(String name) {
|
||||
try {
|
||||
return new WrappedClass(Class.forName(name));
|
||||
|
||||
@@ -100,7 +100,8 @@ public class WrappedClass {
|
||||
}
|
||||
|
||||
public WrappedConstructor getConstructor() {
|
||||
val optional = Arrays.stream(this.parent.getConstructors()).filter(cons -> cons.getParameterCount() == 0).findFirst();
|
||||
val optional = Arrays.stream(this.parent.getConstructors())
|
||||
.filter(cons -> cons.getParameterCount() == 0).findFirst();
|
||||
return optional.map(constructor -> new WrappedConstructor(this, constructor)).orElse(null);
|
||||
}
|
||||
|
||||
@@ -160,6 +161,20 @@ public class WrappedClass {
|
||||
return this.getFieldByType(type, 0);
|
||||
}
|
||||
|
||||
public WrappedMethod[] getDeclaredMethods() {
|
||||
return Arrays.stream(getParent().getDeclaredMethods())
|
||||
.map(m -> new WrappedMethod(this, m))
|
||||
.toArray(WrappedMethod[]::new);
|
||||
}
|
||||
|
||||
public boolean isAssignableFrom(WrappedClass wrapped) {
|
||||
return wrapped.getParent().isAssignableFrom(getParent());
|
||||
}
|
||||
|
||||
public boolean isAssignableFrom(Class<?> paramClass) {
|
||||
return getParent().isAssignableFrom(paramClass);
|
||||
}
|
||||
|
||||
public WrappedMethod getMethod(String name, Class... parameters) {
|
||||
String key = name + ";;" + Arrays.stream(parameters).map(Class::getName)
|
||||
.collect(Collectors.joining(","));
|
||||
|
||||
@@ -14,7 +14,9 @@ import dev.brighten.ac.utils.objects.TriFunction;
|
||||
import dev.brighten.ac.utils.reflections.Reflections;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
@@ -69,6 +71,18 @@ public class WrappedMethod {
|
||||
return mfunc.invokeMethod(object, args);
|
||||
}
|
||||
|
||||
public boolean isAnnotationPresent(Class<? extends Annotation> annotation) {
|
||||
return method.isAnnotationPresent(annotation);
|
||||
}
|
||||
|
||||
public Parameter[] getParameters() {
|
||||
return method.getParameters();
|
||||
}
|
||||
|
||||
public Class<?>[] getParameterTypes() {
|
||||
return method.getParameterTypes();
|
||||
}
|
||||
|
||||
public int getModifiers() {
|
||||
return this.method.getModifiers();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package dev.brighten.ac.utils.timer;
|
||||
|
||||
public interface Timer {
|
||||
|
||||
boolean isPassed(long stamp);
|
||||
|
||||
boolean isPassed();
|
||||
|
||||
boolean isNotPassed(long stamp);
|
||||
|
||||
boolean isNotPassed();
|
||||
|
||||
boolean isReset();
|
||||
|
||||
int getResetStreak();
|
||||
|
||||
long getPassed();
|
||||
|
||||
long getCurrent();
|
||||
|
||||
void reset();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package dev.brighten.ac.utils.timer.impl;
|
||||
|
||||
import dev.brighten.ac.utils.timer.Timer;
|
||||
|
||||
public class MillisTimer implements Timer {
|
||||
|
||||
private long currentStamp;
|
||||
private int resetStreak;
|
||||
private final long defaultPassed;
|
||||
|
||||
public MillisTimer(long defaultPassed) {
|
||||
this.defaultPassed = defaultPassed;
|
||||
}
|
||||
|
||||
public MillisTimer() {
|
||||
defaultPassed = 1000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPassed(long stamp) {
|
||||
return getPassed() > stamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPassed() {
|
||||
return getPassed() > defaultPassed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotPassed(long stamp) {
|
||||
return getPassed() <= stamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotPassed() {
|
||||
return getPassed() <= defaultPassed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReset() {
|
||||
return getPassed() <= 1L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getResetStreak() {
|
||||
return resetStreak;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getPassed() {
|
||||
return System.currentTimeMillis() - currentStamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCurrent() {
|
||||
return currentStamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
if(getPassed() <= 60L) resetStreak++;
|
||||
else resetStreak = 0;
|
||||
|
||||
currentStamp = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package dev.brighten.ac.utils.timer.impl;
|
||||
|
||||
import dev.brighten.ac.Anticheat;
|
||||
import dev.brighten.ac.utils.timer.Timer;
|
||||
|
||||
public class TickTimer implements Timer {
|
||||
private long currentStamp;
|
||||
private int resetStreak;
|
||||
private final long defaultPassed;
|
||||
|
||||
public TickTimer(long defaultPassed) {
|
||||
this.defaultPassed = defaultPassed;
|
||||
currentStamp = Anticheat.INSTANCE.getCurrentTick();
|
||||
}
|
||||
|
||||
public TickTimer() {
|
||||
defaultPassed = 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPassed(long stamp) {
|
||||
return getPassed() > stamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPassed() {
|
||||
return getPassed() > defaultPassed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotPassed(long stamp) {
|
||||
return getPassed() <= stamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotPassed() {
|
||||
return getPassed() <= defaultPassed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReset() {
|
||||
return getPassed() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getResetStreak() {
|
||||
return resetStreak;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getPassed() {
|
||||
return Anticheat.INSTANCE.getCurrentTick()- currentStamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCurrent() {
|
||||
return currentStamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
if(getPassed() <= 1) resetStreak++;
|
||||
else resetStreak = 0;
|
||||
|
||||
currentStamp = Anticheat.INSTANCE.getCurrentTick();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.brighten.ac.utils.world.types;
|
||||
|
||||
import dev.brighten.ac.utils.BoundingBox;
|
||||
import dev.brighten.ac.utils.KLocation;
|
||||
import dev.brighten.ac.utils.reflections.impl.MinecraftReflection;
|
||||
import dev.brighten.ac.utils.world.CollisionBox;
|
||||
import org.bukkit.Location;
|
||||
@@ -51,7 +52,11 @@ public class SimpleCollisionBox implements CollisionBox {
|
||||
public SimpleCollisionBox(Vector min, Vector max) {
|
||||
this(min.getX(), min.getY(), min.getZ(), max.getX(), max.getY(), max.getZ());
|
||||
}
|
||||
|
||||
|
||||
public SimpleCollisionBox(KLocation loc, double width, double height) {
|
||||
this(loc.toVector(), width, height);
|
||||
}
|
||||
|
||||
public SimpleCollisionBox(Location loc, double width, double height) {
|
||||
this(loc.toVector(), width, height);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user