diff --git a/pom.xml b/pom.xml
index 04586d3..182f8fe 100644
--- a/pom.xml
+++ b/pom.xml
@@ -26,6 +26,10 @@
jitpack.io
https://jitpack.io
+
+ lucko
+ https://repo.lucko.me/
+
@@ -57,23 +61,6 @@
shade
-
- true
-
-
- com.google.common
- dev.brighten.ac.com.google.common
-
-
- it.unimi.dsi
- dev.brighten.ac.it.unimi.dsi
-
-
- co.aikar.commands
- dev.brighten.ac.co.aikar.commands
-
-
-
@@ -114,8 +101,8 @@
com.h2database
h2
- 2.1.214
- compile
+ 1.4.199
+ provided
org.github.spigot
@@ -127,7 +114,7 @@
it.unimi.dsi
fastutil
8.5.6
- compile
+ provided
com.shevchik.protocolsupport
@@ -145,25 +132,25 @@
com.google.guava
guava
31.1-jre
- compile
+ provided
org.ow2.asm
asm
9.2
- compile
+ provided
org.ow2.asm
asm-tree
9.2
- compile
+ provided
co.aikar
acf-bukkit
0.5.0-SNAPSHOT
- compile
+ provided
diff --git a/src/main/java/dev/brighten/ac/Anticheat.java b/src/main/java/dev/brighten/ac/Anticheat.java
index 85e0900..4d778bd 100644
--- a/src/main/java/dev/brighten/ac/Anticheat.java
+++ b/src/main/java/dev/brighten/ac/Anticheat.java
@@ -7,12 +7,19 @@ import dev.brighten.ac.api.AnticheatAPI;
import dev.brighten.ac.check.Check;
import dev.brighten.ac.check.CheckManager;
import dev.brighten.ac.data.PlayerRegistry;
+import dev.brighten.ac.depends.LibraryLoader;
+import dev.brighten.ac.depends.MavenLibrary;
+import dev.brighten.ac.depends.Repository;
import dev.brighten.ac.handler.PacketHandler;
import dev.brighten.ac.handler.keepalive.KeepaliveProcessor;
import dev.brighten.ac.handler.protocolsupport.ProtocolAPI;
+import dev.brighten.ac.logging.LoggerManager;
import dev.brighten.ac.packet.handler.HandlerAbstract;
import dev.brighten.ac.packet.listener.PacketProcessor;
import dev.brighten.ac.utils.*;
+import dev.brighten.ac.utils.annotation.ConfigSetting;
+import dev.brighten.ac.utils.annotation.Init;
+import dev.brighten.ac.utils.annotation.Invoke;
import dev.brighten.ac.utils.math.RollingAverageDouble;
import dev.brighten.ac.utils.objects.RemoteClassLoader;
import dev.brighten.ac.utils.reflections.Reflections;
@@ -40,6 +47,12 @@ import java.util.concurrent.atomic.AtomicLong;
@Getter
@Init
+@MavenLibrary(groupId = "co.aikar", artifactId = "acf-bukkit", version = "0.5.0", repo = @Repository(url = "https://nexus.funkemunky.cc/content/repositories/releases/"))
+@MavenLibrary(groupId = "com.google.guava", artifactId = "guava", version = "21.0", repo = @Repository(url = "https://repo1.maven.org/maven2"))
+@MavenLibrary(groupId = "com.h2database", artifactId = "h2", version = "1.4.199", repo = @Repository(url = "https://repo1.maven.org/maven2"))
+@MavenLibrary(groupId = "it.unimi.dsi", artifactId = "fastutil", version = "8.5.6", repo = @Repository(url = "https://repo1.maven.org/maven2"))
+@MavenLibrary(groupId = "org.ow2.asm", artifactId = "asm", version = "9.2", repo = @Repository(url = "https://repo1.maven.org/maven2"))
+@MavenLibrary(groupId = "org.ow2.asm", artifactId = "asm-tree", version = "9.2", repo = @Repository(url = "https://repo1.maven.org/maven2"))
public class Anticheat extends JavaPlugin {
public static Anticheat INSTANCE;
@@ -51,6 +64,7 @@ public class Anticheat extends JavaPlugin {
private PlayerRegistry playerRegistry;
private KeepaliveProcessor keepaliveProcessor;
private PacketHandler packetHandler;
+ private LoggerManager logManager;
private int currentTick;
private Deque onTickEnd = new LinkedList<>();
private ServerInjector injector;
@@ -68,6 +82,7 @@ public class Anticheat extends JavaPlugin {
public void onEnable() {
INSTANCE = this;
+ LibraryLoader.loadAll(getClass());
scheduler = Executors.newScheduledThreadPool(2, new ThreadFactoryBuilder()
.setNameFormat("Anticheat Schedular")
@@ -98,12 +113,15 @@ public class Anticheat extends JavaPlugin {
getConfig().set("database.password", UUID.randomUUID().toString());
}
+ HandlerAbstract.init();
+
this.keepaliveProcessor = new KeepaliveProcessor();
this.checkManager = new CheckManager();
this.playerRegistry = new PlayerRegistry();
this.packetHandler = new PacketHandler();
+ logManager = new LoggerManager();
- HandlerAbstract.init();
+ logManager.init();
alog(Color.Green + "Loading WorldInfo system...");
Bukkit.getWorlds().forEach(w -> worldInfoMap.put(w.getUID(), new WorldInfo(w)));
@@ -114,6 +132,8 @@ public class Anticheat extends JavaPlugin {
} catch (Exception e) {
e.printStackTrace();
}
+
+ Bukkit.getOnlinePlayers().forEach(HandlerAbstract.getHandler()::add);
}
public void onDisable() {
@@ -134,6 +154,8 @@ public class Anticheat extends JavaPlugin {
ProtocolAPI.INSTANCE = null;
tps = null;
+ logManager.shutDown();
+
Bukkit.getScheduler().cancelTasks(this);
diff --git a/src/main/java/dev/brighten/ac/check/Check.java b/src/main/java/dev/brighten/ac/check/Check.java
index 5f37ed6..7d9ddd4 100644
--- a/src/main/java/dev/brighten/ac/check/Check.java
+++ b/src/main/java/dev/brighten/ac/check/Check.java
@@ -148,6 +148,8 @@ public class Check implements ECheck {
if(currentResult.isCancelled()) return;
+ Anticheat.INSTANCE.getLogManager().insertLog(player, checkData, vl, System.currentTimeMillis(), info);
+
boolean dev = Anticheat.INSTANCE.getTps() < 18;
//if(vl > 0) Anticheat.INSTANCE.loggerManager.addLog(player, this, info);
diff --git a/src/main/java/dev/brighten/ac/check/CheckConfig.java b/src/main/java/dev/brighten/ac/check/CheckConfig.java
index 23a4789..47c8006 100644
--- a/src/main/java/dev/brighten/ac/check/CheckConfig.java
+++ b/src/main/java/dev/brighten/ac/check/CheckConfig.java
@@ -1,7 +1,7 @@
package dev.brighten.ac.check;
-import dev.brighten.ac.utils.ConfigSetting;
-import dev.brighten.ac.utils.Init;
+import dev.brighten.ac.utils.annotation.ConfigSetting;
+import dev.brighten.ac.utils.annotation.Init;
import java.util.Arrays;
import java.util.List;
diff --git a/src/main/java/dev/brighten/ac/check/CheckManager.java b/src/main/java/dev/brighten/ac/check/CheckManager.java
index 2976e8a..94cab21 100644
--- a/src/main/java/dev/brighten/ac/check/CheckManager.java
+++ b/src/main/java/dev/brighten/ac/check/CheckManager.java
@@ -11,6 +11,7 @@ import java.util.Map;
@Getter
public class CheckManager {
private final Map checkClasses = new HashMap<>();
+ private final Map idToName = new HashMap<>();
public CheckManager() {
synchronized (checkClasses) {
@@ -33,6 +34,7 @@ public class CheckManager {
Anticheat.INSTANCE.alog(true, "&7Adding check to CheckManager: " + checkData.name());
checkClasses.put(checkData.name(), check);
+ idToName.put(checkData.checkId(), checkData.name());
}
public boolean isCheck(String name) {
diff --git a/src/main/java/dev/brighten/ac/check/impl/combat/Aim.java b/src/main/java/dev/brighten/ac/check/impl/combat/Aim.java
index 477eb4a..d8f009b 100644
--- a/src/main/java/dev/brighten/ac/check/impl/combat/Aim.java
+++ b/src/main/java/dev/brighten/ac/check/impl/combat/Aim.java
@@ -1,12 +1,11 @@
package dev.brighten.ac.check.impl.combat;
-import dev.brighten.ac.check.WAction;
+import dev.brighten.ac.api.check.CheckType;
import dev.brighten.ac.check.Check;
import dev.brighten.ac.check.CheckData;
-import dev.brighten.ac.api.check.CheckType;
+import dev.brighten.ac.check.WAction;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
-import dev.brighten.ac.utils.Async;
import dev.brighten.ac.utils.Color;
import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.TickTimer;
@@ -22,8 +21,6 @@ public class Aim extends Check {
private float buffer;
protected Timer lastGrid = new TickTimer(3);
-
- @Async
WAction onFlying = (packet) -> {
if(!packet.isLooked()) return;
diff --git a/src/main/java/dev/brighten/ac/check/impl/combat/Hitbox.java b/src/main/java/dev/brighten/ac/check/impl/combat/Hitbox.java
index f941f21..bb1eb06 100644
--- a/src/main/java/dev/brighten/ac/check/impl/combat/Hitbox.java
+++ b/src/main/java/dev/brighten/ac/check/impl/combat/Hitbox.java
@@ -79,7 +79,7 @@ public class Hitbox extends Check {
EntityData.getEntityBox(oldLocation.toVector(), target.one);
if(player.getPlayerVersion().isBelow(ProtocolVersion.V1_9)) {
- box = box.expand(0.105);
+ box = box.expand(0.1325);
} else box = box.expand(0.0325);
boxes.add(box);
}
@@ -88,7 +88,7 @@ public class Hitbox extends Check {
EntityData.getEntityBox(oldLocation.toVector(), target.one);
if(player.getPlayerVersion().isBelow(ProtocolVersion.V1_9)) {
- box = box.expand(0.105);
+ box = box.expand(0.1325);
} else box = box.expand(0.0325);
boxes.add(box);
}
@@ -98,7 +98,7 @@ public class Hitbox extends Check {
EntityData.getEntityBox(oldLocation.toVector(), target.one);
if(player.getPlayerVersion().isBelow(ProtocolVersion.V1_9)) {
- box = box.expand(0.105);
+ box = box.expand(0.1325);
} else box = box.expand(0.0325);
boxes.add(box);
}
@@ -168,7 +168,7 @@ public class Hitbox extends Check {
if(hbuffer > 0) hbuffer--;
- debug("buffer: %.3f distance=%.2f hits=%s", buffer, distance, hits);
+ debug("buffer: %.3f distance=%.2f hits=%s sneaking=%s", buffer, distance, hits, player.getInfo().isSneaking());
} else if(player.getEntityLocationHandler().streak > 1) {
if (++hbuffer > 5) {
flag("%.1f;%.1f;%.1f", eloc.one.x, eloc.one.y, eloc.one.z);
diff --git a/src/main/java/dev/brighten/ac/check/impl/combat/autoclicker/AutoclickerA.java b/src/main/java/dev/brighten/ac/check/impl/combat/autoclicker/AutoclickerA.java
index 9f80f37..b1858c3 100644
--- a/src/main/java/dev/brighten/ac/check/impl/combat/autoclicker/AutoclickerA.java
+++ b/src/main/java/dev/brighten/ac/check/impl/combat/autoclicker/AutoclickerA.java
@@ -8,7 +8,7 @@ import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.packet.ProtocolVersion;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInArmAnimation;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
-import dev.brighten.ac.utils.Async;
+import dev.brighten.ac.utils.annotation.Async;
@CheckData(name = "AutoClicker (A)", checkId = "autoclickera", type = CheckType.AUTOCLICKER, maxVersion = ProtocolVersion.V1_8_9)
public class AutoclickerA extends Check {
diff --git a/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyA.java b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyA.java
index 973b6b6..6ed130c 100644
--- a/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyA.java
+++ b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyA.java
@@ -7,7 +7,7 @@ import dev.brighten.ac.api.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.Async;
+import dev.brighten.ac.utils.annotation.Async;
import dev.brighten.ac.utils.MathUtils;
import dev.brighten.ac.utils.MovementUtils;
import dev.brighten.ac.utils.timer.Timer;
diff --git a/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyB.java b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyB.java
index 0b2614b..e95c022 100644
--- a/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyB.java
+++ b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyB.java
@@ -6,7 +6,7 @@ import dev.brighten.ac.check.CheckData;
import dev.brighten.ac.api.check.CheckType;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
-import dev.brighten.ac.utils.Async;
+import dev.brighten.ac.utils.annotation.Async;
import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.TickTimer;
diff --git a/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyC.java b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyC.java
index 8dd82d3..d2aaa3f 100644
--- a/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyC.java
+++ b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyC.java
@@ -6,7 +6,6 @@ import dev.brighten.ac.check.CheckData;
import dev.brighten.ac.check.WAction;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
-import dev.brighten.ac.utils.Async;
import dev.brighten.ac.utils.MathUtils;
import dev.brighten.ac.utils.MovementUtils;
@@ -23,6 +22,7 @@ public class FlyC extends Check {
WAction flyingAction = packet -> {
if(player.getMovement().getLastTeleport().isNotPassed((1))
+ || player.getMovement().getMoveTicks() <= 2
|| player.getInfo().isGeneralCancel())
return;
final boolean ground = player.getMovement().getTo().isOnGround(),
@@ -44,7 +44,7 @@ public class FlyC extends Check {
for (Double possibleHeight : possibleHeights) {
double delta = MathUtils.getDelta(player.getMovement().getDeltaY(), possibleHeight);
- if(delta < 1E-5) {
+ if(delta < (player.getInfo().getLastBlockPlace().isNotPassed(20) ? 0.02 : 0.005)) {
debug("Found delta: dy=%.5f, p=%.5f", player.getMovement().getDeltaY(), possibleHeight);
break jumpCheck;
}
diff --git a/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyD.java b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyD.java
new file mode 100644
index 0000000..7c0ddd0
--- /dev/null
+++ b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyD.java
@@ -0,0 +1,34 @@
+package dev.brighten.ac.check.impl.movement.fly;
+
+import dev.brighten.ac.api.check.CheckType;
+import dev.brighten.ac.check.Check;
+import dev.brighten.ac.check.CheckData;
+import dev.brighten.ac.check.WAction;
+import dev.brighten.ac.data.APlayer;
+import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
+import dev.brighten.ac.utils.annotation.Async;
+
+@CheckData(name = "Fly (D)", checkId = "flyd", type = CheckType.MOVEMENT)
+public class FlyD extends Check {
+ public FlyD(APlayer player) {
+ super(player);
+ }
+
+ private double totalY;
+
+ @Async
+ WAction flyingPacket = packet -> {
+ if(!packet.isMoved() || player.getMovement().getMoveTicks() <= 2) return;
+ double deltaY = player.getMovement().getDeltaY();
+
+ if(deltaY > 0)
+ totalY+= deltaY;
+ else {
+ if(totalY % 0.25 < 1E-6 && totalY > 0.6) {
+ flag("totalY=%s gt=%s", totalY, player.getMovement().getGroundTicks());
+ }
+ debug("totalY=%s", totalY);
+ totalY = 0;
+ }
+ };
+}
diff --git a/src/main/java/dev/brighten/ac/check/impl/movement/nofall/NoFallA.java b/src/main/java/dev/brighten/ac/check/impl/movement/nofall/NoFallA.java
index 91bafbb..8a6201d 100644
--- a/src/main/java/dev/brighten/ac/check/impl/movement/nofall/NoFallA.java
+++ b/src/main/java/dev/brighten/ac/check/impl/movement/nofall/NoFallA.java
@@ -6,7 +6,7 @@ import dev.brighten.ac.check.CheckData;
import dev.brighten.ac.api.check.CheckType;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
-import dev.brighten.ac.utils.Async;
+import dev.brighten.ac.utils.annotation.Async;
@CheckData(name = "NoFall (A)", checkId = "nofalla", type = CheckType.MOVEMENT)
public class NoFallA extends Check {
diff --git a/src/main/java/dev/brighten/ac/check/impl/movement/nofall/NoFallB.java b/src/main/java/dev/brighten/ac/check/impl/movement/nofall/NoFallB.java
index fa6998c..5516e6c 100644
--- a/src/main/java/dev/brighten/ac/check/impl/movement/nofall/NoFallB.java
+++ b/src/main/java/dev/brighten/ac/check/impl/movement/nofall/NoFallB.java
@@ -6,7 +6,7 @@ import dev.brighten.ac.check.CheckData;
import dev.brighten.ac.api.check.CheckType;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
-import dev.brighten.ac.utils.Async;
+import dev.brighten.ac.utils.annotation.Async;
@CheckData(name = "NoFall (B)", checkId = "nofallb", type = CheckType.MOVEMENT)
public class NoFallB extends Check {
diff --git a/src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java b/src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java
index 1e39848..55c00d1 100644
--- a/src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java
+++ b/src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java
@@ -1,13 +1,12 @@
package dev.brighten.ac.check.impl.movement.speed;
-import dev.brighten.ac.check.WAction;
+import dev.brighten.ac.api.check.CheckType;
import dev.brighten.ac.check.Check;
import dev.brighten.ac.check.CheckData;
-import dev.brighten.ac.api.check.CheckType;
+import dev.brighten.ac.check.WAction;
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.Async;
import dev.brighten.ac.utils.BlockUtils;
import dev.brighten.ac.utils.MathHelper;
import dev.brighten.ac.utils.math.IntVector;
@@ -34,7 +33,6 @@ public class Horizontal extends Check {
super(player);
}
- @Async
WAction flying = packet -> {
Block underBlock = BlockUtils.getBlock(player.getMovement().getTo().getLoc()
.toLocation(player.getBukkitPlayer().getWorld())
@@ -147,6 +145,11 @@ public class Horizontal extends Check {
if (Math.abs(lmotionZ) < 0.005)
lmotionZ = 0;
}
+
+ //Less than 0.05
+ if(((lmotionX * lmotionX) + (lmotionZ * lmotionZ)) < 0.0025 && player.getMovement().getDeltaXZ() < 0.1) {
+ break check;
+ }
// Attack slowdown
if (attack) {
lmotionX *= 0.6;
diff --git a/src/main/java/dev/brighten/ac/check/impl/world/BlockA.java b/src/main/java/dev/brighten/ac/check/impl/world/BlockA.java
index 5077eeb..de5afc1 100644
--- a/src/main/java/dev/brighten/ac/check/impl/world/BlockA.java
+++ b/src/main/java/dev/brighten/ac/check/impl/world/BlockA.java
@@ -9,6 +9,7 @@ import dev.brighten.ac.packet.ProtocolVersion;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInBlockPlace;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
import dev.brighten.ac.utils.*;
+import dev.brighten.ac.utils.annotation.Async;
import dev.brighten.ac.utils.math.cond.MaxDouble;
import dev.brighten.ac.utils.world.BlockData;
import dev.brighten.ac.utils.world.CollisionBox;
diff --git a/src/main/java/dev/brighten/ac/check/impl/world/BlockB.java b/src/main/java/dev/brighten/ac/check/impl/world/BlockB.java
index 4fa959b..7aeab3a 100644
--- a/src/main/java/dev/brighten/ac/check/impl/world/BlockB.java
+++ b/src/main/java/dev/brighten/ac/check/impl/world/BlockB.java
@@ -5,7 +5,7 @@ import dev.brighten.ac.check.Check;
import dev.brighten.ac.check.CheckData;
import dev.brighten.ac.api.check.CheckType;
import dev.brighten.ac.data.APlayer;
-import dev.brighten.ac.utils.Async;
+import dev.brighten.ac.utils.annotation.Async;
import org.bukkit.block.Block;
import org.bukkit.event.block.BlockPlaceEvent;
diff --git a/src/main/java/dev/brighten/ac/command/AnticheatCommand.java b/src/main/java/dev/brighten/ac/command/AnticheatCommand.java
index 4051507..0212a39 100644
--- a/src/main/java/dev/brighten/ac/command/AnticheatCommand.java
+++ b/src/main/java/dev/brighten/ac/command/AnticheatCommand.java
@@ -6,9 +6,11 @@ import co.aikar.commands.bukkit.contexts.OnlinePlayer;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.check.Check;
import dev.brighten.ac.data.APlayer;
+import dev.brighten.ac.logging.Log;
import dev.brighten.ac.messages.Messages;
import dev.brighten.ac.packet.handler.HandlerAbstract;
import dev.brighten.ac.utils.*;
+import dev.brighten.ac.utils.annotation.Init;
import dev.brighten.ac.utils.msg.ChatBuilder;
import io.netty.buffer.Unpooled;
import lombok.val;
@@ -23,6 +25,8 @@ import org.bukkit.entity.Player;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Comparator;
+import java.util.List;
+import java.util.UUID;
import java.util.stream.Collectors;
@Init(priority = Priority.LOW)
@@ -107,6 +111,40 @@ public class AnticheatCommand extends BaseCommand {
}
}
+ @Subcommand("logs")
+ @Syntax("[player]")
+ @CommandCompletion("@players")
+ @CommandPermission("anticheat.command.logs")
+ @Description("Get player logs")
+ public void onLogs(CommandSender sender, @Single String playername) {
+ UUID uuid = Bukkit.getOfflinePlayer(playername).getUniqueId();
+
+ sender.sendMessage(Color.Red + "Getting logs for " + playername + "...");
+
+ Anticheat.INSTANCE.getScheduler().execute(() -> {
+ List logs = new ArrayList<>();
+ Anticheat.INSTANCE.getLogManager().runQuery("select * from logs where uuid=" + uuid.hashCode(), rs -> {
+ Log log = Log.builder()
+ .uuid(UUID.fromString(rs.getString("uuid")))
+ .checkId(rs.getString("check"))
+ .data(rs.getString("data"))
+ .vl(rs.getFloat("vl"))
+ .time(rs.getLong("time"))
+ .build();
+
+ logs.add("Flagged " + Anticheat.INSTANCE.getCheckManager().getIdToName().get(log.getCheckId()) + " data: " + log.getData() + " VL: " + log.getVl() + " at " + log.getTime());
+ });
+ String url = null;
+ try {
+ url = Pastebin.makePaste(String.join("\n", logs), playername + "'s Logs", Pastebin.Privacy.UNLISTED);
+
+ sender.sendMessage(Color.Green + "Logs for " + playername + ": " + Color.White + url);
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+
@Subcommand("title")
@Private
public void onTitle(CommandSender sender, OnlinePlayer target, String title) {
diff --git a/src/main/java/dev/brighten/ac/data/handlers/CheckHandler.java b/src/main/java/dev/brighten/ac/data/handlers/CheckHandler.java
index 8329e52..6fda566 100644
--- a/src/main/java/dev/brighten/ac/data/handlers/CheckHandler.java
+++ b/src/main/java/dev/brighten/ac/data/handlers/CheckHandler.java
@@ -7,7 +7,7 @@ import dev.brighten.ac.data.obj.ActionStore;
import dev.brighten.ac.data.obj.CancellableActionStore;
import dev.brighten.ac.data.obj.TimedActionStore;
import dev.brighten.ac.handler.thread.ThreadHandler;
-import dev.brighten.ac.utils.Async;
+import dev.brighten.ac.utils.annotation.Async;
import dev.brighten.ac.utils.Tuple;
import dev.brighten.ac.utils.reflections.types.WrappedField;
import lombok.RequiredArgsConstructor;
@@ -63,7 +63,6 @@ public class CheckHandler {
WAction> action = tuple.one.get(check);
if(!tuple.one.getField().isAnnotationPresent(Async.class)) {
- System.out.println("Adding sync event");
events.compute(tuple.two, (packetClass, array) -> {
if (array == null) {
return new ActionStore[] {new ActionStore(action, checkClass.getCheckClass().getParent())};
@@ -81,7 +80,6 @@ public class CheckHandler {
WAction> action = tuple.one.get(check);
if(tuple.one.getField().isAnnotationPresent(Async.class)) {
- System.out.println("Adding async event");
async_events.compute(tuple.two, (packetClass, array) -> {
if (array == null) {
return new ActionStore[] {new ActionStore(action, checkClass.getCheckClass().getParent())};
@@ -99,7 +97,6 @@ public class CheckHandler {
WTimedAction> action = tuple.one.get(check);
if(!tuple.one.getField().isAnnotationPresent(Async.class)) {
- System.out.println("Adding timed sync event");
eventsWithTimestamp.compute(tuple.two, (packetClass, array) -> {
if (array == null) {
return new TimedActionStore[] {new TimedActionStore(action, checkClass.getCheckClass().getParent())};
@@ -117,7 +114,6 @@ public class CheckHandler {
WTimedAction> action = tuple.one.get(check);
if(tuple.one.getField().isAnnotationPresent(Async.class)) {
- System.out.println("Adding timed async event");
async_eventsWithTimestamp.compute(tuple.two, (packetClass, array) -> {
if (array == null) {
return new TimedActionStore[] {new TimedActionStore(action, checkClass.getCheckClass().getParent())};
@@ -135,7 +131,6 @@ public class CheckHandler {
WCancellable> action = tuple.one.get(check);
if(!tuple.one.getField().isAnnotationPresent(Async.class)) {
- System.out.println("Adding cancel sync event");
cancellableEvents.compute(tuple.two, (packetClass, array) -> {
if (array == null) {
return new CancellableActionStore[] {new CancellableActionStore(action, checkClass.getCheckClass().getParent())};
@@ -177,7 +172,6 @@ public class CheckHandler {
//TODO When using WPacket wrappers only, make this strictly WPacket param based only
public void callPacket(Object packet, long timestamp) {
- //System.out.println("Being called");
ThreadHandler.INSTANCE.getThread(player).getThread().execute(() -> {
if(async_events.containsKey(packet.getClass())) {
synchronized (async_events) {
diff --git a/src/main/java/dev/brighten/ac/data/handlers/GeneralInformation.java b/src/main/java/dev/brighten/ac/data/handlers/GeneralInformation.java
index c80c145..2942997 100644
--- a/src/main/java/dev/brighten/ac/data/handlers/GeneralInformation.java
+++ b/src/main/java/dev/brighten/ac/data/handlers/GeneralInformation.java
@@ -26,7 +26,8 @@ public class GeneralInformation {
lastSneak = new TickTimer(), velocity = new TickTimer(), lastCancel = new TickTimer(),
slimeTimer = new TickTimer(), lastElytra = new TickTimer(), blockAbove = new TickTimer(),
lastPlace = new TickTimer(), climbTimer = new TickTimer(), lastUseItem = new TickTimer(),
- lastLiquid = new TickTimer(), lastBlockDig = new TickTimer(), lastBlockPlace = new TickTimer();
+ lastLiquid = new TickTimer(), lastBlockDig = new TickTimer(), lastBlockPlace = new TickTimer(),
+ lastBlockUpdate = new TickTimer();
public LivingEntity target;
public boolean serverGround, lastServerGround, canFly, nearGround, worldLoaded, generalCancel, inVehicle, creative,
sneaking, lsneaking, sprinting, gliding, riptiding, wasOnSlime, onLadder, doingVelocity, breakingBlock;
diff --git a/src/main/java/dev/brighten/ac/data/handlers/MovementHandler.java b/src/main/java/dev/brighten/ac/data/handlers/MovementHandler.java
index 73fdc1e..0a5c3f6 100644
--- a/src/main/java/dev/brighten/ac/data/handlers/MovementHandler.java
+++ b/src/main/java/dev/brighten/ac/data/handlers/MovementHandler.java
@@ -58,7 +58,7 @@ public class MovementHandler {
@Getter
private float sensitivityX, sensitivityY, currentSensX, currentSensY, sensitivityMcp, yawMode, pitchMode;
@Getter
- private int sensXPercent, sensYPercent;
+ private int sensXPercent, sensYPercent, airTicks, groundTicks;
private int ticks;
private double lastX, lastY, lastLastY, lastYawAcelleration, lastPitchAcelleration;
private boolean inTick;
@@ -76,6 +76,7 @@ public class MovementHandler {
if (checkMovement) {
moveTicks++;
+ if(!packet.isMoved()) moveTicks = 1;
} else moveTicks = 0;
updateLocations(packet);
@@ -201,8 +202,13 @@ public class MovementHandler {
}
}
- if (player.getInfo().isServerGround()) {
+ if (packet.isOnGround()) {
player.getInfo().setWasOnSlime(player.getBlockInfo().onSlime);
+ groundTicks++;
+ airTicks = 0;
+ } else {
+ airTicks++;
+ groundTicks = 0;
}
player.getInfo().setCreative(player.getBukkitPlayer().getGameMode() == GameMode.CREATIVE
diff --git a/src/main/java/dev/brighten/ac/depends/LibraryLoader.java b/src/main/java/dev/brighten/ac/depends/LibraryLoader.java
new file mode 100644
index 0000000..dc26ee2
--- /dev/null
+++ b/src/main/java/dev/brighten/ac/depends/LibraryLoader.java
@@ -0,0 +1,201 @@
+/*
+ * This file is part of helper, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * Copyright (c) contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package dev.brighten.ac.depends;
+
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import dev.brighten.ac.Anticheat;
+import dev.brighten.ac.utils.Log;
+import dev.brighten.ac.utils.annotation.NonnullByDefault;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.util.Objects;
+
+/**
+ * Resolves {@link MavenLibrary} annotations for a class, and loads the dependency
+ * into the classloader.
+ */
+@NonnullByDefault
+public final class LibraryLoader {
+
+ @SuppressWarnings("Guava")
+ private static final Supplier URL_INJECTOR = Suppliers.memoize(() -> URLClassLoaderAccess.create((URLClassLoader) Anticheat.INSTANCE.getClass().getClassLoader()));
+
+ /**
+ * Resolves all {@link MavenLibrary} annotations on the given object.
+ *
+ * @param object the object to load libraries for.
+ */
+ public static void loadAll(Object object) {
+ loadAll(object.getClass());
+ }
+
+ /**
+ * Resolves all {@link MavenLibrary} annotations on the given class.
+ *
+ * @param clazz the class to load libraries for.
+ */
+ public static void loadAll(Class> clazz) {
+ MavenLibrary[] libs = clazz.getDeclaredAnnotationsByType(MavenLibrary.class);
+ if (libs == null) {
+ return;
+ }
+
+ for (MavenLibrary lib : libs) {
+ load(lib.groupId(), lib.artifactId(), lib.version(), lib.repo().url());
+ }
+ }
+
+ public static void load(String groupId, String artifactId, String version) {
+ load(groupId, artifactId, version, "https://repo1.maven.org/maven2");
+ }
+
+ public static void load(String groupId, String artifactId, String version, String repoUrl) {
+ load(new Dependency(groupId, artifactId, version, repoUrl));
+ }
+
+ public static void load(Dependency d) {
+ Log.info(String.format("Loading dependency %s:%s:%s from %s", d.getGroupId(), d.getArtifactId(), d.getVersion(), d.getRepoUrl()));
+ String name = d.getArtifactId() + "-" + d.getVersion();
+
+ File saveLocation = new File(getLibFolder(), name + ".jar");
+ if (!saveLocation.exists()) {
+
+ try {
+ Log.info("Dependency '" + name + "' is not already in the libraries folder. Attempting to download...");
+ URL url = d.getUrl();
+
+ try (InputStream is = url.openStream()) {
+ Files.copy(is, saveLocation.toPath());
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ Log.info("Dependency '" + name + "' successfully downloaded.");
+ }
+
+ if (!saveLocation.exists()) {
+ throw new RuntimeException("Unable to download dependency: " + d.toString());
+ }
+
+ try {
+ URL_INJECTOR.get().addURL(saveLocation.toURI().toURL());
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to load dependency: " + saveLocation.toString(), e);
+ }
+
+ Log.info("Loaded dependency '" + name + "' successfully.");
+ }
+
+ private static File getLibFolder() {
+ File pluginDataFolder = Anticheat.INSTANCE.getDataFolder();
+ File libs = new File(pluginDataFolder, "libraries");
+ libs.mkdirs();
+ return libs;
+ }
+
+ @NonnullByDefault
+ public static final class Dependency {
+ private final String groupId;
+ private final String artifactId;
+ private final String version;
+ private final String repoUrl;
+
+ public Dependency(String groupId, String artifactId, String version, String repoUrl) {
+ this.groupId = Objects.requireNonNull(groupId, "groupId");
+ this.artifactId = Objects.requireNonNull(artifactId, "artifactId");
+ this.version = Objects.requireNonNull(version, "version");
+ this.repoUrl = Objects.requireNonNull(repoUrl, "repoUrl");
+ }
+
+ public String getGroupId() {
+ return this.groupId;
+ }
+
+ public String getArtifactId() {
+ return this.artifactId;
+ }
+
+ public String getVersion() {
+ return this.version;
+ }
+
+ public String getRepoUrl() {
+ return this.repoUrl;
+ }
+
+ public URL getUrl() throws MalformedURLException {
+ String repo = this.repoUrl;
+ if (!repo.endsWith("/")) {
+ repo += "/";
+ }
+ repo += "%s/%s/%s/%s-%s.jar";
+
+ String url = String.format(repo, this.groupId.replace(".", "/"), this.artifactId, this.version, this.artifactId, this.version);
+ return new URL(url);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) return true;
+ if (!(o instanceof Dependency)) return false;
+ final Dependency other = (Dependency) o;
+ return this.getGroupId().equals(other.getGroupId()) &&
+ this.getArtifactId().equals(other.getArtifactId()) &&
+ this.getVersion().equals(other.getVersion()) &&
+ this.getRepoUrl().equals(other.getRepoUrl());
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = result * PRIME + this.getGroupId().hashCode();
+ result = result * PRIME + this.getArtifactId().hashCode();
+ result = result * PRIME + this.getVersion().hashCode();
+ result = result * PRIME + this.getRepoUrl().hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "LibraryLoader.Dependency(" +
+ "groupId=" + this.getGroupId() + ", " +
+ "artifactId=" + this.getArtifactId() + ", " +
+ "version=" + this.getVersion() + ", " +
+ "repoUrl=" + this.getRepoUrl() + ")";
+ }
+ }
+
+
+}
diff --git a/src/main/java/dev/brighten/ac/depends/MavenLibraries.java b/src/main/java/dev/brighten/ac/depends/MavenLibraries.java
new file mode 100644
index 0000000..81c02e3
--- /dev/null
+++ b/src/main/java/dev/brighten/ac/depends/MavenLibraries.java
@@ -0,0 +1,42 @@
+/*
+ * This file is part of helper, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * Copyright (c) contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package dev.brighten.ac.depends;
+
+import javax.annotation.Nonnull;
+import java.lang.annotation.*;
+
+/**
+ * Annotation to indicate the required libraries for a class.
+ */
+@Documented
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface MavenLibraries {
+
+ @Nonnull
+ MavenLibrary[] value() default {};
+
+}
diff --git a/src/main/java/dev/brighten/ac/depends/MavenLibrary.java b/src/main/java/dev/brighten/ac/depends/MavenLibrary.java
new file mode 100644
index 0000000..853ed17
--- /dev/null
+++ b/src/main/java/dev/brighten/ac/depends/MavenLibrary.java
@@ -0,0 +1,72 @@
+/*
+ * This file is part of helper, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * Copyright (c) contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package dev.brighten.ac.depends;
+
+import javax.annotation.Nonnull;
+import java.lang.annotation.*;
+
+/**
+ * Annotation to indicate a required library for a class.
+ */
+@Documented
+@Repeatable(MavenLibraries.class)
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface MavenLibrary {
+
+ /**
+ * The group id of the library
+ *
+ * @return the group id of the library
+ */
+ @Nonnull
+ String groupId();
+
+ /**
+ * The artifact id of the library
+ *
+ * @return the artifact id of the library
+ */
+ @Nonnull
+ String artifactId();
+
+ /**
+ * The version of the library
+ *
+ * @return the version of the library
+ */
+ @Nonnull
+ String version();
+
+ /**
+ * The repo where the library can be obtained from
+ *
+ * @return the repo where the library can be obtained from
+ */
+ @Nonnull
+ Repository repo() default @Repository(url = "https://repo1.maven.org/maven2");
+
+}
diff --git a/src/main/java/dev/brighten/ac/depends/Repository.java b/src/main/java/dev/brighten/ac/depends/Repository.java
new file mode 100644
index 0000000..4fe4752
--- /dev/null
+++ b/src/main/java/dev/brighten/ac/depends/Repository.java
@@ -0,0 +1,47 @@
+/*
+ * This file is part of helper, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * Copyright (c) contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package dev.brighten.ac.depends;
+
+import javax.annotation.Nonnull;
+import java.lang.annotation.*;
+
+/**
+ * Represents a maven repository.
+ */
+@Documented
+@Target(ElementType.LOCAL_VARIABLE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Repository {
+
+ /**
+ * Gets the base url of the repository.
+ *
+ * @return the base url of the repository
+ */
+ @Nonnull
+ String url();
+
+}
diff --git a/src/main/java/dev/brighten/ac/depends/URLClassLoaderAccess.java b/src/main/java/dev/brighten/ac/depends/URLClassLoaderAccess.java
new file mode 100644
index 0000000..b847765
--- /dev/null
+++ b/src/main/java/dev/brighten/ac/depends/URLClassLoaderAccess.java
@@ -0,0 +1,176 @@
+/*
+ * This file is part of helper, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * Copyright (c) contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package dev.brighten.ac.depends;
+
+import javax.annotation.Nonnull;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Collection;
+
+/**
+ * Provides access to {@link URLClassLoader}#addURL.
+ */
+public abstract class URLClassLoaderAccess {
+
+ /**
+ * Creates a {@link URLClassLoaderAccess} for the given class loader.
+ *
+ * @param classLoader the class loader
+ * @return the access object
+ */
+ static URLClassLoaderAccess create(URLClassLoader classLoader) {
+ if (Reflection.isSupported()) {
+ return new Reflection(classLoader);
+ } else if (Unsafe.isSupported()) {
+ return new Unsafe(classLoader);
+ } else {
+ return Noop.INSTANCE;
+ }
+ }
+
+ private final URLClassLoader classLoader;
+
+ protected URLClassLoaderAccess(URLClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+
+ /**
+ * Adds the given URL to the class loader.
+ *
+ * @param url the URL to add
+ */
+ public abstract void addURL(@Nonnull URL url);
+
+ /**
+ * Accesses using reflection, not supported on Java 9+.
+ */
+ private static class Reflection extends URLClassLoaderAccess {
+ private static final Method ADD_URL_METHOD;
+
+ static {
+ Method addUrlMethod;
+ try {
+ addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
+ addUrlMethod.setAccessible(true);
+ } catch (Exception e) {
+ addUrlMethod = null;
+ }
+ ADD_URL_METHOD = addUrlMethod;
+ }
+
+ private static boolean isSupported() {
+ return ADD_URL_METHOD != null;
+ }
+
+ Reflection(URLClassLoader classLoader) {
+ super(classLoader);
+ }
+
+ @Override
+ public void addURL(@Nonnull URL url) {
+ try {
+ ADD_URL_METHOD.invoke(super.classLoader, url);
+ } catch (ReflectiveOperationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * Accesses using sun.misc.Unsafe, supported on Java 9+.
+ *
+ * @author Vaishnav Anil (https://github.com/slimjar/slimjar)
+ */
+ private static class Unsafe extends URLClassLoaderAccess {
+ private static final sun.misc.Unsafe UNSAFE;
+
+ static {
+ sun.misc.Unsafe unsafe;
+ try {
+ Field unsafeField = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
+ unsafeField.setAccessible(true);
+ unsafe = (sun.misc.Unsafe) unsafeField.get(null);
+ } catch (Throwable t) {
+ unsafe = null;
+ }
+ UNSAFE = unsafe;
+ }
+
+ private static boolean isSupported() {
+ return UNSAFE != null;
+ }
+
+ private final Collection unopenedURLs;
+ private final Collection pathURLs;
+
+ @SuppressWarnings("unchecked")
+ Unsafe(URLClassLoader classLoader) {
+ super(classLoader);
+
+ Collection unopenedURLs;
+ Collection pathURLs;
+ try {
+ Object ucp = fetchField(URLClassLoader.class, classLoader, "ucp");
+ unopenedURLs = (Collection) fetchField(ucp.getClass(), ucp, "unopenedUrls");
+ pathURLs = (Collection) fetchField(ucp.getClass(), ucp, "path");
+ } catch (Throwable e) {
+ unopenedURLs = null;
+ pathURLs = null;
+ }
+ this.unopenedURLs = unopenedURLs;
+ this.pathURLs = pathURLs;
+ }
+
+ private static Object fetchField(final Class> clazz, final Object object, final String name) throws NoSuchFieldException {
+ Field field = clazz.getDeclaredField(name);
+ long offset = UNSAFE.objectFieldOffset(field);
+ return UNSAFE.getObject(object, offset);
+ }
+
+ @Override
+ public void addURL(@Nonnull URL url) {
+ this.unopenedURLs.add(url);
+ this.pathURLs.add(url);
+ }
+ }
+
+ private static class Noop extends URLClassLoaderAccess {
+ private static final Noop INSTANCE = new Noop();
+
+ private Noop() {
+ super(null);
+ }
+
+ @Override
+ public void addURL(@Nonnull URL url) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+}
diff --git a/src/main/java/dev/brighten/ac/handler/VelocityHandler.java b/src/main/java/dev/brighten/ac/handler/VelocityHandler.java
index 6481a7e..806fc8e 100644
--- a/src/main/java/dev/brighten/ac/handler/VelocityHandler.java
+++ b/src/main/java/dev/brighten/ac/handler/VelocityHandler.java
@@ -5,10 +5,13 @@ import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutEntityVelocity;
import lombok.RequiredArgsConstructor;
import lombok.val;
-import org.bukkit.util.Consumer;
import org.bukkit.util.Vector;
-import java.util.*;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
@RequiredArgsConstructor
public class VelocityHandler {
diff --git a/src/main/java/dev/brighten/ac/handler/block/BlockUpdateHandler.java b/src/main/java/dev/brighten/ac/handler/block/BlockUpdateHandler.java
index 35f271d..7273267 100644
--- a/src/main/java/dev/brighten/ac/handler/block/BlockUpdateHandler.java
+++ b/src/main/java/dev/brighten/ac/handler/block/BlockUpdateHandler.java
@@ -34,6 +34,7 @@ public class BlockUpdateHandler {
* @param place
*/
public void onPlace(WPacketPlayInBlockPlace place) {
+ player.getInfo().lastBlockUpdate.reset();
// Could not possibly be a block placement as it's not a block a player is holding.
IntVector pos = place.getBlockPos().clone();
@@ -68,6 +69,7 @@ public class BlockUpdateHandler {
* @param dig
*/
public void onDig(WPacketPlayInBlockDig dig) {
+ player.getInfo().lastBlockUpdate.reset();
if(dig.getDigType() == WPacketPlayInBlockDig.EnumPlayerDigType.STOP_DESTROY_BLOCK) {
Deque possible = getPossibleMaterials(dig.getBlockPos());
possible.clear();
@@ -76,6 +78,7 @@ public class BlockUpdateHandler {
}
public void runUpdate(WPacketPlayOutBlockChange packet) {
+ player.getInfo().lastBlockUpdate.reset();
Deque blockInfo = blockInformation.compute(packet.getBlockLocation(), (blockLoc, blockI) -> {
if(blockI == null) {
blockI = new LinkedList<>();
@@ -105,6 +108,7 @@ public class BlockUpdateHandler {
}
public void runUpdate(WPacketPlayOutMultiBlockChange packet) {
+ player.getInfo().lastBlockUpdate.reset();
List, Material>> changes = new ArrayList<>();
for (WPacketPlayOutMultiBlockChange.BlockChange change : packet.getChanges()) {
Deque blockInfo = blockInformation.compute(change.getLocation(), (blockLoc, blockI) -> {
@@ -144,7 +148,7 @@ public class BlockUpdateHandler {
}
public Deque getPossibleMaterials(IntVector loc) {
- return blockInformation.compute(loc, (blockLoc, blockI) -> {
+ return new LinkedList<>(blockInformation.compute(loc, (blockLoc, blockI) -> {
if(blockI == null) {
blockI = new LinkedList<>();
@@ -160,6 +164,6 @@ public class BlockUpdateHandler {
}
return blockI;
- });
+ }));
}
}
diff --git a/src/main/java/dev/brighten/ac/handler/keepalive/KeepaliveProcessor.java b/src/main/java/dev/brighten/ac/handler/keepalive/KeepaliveProcessor.java
index 370e42f..470db61 100644
--- a/src/main/java/dev/brighten/ac/handler/keepalive/KeepaliveProcessor.java
+++ b/src/main/java/dev/brighten/ac/handler/keepalive/KeepaliveProcessor.java
@@ -46,6 +46,7 @@ public class KeepaliveProcessor implements Runnable {
currentKeepalive.startStamp = System.currentTimeMillis();
totalPlayers = laggyPlayers = 0;
+ if(Anticheat.INSTANCE.getPlayerRegistry() == null) return; //Temp fix for startup errors on plugman reload
for (APlayer value : Anticheat.INSTANCE.getPlayerRegistry().aplayerMap.values()) {
totalPlayers++;
diff --git a/src/main/java/dev/brighten/ac/handler/protocolsupport/ProtocolAPI.java b/src/main/java/dev/brighten/ac/handler/protocolsupport/ProtocolAPI.java
index 7bc1555..2ea41d3 100644
--- a/src/main/java/dev/brighten/ac/handler/protocolsupport/ProtocolAPI.java
+++ b/src/main/java/dev/brighten/ac/handler/protocolsupport/ProtocolAPI.java
@@ -4,8 +4,8 @@ import dev.brighten.ac.Anticheat;
import dev.brighten.ac.handler.protocolsupport.impl.NoAPI;
import dev.brighten.ac.handler.protocolsupport.impl.ProtocolSupport;
import dev.brighten.ac.handler.protocolsupport.impl.ViaVersionAPI;
-import dev.brighten.ac.utils.Init;
-import dev.brighten.ac.utils.Instance;
+import dev.brighten.ac.utils.annotation.Init;
+import dev.brighten.ac.utils.annotation.Instance;
import org.bukkit.Bukkit;
import java.util.HashMap;
diff --git a/src/main/java/dev/brighten/ac/handler/thread/ThreadHandler.java b/src/main/java/dev/brighten/ac/handler/thread/ThreadHandler.java
index 5152239..c25dd27 100644
--- a/src/main/java/dev/brighten/ac/handler/thread/ThreadHandler.java
+++ b/src/main/java/dev/brighten/ac/handler/thread/ThreadHandler.java
@@ -3,7 +3,7 @@ package dev.brighten.ac.handler.thread;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.data.APlayer;
-import dev.brighten.ac.utils.Init;
+import dev.brighten.ac.utils.annotation.Init;
import dev.brighten.ac.utils.MiscUtils;
import dev.brighten.ac.utils.RunUtils;
import lombok.Getter;
diff --git a/src/main/java/dev/brighten/ac/listener/GeneralListener.java b/src/main/java/dev/brighten/ac/listener/GeneralListener.java
index 6bd67d8..b0db79f 100644
--- a/src/main/java/dev/brighten/ac/listener/GeneralListener.java
+++ b/src/main/java/dev/brighten/ac/listener/GeneralListener.java
@@ -2,7 +2,7 @@ package dev.brighten.ac.listener;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.data.APlayer;
-import dev.brighten.ac.utils.Init;
+import dev.brighten.ac.utils.annotation.Init;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
diff --git a/src/main/java/dev/brighten/ac/listener/JoinListener.java b/src/main/java/dev/brighten/ac/listener/JoinListener.java
index 7765f29..fcb1f7b 100644
--- a/src/main/java/dev/brighten/ac/listener/JoinListener.java
+++ b/src/main/java/dev/brighten/ac/listener/JoinListener.java
@@ -4,7 +4,7 @@ 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.utils.Init;
+import dev.brighten.ac.utils.annotation.Init;
import dev.brighten.ac.utils.RunUtils;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
diff --git a/src/main/java/dev/brighten/ac/logging/Log.java b/src/main/java/dev/brighten/ac/logging/Log.java
new file mode 100644
index 0000000..af0c9c4
--- /dev/null
+++ b/src/main/java/dev/brighten/ac/logging/Log.java
@@ -0,0 +1,16 @@
+package dev.brighten.ac.logging;
+
+import lombok.Builder;
+import lombok.Getter;
+
+import java.util.UUID;
+
+@Getter
+@Builder
+public class Log {
+ public UUID uuid;
+ private float vl;
+ private long time;
+ private String data;
+ private String checkId;
+}
diff --git a/src/main/java/dev/brighten/ac/logging/LoggerManager.java b/src/main/java/dev/brighten/ac/logging/LoggerManager.java
index c84c23d..6742f84 100644
--- a/src/main/java/dev/brighten/ac/logging/LoggerManager.java
+++ b/src/main/java/dev/brighten/ac/logging/LoggerManager.java
@@ -1,10 +1,25 @@
package dev.brighten.ac.logging;
+import dev.brighten.ac.Anticheat;
+import dev.brighten.ac.check.CheckData;
+import dev.brighten.ac.data.APlayer;
+import dev.brighten.ac.logging.sql.ExecutableStatement;
import dev.brighten.ac.logging.sql.MySQL;
+import dev.brighten.ac.logging.sql.Query;
+import dev.brighten.ac.logging.sql.ResultSetIterator;
+
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
public class LoggerManager {
+ private final Deque logList = new LinkedList<>();
+
/*
* Structure of Log
* UUID hashcode (INT32),
@@ -12,6 +27,63 @@ public class LoggerManager {
public void init() {
// Starting up H2
MySQL.initH2();
+
+ Query.prepare("CREATE TABLE IF NOT EXISTS `logs` (" +
+ "`id` INT NOT NULL AUTO_INCREMENT," +
+ "`uuid` INT NOT NULL," +
+ "`check` VARCHAR(32) NOT NULL," +
+ "`vl` FLOAT NOT NULL," +
+ "`data` MEDIUMTEXT NOT NULL," +
+ "`time` TIMESTAMP NOT NULL," +
+ "PRIMARY KEY (`id`)" +
+ ");").execute();
+
+ Anticheat.INSTANCE.getScheduler().scheduleAtFixedRate(() -> {
+ if(logList.size() > 0) {
+ synchronized (logList) {
+ final StringBuilder values = new StringBuilder();
+
+ List