diff --git a/src/main/java/dev/brighten/ac/check/Check.java b/src/main/java/dev/brighten/ac/check/Check.java index 1d636ae..5f37ed6 100644 --- a/src/main/java/dev/brighten/ac/check/Check.java +++ b/src/main/java/dev/brighten/ac/check/Check.java @@ -13,6 +13,7 @@ import dev.brighten.ac.utils.*; import dev.brighten.ac.utils.timer.Timer; import dev.brighten.ac.utils.timer.impl.MillisTimer; import lombok.Getter; +import lombok.Setter; import lombok.val; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; @@ -30,8 +31,11 @@ public class Check implements ECheck { @Getter private final CheckData checkData; @Getter - private float vl; + public float vl; private long lastFlagRun; + @Getter + @Setter + private boolean enabled, punishable; private final Timer lastAlert = new MillisTimer(); public static Set alertsEnabled = new HashSet<>(); @@ -60,6 +64,14 @@ public class Check implements ECheck { .replace("%info%", info)); } + public void onEnable() { + + } + + public void onDisable() { + + } + private String addPlaceHolders(String string) { return string.replace("%player%", player.getBukkitPlayer().getName()) .replace("%check%", checkData.name()) @@ -170,6 +182,8 @@ public class Check implements ECheck { } public void punish() { + if(!punishable) return; + PunishResult result = PunishResult.builder().cancelled(false).build(); List commands = CheckConfig.punishmentCommands.stream().map(this::addPlaceHolders) diff --git a/src/main/java/dev/brighten/ac/check/CheckData.java b/src/main/java/dev/brighten/ac/check/CheckData.java index 3ebbe6b..4166cd3 100644 --- a/src/main/java/dev/brighten/ac/check/CheckData.java +++ b/src/main/java/dev/brighten/ac/check/CheckData.java @@ -11,6 +11,9 @@ public @interface CheckData { String name(); CheckType type(); + boolean enabled() default true; + + boolean punishable() 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 afc4e18..2976e8a 100644 --- a/src/main/java/dev/brighten/ac/check/CheckManager.java +++ b/src/main/java/dev/brighten/ac/check/CheckManager.java @@ -5,17 +5,19 @@ import dev.brighten.ac.utils.ClassScanner; import dev.brighten.ac.utils.reflections.types.WrappedClass; import lombok.Getter; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; @Getter public class CheckManager { - private final List checkClasses = new ArrayList<>(); + private final Map checkClasses = new HashMap<>(); public CheckManager() { - for (WrappedClass aClass : ClassScanner.getClasses(CheckData.class, - "dev.brighten.ac.check.impl")) { - addCheck(aClass); + synchronized (checkClasses) { + for (WrappedClass aClass : ClassScanner.getClasses(CheckData.class, + "dev.brighten.ac.check.impl")) { + addCheck(aClass); + } } } @@ -30,12 +32,11 @@ public class CheckManager { Anticheat.INSTANCE.alog(true, "&7Adding check to CheckManager: " + checkData.name()); - checkClasses.add(check); + checkClasses.put(checkData.name(), check); } public boolean isCheck(String name) { final String formattedName = name.replace("_", " "); - return checkClasses.stream().anyMatch(c -> c.getCheckClass().getAnnotation(CheckData.class).name() - .equalsIgnoreCase(formattedName)); + return checkClasses.containsKey(formattedName); } } diff --git a/src/main/java/dev/brighten/ac/command/AnticheatCommand.java b/src/main/java/dev/brighten/ac/command/AnticheatCommand.java index cb17fff..4051507 100644 --- a/src/main/java/dev/brighten/ac/command/AnticheatCommand.java +++ b/src/main/java/dev/brighten/ac/command/AnticheatCommand.java @@ -5,7 +5,6 @@ import co.aikar.commands.annotation.*; import co.aikar.commands.bukkit.contexts.OnlinePlayer; import dev.brighten.ac.Anticheat; import dev.brighten.ac.check.Check; -import dev.brighten.ac.check.CheckData; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.messages.Messages; import dev.brighten.ac.packet.handler.HandlerAbstract; @@ -35,9 +34,9 @@ public class AnticheatCommand extends BaseCommand { BukkitCommandCompletions cc = (BukkitCommandCompletions) Anticheat.INSTANCE.getCommandManager() .getCommandCompletions(); - cc.registerCompletion("checks", (c) -> Anticheat.INSTANCE.getCheckManager().getCheckClasses().stream() - .map(cs -> cs.getCheckClass().getAnnotation(CheckData.class).name().replace(" ", "_")) - .sorted(Comparator.naturalOrder()).collect(Collectors.toList())); + cc.registerCompletion("checks", (c) -> Anticheat.INSTANCE.getCheckManager().getCheckClasses().keySet() + .stream() .sorted(Comparator.naturalOrder()) + .map(name -> name.replace(" ", "_")).collect(Collectors.toList())); BukkitCommandContexts contexts = (BukkitCommandContexts) Anticheat.INSTANCE.getCommandManager() .getCommandContexts(); diff --git a/src/main/java/dev/brighten/ac/data/APlayer.java b/src/main/java/dev/brighten/ac/data/APlayer.java index f63f690..720961d 100644 --- a/src/main/java/dev/brighten/ac/data/APlayer.java +++ b/src/main/java/dev/brighten/ac/data/APlayer.java @@ -6,8 +6,10 @@ import dev.brighten.ac.data.handlers.BlockInformation; import dev.brighten.ac.data.handlers.GeneralInformation; import dev.brighten.ac.data.handlers.LagInformation; import dev.brighten.ac.data.handlers.MovementHandler; +import dev.brighten.ac.data.obj.ActionStore; import dev.brighten.ac.data.obj.InstantAction; import dev.brighten.ac.data.obj.NormalAction; +import dev.brighten.ac.data.obj.TimedActionStore; import dev.brighten.ac.handler.EntityLocationHandler; import dev.brighten.ac.handler.PotionHandler; import dev.brighten.ac.handler.block.BlockUpdateHandler; @@ -82,8 +84,8 @@ public class APlayer { private final List> onVelocityTasks = new ArrayList<>(); public final EvictingList> pastLocations = new EvictingList<>(20); - private final Map, WAction[]> events = new HashMap<>(); - private final Map, TimedWAction[]> eventsWithTimestamp = new HashMap<>(); + private final Map, ActionStore[]> events = new HashMap<>(); + private final Map, TimedActionStore[]> eventsWithTimestamp = new HashMap<>(); @Setter @Getter @@ -111,7 +113,7 @@ public class APlayer { private void load() { synchronized (checks) { - for (CheckStatic check : Anticheat.INSTANCE.getCheckManager().getCheckClasses()) { + for (CheckStatic check : Anticheat.INSTANCE.getCheckManager().getCheckClasses().values()) { checks.add(check.playerInit(this)); } } @@ -128,7 +130,7 @@ public class APlayer { playerVersion = ProtocolVersion.getVersion(ProtocolAPI.INSTANCE.getPlayerVersion(getBukkitPlayer())); // Enabling checks for players on join - for (CheckStatic checkClass : Anticheat.INSTANCE.getCheckManager().getCheckClasses()) { + for (CheckStatic checkClass : Anticheat.INSTANCE.getCheckManager().getCheckClasses().values()) { CheckData data = checkClass.getCheckClass().getAnnotation(CheckData.class); //Version checks @@ -141,31 +143,35 @@ public class APlayer { Check check = checkClass.playerInit(this); - for (Tuple> tuple : checkClass.getActions()) { - WAction action = tuple.one.get(check); + synchronized (events) { + for (Tuple> tuple : checkClass.getActions()) { + WAction action = tuple.one.get(check); - events.compute(tuple.two, (packetClass, array) -> { - if (array == null) { - return new WAction[]{action}; - } else { - WAction[] newArray = Arrays.copyOf(array, array.length + 1); - newArray[array.length] = action; - return newArray; - } - }); + events.compute(tuple.two, (packetClass, array) -> { + if (array == null) { + return new ActionStore[] {new ActionStore(action, checkClass.getCheckClass().getParent())}; + } else { + ActionStore[] newArray = Arrays.copyOf(array, array.length + 1); + newArray[array.length] = new ActionStore(action, checkClass.getCheckClass().getParent()); + return newArray; + } + }); + } } - for (Tuple> tuple : checkClass.getTimedActions()) { - TimedWAction action = tuple.one.get(check); + synchronized (eventsWithTimestamp) { + for (Tuple> tuple : checkClass.getTimedActions()) { + TimedWAction action = tuple.one.get(check); - eventsWithTimestamp.compute(tuple.two, (packetClass, array) -> { - if (array == null) { - return new TimedWAction[]{action}; - } else { - TimedWAction[] newArray = Arrays.copyOf(array, array.length + 1); - newArray[array.length] = action; - return newArray; - } - }); + eventsWithTimestamp.compute(tuple.two, (packetClass, array) -> { + if (array == null) { + return new TimedActionStore[] {new TimedActionStore(action, checkClass.getCheckClass().getParent())}; + } else { + TimedActionStore[] newArray = Arrays.copyOf(array, array.length + 1); + newArray[array.length] = new TimedActionStore(action, checkClass.getCheckClass().getParent()); + return newArray; + } + }); + } } } }); @@ -187,11 +193,15 @@ public class APlayer { this.movement = null; } + public void disableCheck(String checkName) { + + } + public void callEvent(Event event) { if(events.containsKey(event.getClass())) { - WAction[] actions = (WAction[]) events.get(event.getClass()); - for (WAction action : actions) { - action.invoke(event); + ActionStore[] actions = (ActionStore[]) events.get(event.getClass()); + for (ActionStore action : actions) { + action.getAction().invoke(event); } } } @@ -199,15 +209,19 @@ public class APlayer { //TODO When using WPacket wrappers only, make this strictly WPacket param based only public void callPacket(Object packet, long timestamp) { if(events.containsKey(packet.getClass())) { - WAction[] actions = (WAction[]) events.get(packet.getClass()); - for (WAction action : actions) { - action.invoke(packet); + synchronized (events) { + ActionStore[] actions = events.get(packet.getClass()); + for (ActionStore action : actions) { + action.getAction().invoke(packet); + } } } if(eventsWithTimestamp.containsKey(packet.getClass())) { - TimedWAction[] actions = (TimedWAction[]) eventsWithTimestamp.get(packet.getClass()); - for (TimedWAction action : actions) { - action.invoke(packet, timestamp); + synchronized (events) { + TimedActionStore[] actions = eventsWithTimestamp.get(packet.getClass()); + for (TimedActionStore action : actions) { + action.getAction().invoke(packet, timestamp); + } } } } diff --git a/src/main/java/dev/brighten/ac/data/obj/ActionStore.java b/src/main/java/dev/brighten/ac/data/obj/ActionStore.java new file mode 100644 index 0000000..68f8aa6 --- /dev/null +++ b/src/main/java/dev/brighten/ac/data/obj/ActionStore.java @@ -0,0 +1,31 @@ +package dev.brighten.ac.data.obj; + +import dev.brighten.ac.check.Check; +import dev.brighten.ac.check.WAction; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Objects; +import java.util.UUID; + +@RequiredArgsConstructor +@Getter +public class ActionStore { + private final WAction action; + private final Class checkClass; + //To ensure duplicate actions are not added to the list + private final UUID uuid = UUID.randomUUID(); + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ActionStore that = (ActionStore) o; + return uuid.equals(that.uuid); + } + + @Override + public int hashCode() { + return Objects.hash(uuid); + } +} diff --git a/src/main/java/dev/brighten/ac/data/obj/TimedActionStore.java b/src/main/java/dev/brighten/ac/data/obj/TimedActionStore.java new file mode 100644 index 0000000..b9df22f --- /dev/null +++ b/src/main/java/dev/brighten/ac/data/obj/TimedActionStore.java @@ -0,0 +1,31 @@ +package dev.brighten.ac.data.obj; + +import dev.brighten.ac.check.Check; +import dev.brighten.ac.check.TimedWAction; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Objects; +import java.util.UUID; + +@RequiredArgsConstructor +@Getter +public class TimedActionStore { + private final TimedWAction action; + private final Class checkClass; + //To ensure duplicate actions are not added to the list + private final UUID uuid = UUID.randomUUID(); + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TimedActionStore that = (TimedActionStore) o; + return uuid.equals(that.uuid); + } + + @Override + public int hashCode() { + return Objects.hash(uuid); + } +} diff --git a/src/main/java/dev/brighten/ac/handler/VelocityHandler.java b/src/main/java/dev/brighten/ac/handler/VelocityHandler.java index cca3cd6..df941c3 100644 --- a/src/main/java/dev/brighten/ac/handler/VelocityHandler.java +++ b/src/main/java/dev/brighten/ac/handler/VelocityHandler.java @@ -1,6 +1,7 @@ package dev.brighten.ac.handler; import dev.brighten.ac.data.APlayer; +import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutEntityVelocity; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor @@ -8,7 +9,7 @@ public class VelocityHandler { private APlayer player; - public void onPre( packet) { + public void onPre(WPacketPlayOutEntityVelocity packet) { if(packet.getEntityId() != player.getBukkitPlayer().getEntityId()) return; } } diff --git a/src/main/java/dev/brighten/ac/listener/JoinListener.java b/src/main/java/dev/brighten/ac/listener/JoinListener.java index 18b64d7..13fb4ab 100644 --- a/src/main/java/dev/brighten/ac/listener/JoinListener.java +++ b/src/main/java/dev/brighten/ac/listener/JoinListener.java @@ -61,7 +61,7 @@ public class JoinListener implements Listener { case BLOCK_CHANGE: case MULTI_BLOCK_CHANGE: case MAP_CHUNK: { - if(player.getLagInfo().getLastClientTransaction().isPassed(100L)) { + if(player.getLagInfo().getLastClientTransaction().isPassed(100L) && player.getCreation().isPassed(2000L)) { synchronized (player.getPacketQueue()) { player.getPacketQueue().add(event.getPacket()); } @@ -78,7 +78,10 @@ public class JoinListener implements Listener { public void onJoin(PlayerJoinEvent event) { APlayer player = Anticheat.INSTANCE.getPlayerRegistry().generate(event.getPlayer()); - RunUtils.taskLater(() -> HandlerAbstract.getHandler().add(event.getPlayer()), 6); + RunUtils.taskLater(() -> { + if(event.getPlayer() != null && event.getPlayer().isOnline()) + HandlerAbstract.getHandler().add(event.getPlayer()); + }, 6); player.callEvent(event); } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 7a1bbdc..be9b039 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -2,4 +2,4 @@ name: Anticheat main: dev.brighten.ac.Anticheat version: 1.0 author: funkemunky -softdepend: [ViaVersion] \ No newline at end of file +softdepend: [ViaVersion, ProtocolSupport] \ No newline at end of file