From d8225182b9a359aba3773236e1af158701ec6aa8 Mon Sep 17 00:00:00 2001 From: Dawson <30784509+funkemunky@users.noreply.github.com> Date: Tue, 30 Aug 2022 11:07:26 -0400 Subject: [PATCH] Finishing loader, adding config support for Checks, fixing EntityData box inaccuracies to patch Hitbox false Hitbox falses on Zombies, and would have potentially falsed with other mobs because of innaccurate bounds. --- API/API.iml | 12 ---- src/main/java/dev/brighten/ac/Anticheat.java | 57 ++++++++++++++++--- .../java/dev/brighten/ac/check/Check.java | 7 ++- .../java/dev/brighten/ac/check/CheckData.java | 2 +- .../dev/brighten/ac/check/CheckManager.java | 44 +++++++++++++- .../dev/brighten/ac/check/CheckSettings.java | 21 +++++++ .../brighten/ac/check/impl/combat/Hitbox.java | 13 ++++- .../brighten/ac/data/info/CheckHandler.java | 24 ++++++++ .../brighten/ac/depends/LibraryLoader.java | 3 - .../dev/brighten/ac/utils/ClassScanner.java | 34 ++++++++--- .../brighten/ac/utils/world/EntityData.java | 10 ++-- .../resources/{config.yml => anticheat.yml} | 0 12 files changed, 185 insertions(+), 42 deletions(-) delete mode 100644 API/API.iml create mode 100644 src/main/java/dev/brighten/ac/check/CheckSettings.java rename src/main/resources/{config.yml => anticheat.yml} (100%) diff --git a/API/API.iml b/API/API.iml deleted file mode 100644 index fa63d4b..0000000 --- a/API/API.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - SPIGOT - - - - - \ No newline at end of file diff --git a/src/main/java/dev/brighten/ac/Anticheat.java b/src/main/java/dev/brighten/ac/Anticheat.java index 794d433..9db32be 100644 --- a/src/main/java/dev/brighten/ac/Anticheat.java +++ b/src/main/java/dev/brighten/ac/Anticheat.java @@ -21,6 +21,9 @@ 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.config.Configuration; +import dev.brighten.ac.utils.config.ConfigurationProvider; +import dev.brighten.ac.utils.config.YamlConfiguration; import dev.brighten.ac.utils.math.RollingAverageDouble; import dev.brighten.ac.utils.reflections.types.WrappedClass; import dev.brighten.ac.utils.reflections.types.WrappedField; @@ -33,11 +36,12 @@ 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 java.io.File; +import java.io.IOException; import java.util.*; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -80,6 +84,7 @@ public class Anticheat extends LoaderPlugin { private static boolean verboseLogging = true; private WrappedMethod findClassMethod; + private Configuration anticheatConfig; public void onEnable() { INSTANCE = this; @@ -92,7 +97,7 @@ public class Anticheat extends LoaderPlugin { .setUncaughtExceptionHandler((t, e) -> RunUtils.task(e::printStackTrace)) .build()); - saveDefaultConfig(); + loadConfig(); commandManager = new BukkitCommandManager(getPluginInstance()); commandManager.enableUnstableAPI("help"); @@ -111,11 +116,11 @@ public class Anticheat extends LoaderPlugin { true, true); - if(!getConfig().contains("database.username")) { - getConfig().set("database.username", "dbuser"); + if(!getAnticheatConfig().contains("database.username")) { + getAnticheatConfig().set("database.username", "dbuser"); } - if(!getConfig().contains("database.password")) { - getConfig().set("database.password", UUID.randomUUID().toString()); + if(!getAnticheatConfig().contains("database.password")) { + getAnticheatConfig().set("database.password", UUID.randomUUID().toString()); } this.keepaliveProcessor = new KeepaliveProcessor(); @@ -182,7 +187,43 @@ public class Anticheat extends LoaderPlugin { packetHandler = null; } + public void saveConfig() { + try { + ConfigurationProvider.getProvider(YamlConfiguration.class) + .save(getAnticheatConfig(), new File(getDataFolder().getPath() + File.separator + "anticheat.yml")); + } catch (IOException e) { + e.printStackTrace(); + } + } + public void reloadConfig() { + try { + + anticheatConfig = ConfigurationProvider.getProvider(YamlConfiguration.class) + .load(new File(getDataFolder().getPath() + File.separator + "anticheat.yml")); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void loadConfig() { + try { + File configFile = new File(getDataFolder(), "anticheat.yml"); + + if(!configFile.exists()) { + configFile.getParentFile().mkdirs(); + if(!configFile.createNewFile()) { + throw new RuntimeException("Could not create new anticheat.yml in plugin folder!" + + "Insufficient write permissions?"); + } else { + MiscUtils.copy(INSTANCE.getResource2("anticheat.yml"), configFile); + } + } + anticheatConfig = ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile); + } catch(IOException e) { + throw new RuntimeException("Could not load \"anticheat.yml\"!", e); + } + } public void initializeScanner(Class mainClass, Plugin plugin, ClassLoader loader, boolean loadListeners, boolean loadCommands) { @@ -277,12 +318,12 @@ public class Anticheat extends LoaderPlugin { (setting.hide() ? "HIDDEN" : field.get(obj))); - FileConfiguration config = plugin.getConfig(); + Configuration config = getAnticheatConfig(); if(config.get((setting.path().length() > 0 ? setting.path() + "." : "") + name) == null) { alog(true,"&7Value not set in config! Setting value..."); config.set((setting.path().length() > 0 ? setting.path() + "." : "") + name, field.get(obj)); - plugin.saveConfig(); + saveConfig(); } else { Object configObj = config.get((setting.path().length() > 0 ? setting.path() + "." : "") + name); alog(true, "&7Set field to value &e%s&7.", diff --git a/src/main/java/dev/brighten/ac/check/Check.java b/src/main/java/dev/brighten/ac/check/Check.java index c766024..1d4fc30 100644 --- a/src/main/java/dev/brighten/ac/check/Check.java +++ b/src/main/java/dev/brighten/ac/check/Check.java @@ -35,7 +35,10 @@ public class Check implements ECheck { private long lastFlagRun; @Getter @Setter - private boolean enabled, punishable; + private boolean enabled, punishable, cancellable; + @Getter + @Setter + private int punishVl; private final Timer lastAlert = new MillisTimer(); public static Set alertsEnabled = new HashSet<>(); @@ -179,7 +182,7 @@ public class Check implements ECheck { .ifPresent(apl -> apl.getBukkitPlayer().spigot().sendMessage(toSend)); } - if(punish && vl > checkData.punishVl()) { + if(punish && vl > punishVl) { punish(); } lastAlert.reset(); diff --git a/src/main/java/dev/brighten/ac/check/CheckData.java b/src/main/java/dev/brighten/ac/check/CheckData.java index 123130a..33f6980 100644 --- a/src/main/java/dev/brighten/ac/check/CheckData.java +++ b/src/main/java/dev/brighten/ac/check/CheckData.java @@ -13,8 +13,8 @@ public @interface CheckData { CheckType type(); boolean enabled() default true; - boolean punishable() default true; + boolean cancellable() default true; int punishVl() default 10; ProtocolVersion minVersion() default ProtocolVersion.V1_7; diff --git a/src/main/java/dev/brighten/ac/check/CheckManager.java b/src/main/java/dev/brighten/ac/check/CheckManager.java index 94cab21..67e3573 100644 --- a/src/main/java/dev/brighten/ac/check/CheckManager.java +++ b/src/main/java/dev/brighten/ac/check/CheckManager.java @@ -4,15 +4,17 @@ import dev.brighten.ac.Anticheat; import dev.brighten.ac.utils.ClassScanner; import dev.brighten.ac.utils.reflections.types.WrappedClass; import lombok.Getter; +import lombok.val; import java.util.HashMap; import java.util.Map; +import java.util.Optional; @Getter public class CheckManager { private final Map checkClasses = new HashMap<>(); private final Map idToName = new HashMap<>(); - + private final Map, CheckSettings> checkSettings = new HashMap<>(); public CheckManager() { synchronized (checkClasses) { for (WrappedClass aClass : ClassScanner.getClasses(CheckData.class, @@ -31,12 +33,52 @@ public class CheckManager { CheckData checkData = check.getCheckClass().getAnnotation(CheckData.class); + Optional settings = getConfigSettings(checkData.checkId()); + + if(!settings.isPresent()) { + generateConfigSettings(checkData); + settings = Optional.of(CheckSettings.settingsFromData(checkData)); + } + + checkSettings.put(checkClass.getParent(), settings.get()); + Anticheat.INSTANCE.alog(true, "&7Adding check to CheckManager: " + checkData.name()); checkClasses.put(checkData.name(), check); idToName.put(checkData.checkId(), checkData.name()); } + private Optional getConfigSettings(String checkId) { + String basePath = "checks." + checkId + "."; + if(Anticheat.INSTANCE.getAnticheatConfig().contains(basePath + "enabled")) { + val config = Anticheat.INSTANCE.getAnticheatConfig(); + return Optional.of(CheckSettings.builder() + .enabled(config.getBoolean(basePath + "enabled")) + .punishable(config.getBoolean(basePath + "punishable")) + .cancellable(config.getBoolean(basePath + "cancellable")) + .punishVl(config.getInt(basePath + "punishVl")) + .build()); + } + + return Optional.empty(); + } + + public CheckSettings getCheckSettings(Class checkClass) { + return checkSettings.get(checkClass); + } + + private void generateConfigSettings(CheckData data) { + val config = Anticheat.INSTANCE.getAnticheatConfig(); + String basePath = "checks." + data.checkId() + "."; + + config.set(basePath + "enabled", data.enabled()); + config.set(basePath + "punishable", data.punishable()); + config.set(basePath + "cancellable", data.cancellable()); + config.set(basePath + "punishVl", data.punishVl()); + + Anticheat.INSTANCE.saveConfig(); + } + public boolean isCheck(String name) { final String formattedName = name.replace("_", " "); return checkClasses.containsKey(formattedName); diff --git a/src/main/java/dev/brighten/ac/check/CheckSettings.java b/src/main/java/dev/brighten/ac/check/CheckSettings.java new file mode 100644 index 0000000..55281b8 --- /dev/null +++ b/src/main/java/dev/brighten/ac/check/CheckSettings.java @@ -0,0 +1,21 @@ +package dev.brighten.ac.check; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +public class CheckSettings { + private boolean enabled, punishable, cancellable; + private int punishVl; + + public static CheckSettings settingsFromData(CheckData data) { + return CheckSettings.builder().enabled(data.enabled()) + .punishable(data.punishable()) + .cancellable(data.cancellable()) + .punishVl(data.punishVl()) + .build(); + } +} 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 bb1eb06..80b398c 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 @@ -1,20 +1,23 @@ 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.ProtocolVersion; import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying; import dev.brighten.ac.packet.wrapper.in.WPacketPlayInUseEntity; +import dev.brighten.ac.packet.wrapper.objects.EnumParticle; import dev.brighten.ac.utils.*; import dev.brighten.ac.utils.timer.Timer; import dev.brighten.ac.utils.timer.impl.TickTimer; import dev.brighten.ac.utils.world.EntityData; import dev.brighten.ac.utils.world.types.SimpleCollisionBox; +import org.bukkit.Bukkit; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; import org.bukkit.util.Vector; import java.util.*; @@ -78,6 +81,8 @@ public class Hitbox extends Check { SimpleCollisionBox box = (SimpleCollisionBox) EntityData.getEntityBox(oldLocation.toVector(), target.one); + box.draw(EnumParticle.FLAME, Bukkit.getOnlinePlayers().toArray(new Player[0])); + if(player.getPlayerVersion().isBelow(ProtocolVersion.V1_9)) { box = box.expand(0.1325); } else box = box.expand(0.0325); @@ -87,6 +92,8 @@ public class Hitbox extends Check { SimpleCollisionBox box = (SimpleCollisionBox) EntityData.getEntityBox(oldLocation.toVector(), target.one); + box.draw(EnumParticle.FLAME, Bukkit.getOnlinePlayers().toArray(new Player[0])); + if(player.getPlayerVersion().isBelow(ProtocolVersion.V1_9)) { box = box.expand(0.1325); } else box = box.expand(0.0325); @@ -97,6 +104,8 @@ public class Hitbox extends Check { SimpleCollisionBox box = (SimpleCollisionBox) EntityData.getEntityBox(oldLocation.toVector(), target.one); + box.draw(EnumParticle.FLAME, Bukkit.getOnlinePlayers().toArray(new Player[0])); + if(player.getPlayerVersion().isBelow(ProtocolVersion.V1_9)) { box = box.expand(0.1325); } else box = box.expand(0.0325); diff --git a/src/main/java/dev/brighten/ac/data/info/CheckHandler.java b/src/main/java/dev/brighten/ac/data/info/CheckHandler.java index 9b1339f..666aeb7 100644 --- a/src/main/java/dev/brighten/ac/data/info/CheckHandler.java +++ b/src/main/java/dev/brighten/ac/data/info/CheckHandler.java @@ -56,6 +56,18 @@ public class CheckHandler { Check check = checkClass.playerInit(player); + CheckSettings settings = Anticheat.INSTANCE.getCheckManager() + .getCheckSettings(checkClass.getCheckClass().getParent()); + + if(settings == null) { + throw new RuntimeException("Settings for check" + check.getName() + " do not exist!"); + } + + check.setEnabled(settings.isEnabled()); + check.setPunishable(settings.isPunishable()); + check.setCancellable(settings.isCancellable()); + check.setPunishVl(settings.getPunishVl()); + checks.add(check); synchronized (events) { @@ -165,6 +177,8 @@ public class CheckHandler { if(events.containsKey(event.getClass())) { ActionStore[] actions = (ActionStore[]) events.get(event.getClass()); for (ActionStore action : actions) { + if(!Anticheat.INSTANCE.getCheckManager().getCheckSettings(action.getCheckClass()).isEnabled()) + continue; action.getAction().invoke(event); } } @@ -177,6 +191,8 @@ public class CheckHandler { synchronized (async_events) { ActionStore[] actions = async_events.get(packet.getClass()); for (ActionStore action : actions) { + if(!Anticheat.INSTANCE.getCheckManager().getCheckSettings(action.getCheckClass()).isEnabled()) + continue; action.getAction().invoke(packet); } } @@ -185,6 +201,8 @@ public class CheckHandler { synchronized (async_eventsWithTimestamp) { TimedActionStore[] actions = async_eventsWithTimestamp.get(packet.getClass()); for (TimedActionStore action : actions) { + if(!Anticheat.INSTANCE.getCheckManager().getCheckSettings(action.getCheckClass()).isEnabled()) + continue; action.getAction().invoke(packet, timestamp); } } @@ -197,6 +215,8 @@ public class CheckHandler { synchronized (events) { ActionStore[] actions = events.get(packet.getClass()); for (ActionStore action : actions) { + if(!Anticheat.INSTANCE.getCheckManager().getCheckSettings(action.getCheckClass()).isEnabled()) + continue; action.getAction().invoke(packet); } } @@ -205,6 +225,8 @@ public class CheckHandler { synchronized (eventsWithTimestamp) { TimedActionStore[] actions = eventsWithTimestamp.get(packet.getClass()); for (TimedActionStore action : actions) { + if(!Anticheat.INSTANCE.getCheckManager().getCheckSettings(action.getCheckClass()).isEnabled()) + continue; action.getAction().invoke(packet, timestamp); } } @@ -214,6 +236,8 @@ public class CheckHandler { synchronized (cancellableEvents) { CancellableActionStore[] actions = cancellableEvents.get(packet.getClass()); for (CancellableActionStore action : actions) { + if(!Anticheat.INSTANCE.getCheckManager().getCheckSettings(action.getCheckClass()).isEnabled()) + continue; if(action.getAction().invoke(packet)) { cancelled = true; } diff --git a/src/main/java/dev/brighten/ac/depends/LibraryLoader.java b/src/main/java/dev/brighten/ac/depends/LibraryLoader.java index 15d9875..172368f 100644 --- a/src/main/java/dev/brighten/ac/depends/LibraryLoader.java +++ b/src/main/java/dev/brighten/ac/depends/LibraryLoader.java @@ -110,9 +110,6 @@ public final class LibraryLoader { try { URL_INJECTOR.get().addURL(saveLocation.toURI().toURL()); - //val mapOfShit = JarUtil.loadJar(saveLocation); - - //((Map)Anticheat.INSTANCE.getStuffs()).putAll(mapOfShit); } catch (Exception e) { throw new RuntimeException("Unable to load dependency: " + saveLocation.toString(), e); } diff --git a/src/main/java/dev/brighten/ac/utils/ClassScanner.java b/src/main/java/dev/brighten/ac/utils/ClassScanner.java index cb9c0a1..631cf0f 100644 --- a/src/main/java/dev/brighten/ac/utils/ClassScanner.java +++ b/src/main/java/dev/brighten/ac/utils/ClassScanner.java @@ -4,12 +4,12 @@ import dev.brighten.ac.Anticheat; import dev.brighten.ac.utils.annotation.Init; import dev.brighten.ac.utils.reflections.Reflections; import dev.brighten.ac.utils.reflections.types.WrappedClass; -import jdk.tools.jlink.resources.plugins; import org.bukkit.Bukkit; import org.objectweb.asm.ClassReader; import org.objectweb.asm.tree.AnnotationNode; import org.objectweb.asm.tree.ClassNode; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Annotation; @@ -17,7 +17,6 @@ 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; @@ -31,18 +30,37 @@ public class ClassScanner { //TODO Get check classes too public static Set getClasses(Class annotationClass, String packageName) { - Map map = (Map) Anticheat.INSTANCE.getStuffs(); - return getNames().stream().filter(pkg -> pkg.startsWith(packageName) && findClass(map.get(pkg), annotationClass) != null) - .map(Reflections::getClass).collect(Collectors.toSet()); + Map map = Anticheat.INSTANCE.getStuffs(); + Map loadedClasses = Anticheat.INSTANCE.getLoadedClasses(); + Set toReturn = new HashSet<>(); + + for (Map.Entry entry : map.entrySet()) { + boolean startsWith = entry.getKey().startsWith(packageName); + boolean hasAnnotation = findClass(new ByteArrayInputStream(entry.getValue()), annotationClass) != null; + + if(startsWith && hasAnnotation) { + toReturn.add(Reflections.getClass(entry.getKey())); + } + } + + for (Map.Entry entry : loadedClasses.entrySet()) { + boolean startsWith = entry.getKey().startsWith(packageName); + boolean hasAnnotation = findClass(new ByteArrayInputStream(entry.getValue()), annotationClass) != null; + + if(startsWith && hasAnnotation) { + toReturn.add(Reflections.getClass(entry.getKey())); + } + } + return toReturn; } public static Set getNames() { - Map map = (Map) Anticheat.INSTANCE.getStuffs(); + Map map = Anticheat.INSTANCE.getStuffs(); Set nameSet = new HashSet<>(); - for (String loadedClass : Anticheat.INSTANCE.getLoadedClasses()) { - InputStream stream = Anticheat.INSTANCE.getClassLoader2().getResourceAsStream(loadedClass); + for (String loadedClass : Anticheat.INSTANCE.getLoadedClasses().keySet()) { + InputStream stream = new ByteArrayInputStream(Anticheat.INSTANCE.getLoadedClasses().get(loadedClass)); if(findClass(stream, Init.class) != null) { nameSet.add(loadedClass); diff --git a/src/main/java/dev/brighten/ac/utils/world/EntityData.java b/src/main/java/dev/brighten/ac/utils/world/EntityData.java index 6689b5e..1b07c3a 100644 --- a/src/main/java/dev/brighten/ac/utils/world/EntityData.java +++ b/src/main/java/dev/brighten/ac/utils/world/EntityData.java @@ -53,15 +53,15 @@ public class EntityData { entityBounds.put(EntityType.WITCH, new SimpleCollisionBox(new Vector(), 0.62f, 1.95f)); entityBounds.put(EntityType.BLAZE, new SimpleCollisionBox(new Vector(), 0.62f, 1.8f)); entityBounds.put(EntityType.PLAYER, new SimpleCollisionBox(new Vector(), 0.6f, 1.8f)); - entityBounds.put(EntityType.VILLAGER, new SimpleCollisionBox(new Vector(), 0.62f, 1.8f)); - entityBounds.put(EntityType.CREEPER, new SimpleCollisionBox(new Vector(), 0.62f, 1.8f)); + entityBounds.put(EntityType.VILLAGER, new SimpleCollisionBox(new Vector(), 0.6f, 1.8f)); + entityBounds.put(EntityType.CREEPER, new SimpleCollisionBox(new Vector(), 0.6f, 1.8f)); entityBounds.put(EntityType.GIANT, new SimpleCollisionBox(new Vector(), 3.6f, 10.8f)); - entityBounds.put(EntityType.SKELETON, new SimpleCollisionBox(new Vector(), 0.62f, 1.8f)); - entityBounds.put(EntityType.ZOMBIE, new SimpleCollisionBox(new Vector(), 0.62f, 1.8f)); + entityBounds.put(EntityType.SKELETON, new SimpleCollisionBox(new Vector(), 0.6f, 1.95F)); + entityBounds.put(EntityType.ZOMBIE, new SimpleCollisionBox(new Vector(), 0.6f, 1.95F)); entityBounds.put(EntityType.SNOWMAN, new SimpleCollisionBox(new Vector(), 0.7f, 1.9f)); entityBounds.put(EntityType.HORSE, new SimpleCollisionBox(new Vector(), 1.4f, 1.6f)); entityBounds.put(EntityType.ENDER_DRAGON, new SimpleCollisionBox(new Vector(), 3f, 1.5f)); - entityBounds.put(EntityType.ENDERMAN, new SimpleCollisionBox(new Vector(), 0.62f, 2.9f)); + entityBounds.put(EntityType.ENDERMAN, new SimpleCollisionBox(new Vector(), 0.6f, 2.9f)); entityBounds.put(EntityType.CHICKEN, new SimpleCollisionBox(new Vector(), 0.4f, 0.7f)); entityBounds.put(EntityType.OCELOT, new SimpleCollisionBox(new Vector(), 0.62f, 0.7f)); entityBounds.put(EntityType.SPIDER, new SimpleCollisionBox(new Vector(), 1.4f, 0.9f)); diff --git a/src/main/resources/config.yml b/src/main/resources/anticheat.yml similarity index 100% rename from src/main/resources/config.yml rename to src/main/resources/anticheat.yml