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