Adding loader support

This commit is contained in:
Dawson
2022-08-29 17:36:49 -04:00
parent 9f35f0497b
commit ec18c17720
25 changed files with 349 additions and 461 deletions
+23 -28
View File
@@ -6,6 +6,7 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
import dev.brighten.ac.api.AnticheatAPI;
import dev.brighten.ac.check.Check;
import dev.brighten.ac.check.CheckManager;
import dev.brighten.ac.command.AnticheatCommand;
import dev.brighten.ac.data.PlayerRegistry;
import dev.brighten.ac.depends.LibraryLoader;
import dev.brighten.ac.depends.MavenLibrary;
@@ -21,8 +22,6 @@ 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;
import dev.brighten.ac.utils.reflections.types.WrappedClass;
import dev.brighten.ac.utils.reflections.types.WrappedField;
import dev.brighten.ac.utils.reflections.types.WrappedMethod;
@@ -31,13 +30,13 @@ import dev.brighten.ac.utils.timer.impl.TickTimer;
import dev.brighten.ac.utils.world.WorldInfo;
import lombok.Getter;
import lombok.experimental.PackagePrivate;
import me.mat1337.loader.plugin.LoaderPlugin;
import org.bukkit.Bukkit;
import org.bukkit.World;
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 java.util.*;
import java.util.concurrent.Executors;
@@ -53,7 +52,7 @@ import java.util.concurrent.atomic.AtomicLong;
@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 class Anticheat extends LoaderPlugin {
public static Anticheat INSTANCE;
@@ -80,10 +79,14 @@ public class Anticheat extends JavaPlugin {
@ConfigSetting(path = "logging", name = "verbose")
private static boolean verboseLogging = true;
private WrappedMethod findClassMethod;
public void onEnable() {
INSTANCE = this;
LibraryLoader.loadAll(getClass());
findClassMethod = new WrappedClass(getClassLoader2().getClass()).getMethod("findClass", String.class);
scheduler = Executors.newScheduledThreadPool(2, new ThreadFactoryBuilder()
.setNameFormat("Anticheat Schedular")
.setUncaughtExceptionHandler((t, e) -> RunUtils.task(e::printStackTrace))
@@ -91,17 +94,19 @@ public class Anticheat extends JavaPlugin {
saveDefaultConfig();
commandManager = new BukkitCommandManager(this);
commandManager = new BukkitCommandManager(getPluginInstance());
commandManager.enableUnstableAPI("help");
commandManager.registerCommand(new AnticheatCommand());
new CommandPropertiesManager(commandManager, getDataFolder(),
getResource("command-messages.properties"));
getResource2("command-messages.properties"));
packetProcessor = new PacketProcessor();
new AnticheatAPI();
initializeScanner(getClass(), this,
initializeScanner(getPluginInstance().getClass(), getPluginInstance(),
null,
true,
true);
@@ -137,14 +142,13 @@ public class Anticheat extends JavaPlugin {
Bukkit.getOnlinePlayers().forEach(HandlerAbstract.getHandler()::add);
}
public void onDisable() {
scheduler.shutdown();
commandManager.unregisterCommands();
// Unregistering packet listeners for players
HandlerAbstract.shutdown();
HandlerList.unregisterAll(this);
HandlerList.unregisterAll(getPluginInstance());
packetProcessor.shutdown();
packetProcessor = null;
checkManager.getCheckClasses().clear();
@@ -158,7 +162,7 @@ public class Anticheat extends JavaPlugin {
logManager.shutDown();
Bukkit.getScheduler().cancelTasks(this);
Bukkit.getScheduler().cancelTasks(getPluginInstance());
// Unregistering APlayer objects
@@ -180,9 +184,9 @@ public class Anticheat extends JavaPlugin {
public void initializeScanner(Class<? extends Plugin> mainClass, Plugin plugin, ClassLoader loader,
public void initializeScanner(Class<?> mainClass, Plugin plugin, ClassLoader loader,
boolean loadListeners, boolean loadCommands) {
initializeScanner(mainClass, plugin, loader, ClassScanner.scanFile(null, mainClass), loadListeners,
initializeScanner(mainClass, plugin, loader, ClassScanner.getNames(), loadListeners,
loadCommands);
}
@@ -190,26 +194,17 @@ public class Anticheat extends JavaPlugin {
return worldInfoMap.computeIfAbsent(world.getUID(), key -> new WorldInfo(world));
}
public void initializeScanner(Class<? extends Plugin> mainClass, Plugin plugin, ClassLoader loader, Set<String> names,
public void initializeScanner(Class<?> mainClass, Plugin plugin, ClassLoader loader, Set<String> names,
boolean loadListeners, boolean loadCommands) {
names.stream()
.map(name -> {
if(loader != null) {
try {
if(loader instanceof RemoteClassLoader) {
return new WrappedClass(((RemoteClassLoader)loader).findClass(name));
} else
return new WrappedClass(Class.forName(name, true, loader));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
} else {
return Reflections.getClass(name);
}
return new WrappedClass(findClassMethod.invoke(getClassLoader2(), name));
})
.filter(c -> {
if(c == null) return false;
if(c.getParent() == null) {
return false;
}
Init init = c.getAnnotation(Init.class);
String[] required = init.requirePlugins();
@@ -333,7 +328,7 @@ public class Anticheat extends JavaPlugin {
lastTimeStamp.set(currentTime);
}
lastTick = currentTime;
}, this, 1L, 1L);
}, 1L, 1L);
}
public void onTickEnd(Runnable runnable) {
@@ -43,6 +43,7 @@ public class FlyC extends Check {
jumpCheck: {
if(!jumped || player.getInfo().blockAbove.isNotPassed(1)
|| player.getInfo().climbTimer.isNotPassed(1)
|| player.getInfo().slimeTimer.isNotPassed(1)
|| player.getInfo().lastLiquid.isNotPassed(1)) break jumpCheck;
@@ -19,7 +19,9 @@ public class FlyD extends Check {
@Async
WAction<WPacketPlayInFlying> flyingPacket = packet -> {
if(!packet.isMoved() || player.getMovement().getMoveTicks() <= 2
|| player.getBlockInfo().miscNear || player.getInfo().isGeneralCancel()) return;
|| player.getBlockInfo().miscNear || player.getBlockInfo().onSlab
|| player.getBlockInfo().fenceBelow
|| player.getBlockInfo().onStairs || player.getInfo().isGeneralCancel()) return;
double deltaY = player.getMovement().getDeltaY();
if(deltaY > 0)
@@ -7,20 +7,23 @@ 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.PlayerUtils;
import dev.brighten.ac.utils.TagsBuilder;
import dev.brighten.ac.utils.*;
import dev.brighten.ac.utils.math.IntVector;
import dev.brighten.ac.utils.wrapper.Wrapper;
import org.bukkit.potion.PotionEffectType;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
@CheckData(name = "Speed", checkId = "speed", type = CheckType.MOVEMENT)
public class Speed extends Check {
public Speed(APlayer player) {
super(player);
}
private double ldxz = .12f;
private float friction = 0.91f;
private float buffer;
private boolean previousFromGround;
WAction<WPacketPlayInFlying> flyingPacket = packet -> {
if(player.getMovement().isExcuseNextFlying()) return;
@@ -29,88 +32,106 @@ public class Speed extends Check {
if (!packet.isMoved())
break checkProccesing;
float drag = friction;
IntVector belowLoc = new IntVector(MathHelper.floor_double(player.getMovement().getFrom().getX()),
MathHelper.floor_double(player.getMovement().getFrom().getY() - 1),
MathHelper.floor_double(player.getMovement().getFrom().getZ()));
List<Float> frictions = player.getBlockUpdateHandler().getPossibleMaterials(belowLoc).stream()
.map(Wrapper.getInstance()::getFriction).collect(Collectors.toList());
TagsBuilder tags = new TagsBuilder();
double moveFactor = player.getBukkitPlayer().getWalkSpeed() / 2f;
Tuple<Double, TagsBuilder> ratio = frictions.stream().map(friction -> {
float drag = 0.91f;
double ldxz = player.getMovement().getDeltaXZ();
moveFactor+= moveFactor * 0.3f;
if(player.getPotionHandler().hasPotionEffect(PotionEffectType.SPEED))
moveFactor += (PlayerUtils.getPotionEffectLevel(player.getBukkitPlayer(), PotionEffectType.SPEED)
* (0.20000000298023224D)) * moveFactor;
if(player.getPotionHandler().hasPotionEffect(PotionEffectType.SLOW))
moveFactor += (PlayerUtils.getPotionEffectLevel(player.getBukkitPlayer(), PotionEffectType.SLOW)
* (-0.15000000596046448D)) * moveFactor;
if (player.getMovement().getFrom().isOnGround()) {
tags.addTag("ground");
drag *= 0.91f;
moveFactor *= 0.16277136 / (drag * drag * drag);
if (player.getMovement().getFrom().isOnGround() && !player.getMovement().getTo().isOnGround()
&& player.getMovement().getDeltaY() > 0.2) {
tags.addTag("jumped");
moveFactor += 0.2;
if(previousFromGround) {
drag*= friction;
}
} else {
tags.addTag("air");
drag = 0.91f;
moveFactor = 0.026f;
}
if(player.getBlockInfo().inWater) {
tags.addTag("water");
TagsBuilder tags = new TagsBuilder();
double moveFactor = player.getBukkitPlayer().getWalkSpeed() / 2f;
drag = player.getPlayerVersion().isOrAbove(ProtocolVersion.V1_13) ? 0.9f : 0.8f;
moveFactor = 0.034;
moveFactor+= moveFactor * 0.3f;
if(player.getInfo().lastLiquid.getResetStreak() < 3) {
tags.addTag("water-enter");
if(player.getPotionHandler().hasPotionEffect(PotionEffectType.SPEED))
moveFactor += (PlayerUtils.getPotionEffectLevel(player.getBukkitPlayer(), PotionEffectType.SPEED)
* (0.20000000298023224D)) * moveFactor;
if(player.getPotionHandler().hasPotionEffect(PotionEffectType.SLOW))
moveFactor += (PlayerUtils.getPotionEffectLevel(player.getBukkitPlayer(), PotionEffectType.SLOW)
* (-0.15000000596046448D)) * moveFactor;
if (player.getMovement().getFrom().isOnGround()) {
tags.addTag("ground");
drag *= 0.91f;
moveFactor *= 0.16277136 / (drag * drag * drag);
if (player.getMovement().isJumped()) {
tags.addTag("jumped");
moveFactor += 0.2;
}
} else {
tags.addTag("air");
drag = 0.91f;
moveFactor = 0.026f;
}
if(player.getBlockInfo().inWater) {
tags.addTag("water");
drag = player.getPlayerVersion().isOrAbove(ProtocolVersion.V1_13) ? 0.9f : 0.8f;
moveFactor = 0.034;
if(player.getInfo().lastLiquid.getResetStreak() < 3) {
tags.addTag("water-enter");
moveFactor*= 1.35;
}
} else if(player.getInfo().lastLiquid.isNotPassed(3)) {
moveFactor*= 1.35;
tags.addTag("water-leave");
}
} else if(player.getInfo().lastLiquid.isNotPassed(3)) {
moveFactor*= 1.35;
tags.addTag("water-leave");
}
if(player.getMovement().getLastTeleport().isNotPassed(6)
|| player.getInfo().getLastRespawn().isNotPassed(6)) {
tags.addTag("teleport");
moveFactor+= 0.1;
moveFactor*= 5;
}
if(player.getMovement().getLastTeleport().isNotPassed(6)
|| player.getInfo().getLastRespawn().isNotPassed(6)) {
tags.addTag("teleport");
moveFactor+= 0.1;
moveFactor*= 5;
}
//In 1.9+, entity collisions add acceleration to their movement.
if(player.getInfo().lastEntityCollision.isNotPassed(2)) {
tags.addTag("entity-collision");
moveFactor+= 0.05;
}
//In 1.9+, entity collisions add acceleration to their movement.
if(player.getInfo().lastEntityCollision.isNotPassed(2)) {
tags.addTag("entity-collision");
moveFactor+= 0.05;
}
//Pistons have the ability to move players 1 whole block
if(player.getBlockInfo().pistonNear) {
tags.addTag("piston");
moveFactor+= 1;
}
//Pistons have the ability to move players 1 whole block
if(player.getBlockInfo().pistonNear) {
tags.addTag("piston");
moveFactor+= 1;
}
if(player.getBlockInfo().inWeb
//Ensuring they aren't just entering or leaving web
&& player.getInfo().getLastWeb().getResetStreak() > 1) {
tags.addTag("web");
moveFactor*= 0.4;
}
if(player.getBlockInfo().onSlime && player.getMovement().getFrom().isOnGround()) {
if (Math.abs(player.getMovement().getDeltaY()) < 0.1D && !player.getInfo().isSneaking()) {
moveFactor*= 0.5;
}
}
if(player.getBlockInfo().onSoulSand && player.getMovement().getFrom().isOnGround()
//Ensuring the player is actually standing on the block and recieving slow
&& packet.getY() % (1) == 0.875) {
tags.addTag("soulsand");
moveFactor*= 0.88;
}
if(player.getBlockInfo().inWeb
//Ensuring they aren't just entering or leaving web
&& player.getInfo().getLastWeb().getResetStreak() > 1) {
tags.addTag("web");
moveFactor*= 0.4;
}
double ratio = (player.getMovement().getDeltaXZ() - ldxz) / moveFactor * 100;
if(player.getBlockInfo().onSoulSand && player.getMovement().getFrom().isOnGround()
//Ensuring the player is actually standing on the block and recieving slow
&& packet.getY() % (1) == 0.875) {
tags.addTag("soulsand");
moveFactor*= 0.88;
}
if (ratio > 100.8
return new Tuple<>((player.getMovement().getDeltaXZ() - ldxz) / moveFactor * 100D, tags);
}).min(Comparator.comparing(r -> MathUtils.getDelta(r.one, 100))).orElse(new Tuple<>(100D, new TagsBuilder()));
if (ratio.one > 100.8
&& !player.getBlockInfo().inHoney
&& !player.getBlockInfo().inScaffolding
&& player.getInfo().velocity.isPassed(2)
@@ -119,16 +140,14 @@ public class Speed extends Check {
if(++buffer > 2) {
vl++;
flag("p=%.1f%% dxz=%.3f a/g=%s,%s tags=%s",
ratio, player.getMovement().getDeltaXZ(), player.getMovement().getAirTicks(), player.getMovement().getGroundTicks(),
tags.build());
ratio.one, player.getMovement().getDeltaXZ(), player.getMovement().getAirTicks(), player.getMovement().getGroundTicks(),
ratio.two.build());
buffer = Math.min(5, buffer); //Preventing runaway flagging
}
} else if(buffer > 0) buffer-= 0.2f;
debug("ratio=%.1f tags=%s tp=%s buffer=%.1f", ratio, tags.build(),
player.getInfo().getLastLiquid().getPassed(), buffer);
ldxz = player.getMovement().getDeltaXZ() * drag;
debug("ratio=%.1f deltaY=%.3f tags=%s tp=%s buffer=%.1f", ratio.one, player.getMovement().getDeltaY(),
ratio.two.build(), player.getInfo().getLastLiquid().getPassed(), buffer);
}
friction = player.getBlockInfo().currentFriction;
previousFromGround = player.getMovement().getFrom().isOnGround();
};
}
@@ -11,8 +11,10 @@ import dev.brighten.ac.logging.Log;
import dev.brighten.ac.logging.sql.Query;
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.Color;
import dev.brighten.ac.utils.MiscUtils;
import dev.brighten.ac.utils.Pastebin;
import dev.brighten.ac.utils.Tuple;
import dev.brighten.ac.utils.msg.ChatBuilder;
import io.netty.buffer.Unpooled;
import lombok.val;
@@ -32,7 +34,6 @@ import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
@Init(priority = Priority.LOW)
@CommandAlias("anticheat|ac")
@CommandPermission("anticheat.command")
public class AnticheatCommand extends BaseCommand {
@@ -1,10 +1,15 @@
package dev.brighten.ac.data;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.check.*;
import dev.brighten.ac.data.handlers.*;
import dev.brighten.ac.data.obj.*;
import dev.brighten.ac.check.Check;
import dev.brighten.ac.data.info.BlockInformation;
import dev.brighten.ac.data.info.CheckHandler;
import dev.brighten.ac.data.info.GeneralInformation;
import dev.brighten.ac.data.info.LagInformation;
import dev.brighten.ac.data.obj.InstantAction;
import dev.brighten.ac.data.obj.NormalAction;
import dev.brighten.ac.handler.EntityLocationHandler;
import dev.brighten.ac.handler.MovementHandler;
import dev.brighten.ac.handler.PotionHandler;
import dev.brighten.ac.handler.VelocityHandler;
import dev.brighten.ac.handler.block.BlockUpdateHandler;
@@ -17,8 +22,10 @@ import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.RunUtils;
import dev.brighten.ac.utils.Tuple;
import dev.brighten.ac.utils.objects.evicting.EvictingList;
import dev.brighten.ac.utils.reflections.Reflections;
import dev.brighten.ac.utils.reflections.impl.MinecraftReflection;
import dev.brighten.ac.utils.reflections.types.WrappedField;
import dev.brighten.ac.utils.reflections.types.WrappedClass;
import dev.brighten.ac.utils.reflections.types.WrappedMethod;
import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.MillisTimer;
import lombok.Getter;
@@ -26,7 +33,7 @@ import lombok.Setter;
import lombok.val;
import net.minecraft.server.v1_8_R3.PacketPlayOutTransaction;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.plugin.Plugin;
import org.bukkit.util.Vector;
import java.util.*;
@@ -41,7 +48,7 @@ public class APlayer {
@Getter
private final UUID uuid;
@Getter
private MovementHandler movement;
private MovementHandler movement;
@Getter
private PotionHandler potionHandler;
@@ -92,10 +99,21 @@ public class APlayer {
@Getter
private boolean sendingPackets;
static WrappedClass bukkitClass = Reflections.getClass("org.bukkit.Bukkit");
static WrappedClass pluginManager = Reflections.getClass("org.bukkit.plugin.PluginManager");
static WrappedMethod method = pluginManager.getMethod("isPluginEnabled", String.class),
method2 = pluginManager.getMethod("getPlugin", String.class),
gpmanager = bukkitClass.getMethod("getPluginManager");
public APlayer(Player player) {
this.bukkitPlayer = player;
this.uuid = player.getUniqueId();
this.playerConnection = MinecraftReflection.getPlayerConnection(player);
Object pluginManagerObj = gpmanager.invoke(null);
if(method.invoke(pluginManagerObj, "EnterpriseLoader")) {
Plugin plugin = method2.invoke(pluginManagerObj, "EnterpriseLoader");
}
load();
}
@@ -1,4 +1,4 @@
package dev.brighten.ac.data.handlers;
package dev.brighten.ac.data.info;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.data.APlayer;
@@ -23,7 +23,6 @@ public class BlockInformation {
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<>()),
@@ -1,4 +1,4 @@
package dev.brighten.ac.data.handlers;
package dev.brighten.ac.data.info;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.check.*;
@@ -1,4 +1,4 @@
package dev.brighten.ac.data.handlers;
package dev.brighten.ac.data.info;
import dev.brighten.ac.packet.wrapper.objects.PlayerCapabilities;
import dev.brighten.ac.utils.KLocation;
@@ -1,4 +1,4 @@
package dev.brighten.ac.data.handlers;
package dev.brighten.ac.data.info;
import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.MillisTimer;
@@ -47,7 +47,7 @@ import java.util.Objects;
public final class LibraryLoader {
@SuppressWarnings("Guava")
private static final Supplier<URLClassLoaderAccess> URL_INJECTOR = Suppliers.memoize(() -> URLClassLoaderAccess.create((URLClassLoader) Anticheat.INSTANCE.getClass().getClassLoader()));
private static final Supplier<URLClassLoaderAccess> URL_INJECTOR = Suppliers.memoize(() -> URLClassLoaderAccess.create((URLClassLoader) Anticheat.INSTANCE.getPluginInstance().getClass().getClassLoader()));
/**
* Resolves all {@link MavenLibrary} annotations on the given object.
@@ -110,6 +110,9 @@ public final class LibraryLoader {
try {
URL_INJECTOR.get().addURL(saveLocation.toURI().toURL());
//val mapOfShit = JarUtil.loadJar(saveLocation);
//((Map<String, byte[]>)Anticheat.INSTANCE.getStuffs()).putAll(mapOfShit);
} catch (Exception e) {
throw new RuntimeException("Unable to load dependency: " + saveLocation.toString(), e);
}
@@ -1,4 +1,4 @@
package dev.brighten.ac.data.handlers;
package dev.brighten.ac.handler;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.data.obj.CMove;
@@ -41,7 +41,7 @@ public class MovementHandler {
private int moveTicks;
private final List<KLocation> posLocs = new ArrayList<>();
@Getter
private boolean checkMovement, accurateYawData, cinematic;
private boolean checkMovement, accurateYawData, cinematic, jumped, inAir;
@Getter
@Setter
private boolean excuseNextFlying;
@@ -232,6 +232,16 @@ public class MovementHandler {
if (player.getBlockInfo().inLiquid) player.getInfo().getLastLiquid().reset();
if(player.getBlockInfo().inWeb) player.getInfo().lastWeb.reset();
if (!to.isOnGround() && moveTicks > 0) {
if (!jumped && from.isOnGround()
&& deltaY >= 0) {
jumped = true;
} else {
inAir = true;
jumped = false;
}
} else jumped = inAir = false;
player.getInfo().setGeneralCancel(player.getBukkitPlayer().getAllowFlight()
|| moveTicks == 0
|| excuseNextFlying
@@ -82,7 +82,7 @@ public class KeepaliveProcessor implements Runnable {
public void start() {
if (task == null) {
task = RunUtils.taskTimer(this, Anticheat.INSTANCE, 20L, 0L);
task = RunUtils.taskTimer(this, 20L, 0L);
}
}
@@ -1,11 +1,10 @@
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.annotation.Init;
import dev.brighten.ac.utils.MiscUtils;
import dev.brighten.ac.utils.RunUtils;
import dev.brighten.ac.utils.annotation.Init;
import lombok.Getter;
import org.bukkit.entity.Player;
@@ -59,7 +58,7 @@ public class ThreadHandler {
private PlayerThread generatePlayerThread() {
PlayerThread thread = new PlayerThread(Executors.newSingleThreadExecutor(new ThreadFactoryBuilder()
.setNameFormat("Kauri Player Thread " + services.size() + 1)
.setUncaughtExceptionHandler((t, e) -> RunUtils.task(e::printStackTrace, Anticheat.INSTANCE))
.setUncaughtExceptionHandler((t, e) -> RunUtils.task(e::printStackTrace))
.build()));
services.add(thread);
@@ -19,7 +19,7 @@ import java.util.Optional;
public class JoinListener implements Listener {
public JoinListener() {
Anticheat.INSTANCE.getPacketProcessor().processAsync(Anticheat.INSTANCE, EventPriority.NORMAL, event -> {
Anticheat.INSTANCE.getPacketProcessor().processAsync(EventPriority.NORMAL, event -> {
if(event.isCancelled()) return;
Optional<APlayer> aplayer = Anticheat.INSTANCE.getPlayerRegistry()
.getPlayer(event.getPlayer().getUniqueId());
@@ -32,7 +32,7 @@ public class JoinListener implements Listener {
});
});
Anticheat.INSTANCE.getPacketProcessor().process(Anticheat.INSTANCE, EventPriority.HIGHEST, event -> {
Anticheat.INSTANCE.getPacketProcessor().process(EventPriority.HIGHEST, event -> {
Optional<APlayer> op = Anticheat.INSTANCE.getPlayerRegistry().getPlayer(event.getPlayer().getUniqueId());
if(!op.isPresent()) {
@@ -65,7 +65,7 @@ public class JoinListener implements Listener {
case BLOCK_CHANGE:
case MULTI_BLOCK_CHANGE:
case MAP_CHUNK: {
if(player.getLagInfo().getLastClientTransaction().isPassed(100L) && player.getCreation().isPassed(2000L)) {
if(player.getLagInfo().getLastClientTransaction().isPassed(100L) && player.getCreation().isPassed(6000L)) {
synchronized (player.getPacketQueue()) {
player.getPacketQueue().add(event.getPacket());
}
@@ -4,14 +4,12 @@ import dev.brighten.ac.packet.listener.functions.PacketListener;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.bukkit.event.EventPriority;
import org.bukkit.plugin.Plugin;
import java.util.UUID;
@RequiredArgsConstructor
@Getter
class ListenerEntry {
private final Plugin plugin;
private final EventPriority priority;
private final PacketListener listener;
private long id = UUID.randomUUID().getMostSignificantBits();
@@ -11,7 +11,6 @@ import lombok.Getter;
import lombok.val;
import org.bukkit.entity.Player;
import org.bukkit.event.EventPriority;
import org.bukkit.plugin.Plugin;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -41,12 +40,12 @@ public class PacketProcessor {
}
}
public PacketListener process(Plugin plugin, PacketListener listener, PacketType... types) {
return process(plugin, EventPriority.NORMAL, listener, types);
public PacketListener process(PacketListener listener, PacketType... types) {
return process(EventPriority.NORMAL, listener, types);
}
public PacketListener process(Plugin plugin, EventPriority priority, PacketListener listener, PacketType... types) {
ListenerEntry entry = new ListenerEntry(plugin, priority, listener);
public PacketListener process(EventPriority priority, PacketListener listener, PacketType... types) {
ListenerEntry entry = new ListenerEntry(priority, listener);
synchronized (processors) {
for (PacketType type : types) {
processors.compute(type, (key, list) -> {
@@ -63,21 +62,21 @@ public class PacketProcessor {
return listener;
}
public PacketListener process(Plugin plugin, EventPriority priority, PacketListener listener) {
return process(plugin, priority, listener, PacketType.UNKNOWN);
public PacketListener process(EventPriority priority, PacketListener listener) {
return process(priority, listener, PacketType.UNKNOWN);
}
public PacketListener processAsync(Plugin plugin, PacketListener listener, PacketType... types) {
return processAsync(plugin, EventPriority.NORMAL, listener, types);
public PacketListener processAsync(PacketListener listener, PacketType... types) {
return processAsync(EventPriority.NORMAL, listener, types);
}
public PacketListener processAsync(Plugin plugin, EventPriority priority, PacketListener listener) {
return processAsync(plugin, priority, listener, PacketType.UNKNOWN);
public PacketListener processAsync(EventPriority priority, PacketListener listener) {
return processAsync(priority, listener, PacketType.UNKNOWN);
}
public PacketListener processAsync(Plugin plugin, EventPriority priority, PacketListener listener,
public PacketListener processAsync(EventPriority priority, PacketListener listener,
PacketType... types) {
ListenerEntry entry = new ListenerEntry(plugin, priority, listener);
ListenerEntry entry = new ListenerEntry(priority, listener);
synchronized (asyncProcessors) {
for (PacketType type : types) {
asyncProcessors.compute(type, (key, list) -> {
@@ -132,19 +131,6 @@ public class PacketProcessor {
return removedListener;
}
public void removeListeners(Plugin plugin) {
synchronized (processors) {
for (List<ListenerEntry> list : processors.values()) {
list.removeIf(entry -> entry.getPlugin().getName().equals(plugin.getName()));
}
}
synchronized (asyncProcessors) {
for (List<ListenerEntry> list : asyncProcessors.values()) {
list.removeIf(entry -> entry.getPlugin().getName().equals(plugin.getName()));
}
}
}
public Object call(Player player, Object packet, PacketType type) {
if(packet == null) return false;
PacketInfo info = new PacketInfo(player, packet, type, System.currentTimeMillis()),
@@ -9,20 +9,13 @@ import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.AnnotationNode;
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;
import java.net.URL;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@@ -34,259 +27,46 @@ public class ClassScanner {
private static final PathMatcher CLASS_FILE = create("glob:*.class");
private static final PathMatcher ARCHIVE = create("glob:*.{jar}");
public static Set<String> scanFile(String file, File f) {
URL[] urls;
try {
urls = new URL[]{f.toURI().toURL()};
} catch (MalformedURLException e) {
e.printStackTrace();
return new HashSet<>();
}
return scanFile(file, urls);
}
//TODO Get check classes too
public static Set<WrappedClass> getClasses(Class<? extends Annotation> annotationClass,
String packageName) {
return scanFile(annotationClass).stream().filter(pkg -> pkg.startsWith(packageName))
return getNames().stream().filter(pkg -> pkg.startsWith(packageName) && findClass(map.get(n), Init.class) != null)
.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> getNames() {
Map<String, byte[]> map = (Map<String, byte[]>) Anticheat.INSTANCE.getStuffs();
return map.keySet().stream().filter(n -> {
return !n.endsWith(".yml") && !n.endsWith(".xml") && !n.endsWith(".") && !n.endsWith(".properties")
&& !n.contains("dev.brighten.ac.packet")
&& Character.isLetterOrDigit(n.charAt(n.length() - 1))
&& findClass(map.get(n), Init.class) != null;
}).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) {
public static String findClass(byte[] array, Class<? extends Annotation> annotationClass) {
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);
ClassReader reader = new ClassReader(array);
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 + ";"))
.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()});
}
public static Set<String> scanFile2(String file, Class<?> clazz) {
Bukkit.getLogger().info("Found file: " + clazz.getProtectionDomain().getCodeSource().getLocation().toString());
return scanFile2(file, new URL[]{clazz.getProtectionDomain().getCodeSource().getLocation()});
}
public static Set<String> scanFile2(String file, 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)) {
scanPath2(file, Paths.get(source), plugins);
}
}
return plugins;
}
public static Set<String> scanFile(String file, 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(file, Paths.get(source), plugins);
}
}
return plugins;
}
private static void scanPath(String file, Path path, Set<String> plugins) {
if (Files.exists(path)) {
if (Files.isDirectory(path)) {
scanDirectory(file, path, plugins);
} else {
scanZip(file, path, plugins);
}
}
}
private static void scanPath2(String file, Path path, Set<String> plugins) {
if (Files.exists(path)) {
if (Files.isDirectory(path)) {
scanDirectory2(file, path, plugins);
} else {
scanZip2(file, path, plugins);
}
}
}
private static void scanDirectory(String file, Path dir, 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 = findPlugin(file, in);
if (plugin != null) {
plugins.add(plugin);
}
}
}
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
private static void scanDirectory2(String file, Path dir, 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 = findClasses(file, in);
if (plugin != null) {
plugins.add(plugin);
}
}
}
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
//Bukkit.getLogger().info("Failed to scan");
//e.printStackTrace();
}
return null;
}
private static <E> HashSet<E> newHashSet(E... elements) {
@@ -320,30 +100,6 @@ public class ClassScanner {
e.printStackTrace();
}
}
private static void scanZip2(String file, Path path, Set<String> plugins) {
if (!ARCHIVE.matches(path.getFileName())) {
return;
}
try (ZipFile zip = new ZipFile(path.toFile())) {
zip.stream().parallel().forEach(entry -> {
if (!entry.isDirectory() && entry.getName().endsWith(".class")) {
try (InputStream in = zip.getInputStream(entry)) {
String plugin = findClasses(file, in);
if (plugin != null) {
plugins.add(plugin);
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
public static String findPlugin(String file, InputStream in) {
try {
ClassReader reader = new ClassReader(in);
@@ -31,8 +31,11 @@ import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Supplier;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Collectors;
import java.util.stream.LongStream;
import java.util.zip.ZipException;
public class MiscUtils {
@@ -423,6 +426,64 @@ public class MiscUtils {
return false;
}
public static Map<String, byte[]> loadJar(File jarFile) {
try {
Map<String, byte[]> classes = new HashMap<>();
JarFile jar = new JarFile(jarFile);
Enumeration<JarEntry> enumeration = jar.entries();
while (enumeration.hasMoreElements()) {
JarEntry entry = enumeration.nextElement();
readJar(jar, entry, classes, null);
}
jar.close();
return classes;
} catch (ZipException e) {
return null;
}
catch (IOException e) {
e.printStackTrace();
}
return null;
}
private static Map<String, byte[]> readJar(JarFile jar, JarEntry en, Map<String, byte[]> classes, List<String> ignored) {
String name = en.getName();
try (InputStream jis = jar.getInputStream(en)) {
if (name.endsWith(".class")) {
if (ignored != null) {
for (String s : ignored) {
if (name.startsWith(s)) {
return classes;
}
}
}
byte[] bytes = getBytes(jis);
try {
classes.put(name, bytes);
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return classes;
}
private static byte[] getBytes(InputStream inputStream) {
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
return buffer.toByteArray();
} catch (IOException e) {
return new byte[0];
}
}
public static <T> T parseObjectFromString(String s, Class<T> clazz) throws Exception {
return clazz.getConstructor(new Class[] {String.class}).newInstance(s);
}
@@ -483,7 +544,7 @@ public class MiscUtils {
for (final File f : pluginDir.listFiles()) {
try {
if (f.getName().endsWith(".jar")) {
final PluginDescriptionFile pdf = Anticheat.INSTANCE.getPluginLoader().getPluginDescription(f);
final PluginDescriptionFile pdf = Anticheat.INSTANCE.getPluginInstance().getPluginLoader().getPluginDescription(f);
if (pdf.getDepend().contains("Atlas")) {
plugins.add(f);
}
@@ -509,7 +570,7 @@ public class MiscUtils {
for (final File f : pluginDir.listFiles()) {
try {
if (f.getName().endsWith(".jar")) {
final PluginDescriptionFile pdf = Anticheat.INSTANCE.getPluginLoader().getPluginDescription(f);
final PluginDescriptionFile pdf = Anticheat.INSTANCE.getPluginInstance().getPluginLoader().getPluginDescription(f);
if (pdf.getName().equalsIgnoreCase(pl)) {
pluginFile = f;
msg = "(via search) ";
@@ -2,7 +2,6 @@ package dev.brighten.ac.utils;
import dev.brighten.ac.Anticheat;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitTask;
import java.util.concurrent.ExecutionException;
@@ -16,52 +15,28 @@ import java.util.function.Consumer;
*/
public class RunUtils {
public static BukkitTask taskTimer(Runnable runnable, Plugin plugin, long delay, long interval) {
return Bukkit.getScheduler().runTaskTimer(plugin, runnable, delay, interval);
}
public static BukkitTask taskTimer(Runnable runnable, long delay, long interval) {
return taskTimer(runnable, Anticheat.INSTANCE, delay, interval);
}
public static BukkitTask taskTimerAsync(Runnable runnable, Plugin plugin, long delay, long interval) {
return Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, runnable, delay, interval);
return Bukkit.getScheduler().runTaskTimer(Anticheat.INSTANCE.getPluginInstance(), runnable, delay, interval);
}
public static BukkitTask taskTimerAsync(Runnable runnable, long delay, long interval) {
return taskTimerAsync(runnable, Anticheat.INSTANCE, delay, interval);
}
public static BukkitTask task(Runnable runnable, Plugin plugin) {
return Bukkit.getScheduler().runTask(plugin, runnable);
return Bukkit.getScheduler().runTaskTimerAsynchronously(Anticheat.INSTANCE.getPluginInstance(), runnable, delay, interval);
}
public static BukkitTask task(Runnable runnable) {
return task(runnable, Anticheat.INSTANCE);
}
public static BukkitTask taskAsync(Runnable runnable, Plugin plugin) {
return Bukkit.getScheduler().runTaskAsynchronously(plugin, runnable);
return Bukkit.getScheduler().runTask(Anticheat.INSTANCE.getPluginInstance(), runnable);
}
public static BukkitTask taskAsync(Runnable runnable) {
return taskAsync(runnable, Anticheat.INSTANCE);
}
public static BukkitTask taskLater(Runnable runnable, Plugin plugin, long delay) {
return Bukkit.getScheduler().runTaskLater(plugin, runnable, delay);
return Bukkit.getScheduler().runTaskAsynchronously(Anticheat.INSTANCE.getPluginInstance(), runnable);
}
public static BukkitTask taskLater(Runnable runnable, long delay) {
return taskLater(runnable, Anticheat.INSTANCE, delay);
}
public static BukkitTask taskLaterAsync(Runnable runnable, Plugin plugin, long delay) {
return Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, runnable, delay);
return Bukkit.getScheduler().runTaskLater(Anticheat.INSTANCE.getPluginInstance(), runnable, delay);
}
public static BukkitTask taskLaterAsync(Runnable runnable, long delay) {
return taskLaterAsync(runnable, Anticheat.INSTANCE, delay);
return Bukkit.getScheduler().runTaskLaterAsynchronously(Anticheat.INSTANCE.getPluginInstance(), runnable, delay);
}
public static <T> Future<?> callLater(Future<T> runnable, long delay, Consumer<T> onComplete) {
@@ -119,7 +119,7 @@ public class MenuListener implements Listener {
this.cancel();
}
}
}.runTaskTimer(Anticheat.INSTANCE, 2L, 0L));
}.runTaskTimer(Anticheat.INSTANCE.getPluginInstance(), 2L, 0L));
}
}
if(inventory instanceof AnvilInventory && anvils.containsKey(inventory)) {
@@ -0,0 +1,27 @@
package dev.brighten.ac.utils.wrapper;
import dev.brighten.ac.packet.ProtocolVersion;
import dev.brighten.ac.utils.wrapper.impl.Wrapper_18R3;
import dev.brighten.ac.utils.wrapper.impl.Wrapper_Reflection;
import org.bukkit.Material;
public abstract class Wrapper {
private static Wrapper INSTANCE;
public static Wrapper getInstance() {
if(INSTANCE == null) {
switch (ProtocolVersion.getGameVersion()) {
case V1_8_9: {
return INSTANCE = new Wrapper_18R3();
}
default: {
return INSTANCE = new Wrapper_Reflection();
}
}
}
return INSTANCE;
}
public abstract float getFriction(Material material);
}
@@ -0,0 +1,12 @@
package dev.brighten.ac.utils.wrapper.impl;
import dev.brighten.ac.utils.wrapper.Wrapper;
import org.bukkit.Material;
import org.bukkit.craftbukkit.v1_8_R3.util.CraftMagicNumbers;
public class Wrapper_18R3 extends Wrapper {
@Override
public float getFriction(Material material) {
return CraftMagicNumbers.getBlock(material).frictionFactor;
}
}
@@ -0,0 +1,20 @@
package dev.brighten.ac.utils.wrapper.impl;
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.wrapper.Wrapper;
import org.bukkit.Material;
public class Wrapper_Reflection extends Wrapper {
private static WrappedClass blockClass = Reflections.getNMSClass("Block");
private static WrappedMethod getById = blockClass.getMethodByType(blockClass.getParent(), 0);
private static WrappedField fieldFriction = blockClass.getFieldByType(float.class, 3);
@Override
public float getFriction(Material material) {
return fieldFriction.get(getById.invoke(material));
}
}