From 3f57b77718ce228b473905742def893265df4c53 Mon Sep 17 00:00:00 2001 From: Rsl1122 Date: Mon, 27 Nov 2017 23:29:40 +0200 Subject: [PATCH] Advanced Anti Cheat (AAC) Data #125 --- PlanPluginBridge/pom.xml | 6 + .../djrapitops/pluginbridge/plan/Bridge.java | 3 + .../plan/aac/AdvancedAntiCheatData.java | 67 ++++++++++ .../plan/aac/AdvancedAntiCheatHook.java | 48 ++++++++ .../pluginbridge/plan/aac/HackObject.java | 45 +++++++ .../pluginbridge/plan/aac/HackerTable.java | 115 ++++++++++++++++++ .../plan/aac/PlayerHackKickListener.java | 58 +++++++++ 7 files changed, 342 insertions(+) create mode 100644 PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/AdvancedAntiCheatData.java create mode 100644 PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/AdvancedAntiCheatHook.java create mode 100644 PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/HackObject.java create mode 100644 PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/HackerTable.java create mode 100644 PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/PlayerHackKickListener.java diff --git a/PlanPluginBridge/pom.xml b/PlanPluginBridge/pom.xml index 896e2dec9..80f51ae03 100644 --- a/PlanPluginBridge/pom.xml +++ b/PlanPluginBridge/pom.xml @@ -141,6 +141,12 @@ 7.3.0 provided + + me.konsolas + AAC + 3.3.5 + provided + diff --git a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/Bridge.java b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/Bridge.java index 5b71f7dcd..51ce35c65 100644 --- a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/Bridge.java +++ b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/Bridge.java @@ -1,6 +1,7 @@ package com.djrapitops.pluginbridge.plan; import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.pluginbridge.plan.aac.AdvancedAntiCheatHook; import com.djrapitops.pluginbridge.plan.advancedachievements.AdvancedAchievementsHook; import com.djrapitops.pluginbridge.plan.askyblock.ASkyBlockHook; import com.djrapitops.pluginbridge.plan.banmanager.BanManagerHook; @@ -24,6 +25,7 @@ import main.java.com.djrapitops.plan.data.additional.HookHandler; * Manages connection to other plugins. * * @author Rsl1122 + * @see AdvancedAntiCheatHook * @see AdvancedAchievementsHook * @see ASkyBlockHook * @see BanManagerHook @@ -50,6 +52,7 @@ public class Bridge { public static void hook(HookHandler h) { Hook[] hooks = new Hook[]{ + new AdvancedAntiCheatHook(h), new AdvancedAchievementsHook(h), new ASkyBlockHook(h), new BanManagerHook(h), diff --git a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/AdvancedAntiCheatData.java b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/AdvancedAntiCheatData.java new file mode 100644 index 000000000..b2677c525 --- /dev/null +++ b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/AdvancedAntiCheatData.java @@ -0,0 +1,67 @@ +/* + * Licence is provided in the jar as license.yml also here: + * https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml + */ +package com.djrapitops.pluginbridge.plan.aac; + +import com.djrapitops.plugin.utilities.Format; +import main.java.com.djrapitops.plan.data.additional.*; +import main.java.com.djrapitops.plan.utilities.FormatUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * PluginData for AAC plugin. + * + * @author Rsl1122 + */ +public class AdvancedAntiCheatData extends PluginData { + + private final HackerTable table; + + public AdvancedAntiCheatData(HackerTable table) { + super(ContainerSize.THIRD, "AdvancedAntiCheat"); + super.setPluginIcon("heart"); + super.setIconColor("red"); + this.table = table; + } + + @Override + public InspectContainer getPlayerData(UUID uuid, InspectContainer inspectContainer) throws Exception { + List hackObjects = table.getHackObjects(uuid); + + inspectContainer.addValue(getWithIcon("Times Kicked for Possible Hacking", "exclamation-triangle", "red"), hackObjects.size()); + + TableContainer hackTable = new TableContainer( + getWithIcon("Kicked", "calendar"), + getWithIcon("Hack", "exclamation-triangle"), + getWithIcon("Violation Level", "gavel") + ); + hackTable.setColor("red"); + + for (HackObject hackObject : hackObjects) { + String date = FormatUtils.formatTimeStampYear(hackObject.getDate()); + String hack = Format.create(hackObject.getHackType().getName()).capitalize().toString(); + hackTable.addRow(date, hack, hackObject.getViolationLevel()); + } + inspectContainer.addTable("hackTable", hackTable); + + return inspectContainer; + } + + @Override + public AnalysisContainer getServerData(Collection collection, AnalysisContainer analysisContainer) throws Exception { + Map> hackObjects = table.getHackObjects(); + + Map violations = hackObjects.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().size())); + + analysisContainer.addPlayerTableValues(getWithIcon("Kicked for Hacking", "exclamation-triangle"), violations); + + return analysisContainer; + } +} \ No newline at end of file diff --git a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/AdvancedAntiCheatHook.java b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/AdvancedAntiCheatHook.java new file mode 100644 index 000000000..bd7e5deba --- /dev/null +++ b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/AdvancedAntiCheatHook.java @@ -0,0 +1,48 @@ +/* + * Licence is provided in the jar as license.yml also here: + * https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml + */ +package com.djrapitops.pluginbridge.plan.aac; + +import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.pluginbridge.plan.Hook; +import main.java.com.djrapitops.plan.Plan; +import main.java.com.djrapitops.plan.api.exceptions.DBCreateTableException; +import main.java.com.djrapitops.plan.data.additional.HookHandler; +import main.java.com.djrapitops.plan.database.databases.SQLDB; + +/** + * Hook for AAC plugin. + * + * @author Rsl1122 + */ +public class AdvancedAntiCheatHook extends Hook { + + private static PlayerHackKickListener listener; + + public AdvancedAntiCheatHook(HookHandler hookHandler) { + super("me.konsolas.aac.AAC", hookHandler); + } + + @Override + public void hook() throws NoClassDefFoundError { + if (!enabled) { + return; + } + Plan plugin = Plan.getInstance(); + + HackerTable table = new HackerTable((SQLDB) plugin.getDB()); + try { + table.createTable(); + } catch (DBCreateTableException e) { + Log.toLog(this.getClass().getName(), e); + return; + } + + if (listener == null) { + listener = new PlayerHackKickListener(); + plugin.registerListener(listener); + } + addPluginDataSource(new AdvancedAntiCheatData(table)); + } +} \ No newline at end of file diff --git a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/HackObject.java b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/HackObject.java new file mode 100644 index 000000000..89103f048 --- /dev/null +++ b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/HackObject.java @@ -0,0 +1,45 @@ +/* + * Licence is provided in the jar as license.yml also here: + * https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml + */ +package com.djrapitops.pluginbridge.plan.aac; + +import me.konsolas.aac.api.HackType; + +import java.util.UUID; + +/** + * Data object for AAC data. + * + * @author Rsl1122 + */ +public class HackObject { + + private final UUID uuid; + private final long date; + private final HackType hackType; + private final int violationLevel; + + public HackObject(UUID uuid, long date, HackType hackType, int violationLevel) { + this.uuid = uuid; + this.date = date; + this.hackType = hackType; + this.violationLevel = violationLevel; + } + + public UUID getUuid() { + return uuid; + } + + public long getDate() { + return date; + } + + public HackType getHackType() { + return hackType; + } + + public int getViolationLevel() { + return violationLevel; + } +} \ No newline at end of file diff --git a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/HackerTable.java b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/HackerTable.java new file mode 100644 index 000000000..aa39a3dd1 --- /dev/null +++ b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/HackerTable.java @@ -0,0 +1,115 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.djrapitops.pluginbridge.plan.aac; + +import main.java.com.djrapitops.plan.api.exceptions.DBCreateTableException; +import main.java.com.djrapitops.plan.database.databases.SQLDB; +import main.java.com.djrapitops.plan.database.processing.ExecStatement; +import main.java.com.djrapitops.plan.database.processing.QueryAllStatement; +import main.java.com.djrapitops.plan.database.processing.QueryStatement; +import main.java.com.djrapitops.plan.database.sql.Select; +import main.java.com.djrapitops.plan.database.tables.Table; +import me.konsolas.aac.api.HackType; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.*; + +/** + * Class responsible for AAC kick information in Plan database. + * + * @author Rsl1122 + * @since 3.5.0 + */ +public class HackerTable extends Table { + + private final String columnUUID; + private final String columnDate; + private final String columnHackType; + private final String columnViolations; + + public HackerTable(SQLDB db) { + super("plan_viaversion_protocol", db, db.isUsingMySQL()); + columnUUID = "uuid"; + columnDate = "date"; + columnHackType = "hack_type"; + columnViolations = "violation_level"; + } + + @Override + public void createTable() throws DBCreateTableException { + createTable("CREATE TABLE IF NOT EXISTS " + tableName + " (" + + columnUUID + " varchar(36) NOT NULL UNIQUE, " + + columnDate + " bigint NOT NULL, " + + columnHackType + " varchar(100) NOT NULL, " + + columnViolations + " integer NOT NULL" + + ")" + ); + } + + public List getHackObjects(UUID uuid) throws SQLException { + String sql = "SELECT * FROM " + tableName + " WHERE " + columnUUID + "=?"; + + return query(new QueryStatement>(sql) { + @Override + public void prepare(PreparedStatement statement) throws SQLException { + statement.setString(1, uuid.toString()); + } + + @Override + public List processResults(ResultSet set) throws SQLException { + List hackObjects = new ArrayList<>(); + while (set.next()) { + UUID uuid = UUID.fromString(set.getString(columnUUID)); + long date = set.getLong(columnDate); + HackType hackType = HackType.valueOf(set.getString(columnHackType)); + int violationLevel = set.getInt(columnViolations); + hackObjects.add(new HackObject(uuid, date, hackType, violationLevel)); + } + return hackObjects; + } + }); + } + + public Map> getHackObjects() throws SQLException { + return query(new QueryAllStatement>>(Select.all(tableName).toString(), 5000) { + @Override + public Map> processResults(ResultSet set) throws SQLException { + Map> hackObjects = new HashMap<>(); + while (set.next()) { + UUID uuid = UUID.fromString(set.getString(columnUUID)); + long date = set.getLong(columnDate); + HackType hackType = HackType.valueOf(set.getString(columnHackType)); + int violationLevel = set.getInt(columnViolations); + List list = hackObjects.getOrDefault(uuid, new ArrayList<>()); + list.add(new HackObject(uuid, date, hackType, violationLevel)); + hackObjects.put(uuid, list); + } + return hackObjects; + } + }); + } + + public void insertHackRow(HackObject hackObject) throws SQLException { + String sql = "INSERT INTO " + tableName + " (" + + columnUUID + ", " + + columnDate + ", " + + columnHackType + ", " + + columnViolations + + ") VALUES (?, ?, ?, ?)"; + + execute(new ExecStatement(sql) { + @Override + public void prepare(PreparedStatement statement) throws SQLException { + statement.setString(1, hackObject.getUuid().toString()); + statement.setLong(2, hackObject.getDate()); + statement.setString(3, hackObject.getHackType().getName()); + statement.setInt(4, hackObject.getViolationLevel()); + } + }); + } +} diff --git a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/PlayerHackKickListener.java b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/PlayerHackKickListener.java new file mode 100644 index 000000000..5eeb3e674 --- /dev/null +++ b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/aac/PlayerHackKickListener.java @@ -0,0 +1,58 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.djrapitops.pluginbridge.plan.aac; + + +import com.djrapitops.plugin.api.utility.log.Log; +import main.java.com.djrapitops.plan.Plan; +import main.java.com.djrapitops.plan.database.databases.SQLDB; +import main.java.com.djrapitops.plan.systems.processing.Processor; +import main.java.com.djrapitops.plan.utilities.MiscUtils; +import me.konsolas.aac.api.AACAPIProvider; +import me.konsolas.aac.api.HackType; +import me.konsolas.aac.api.PlayerViolationCommandEvent; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import java.sql.SQLException; +import java.util.UUID; + +/** + * Class responsible for listening kick events made by AAC. + * + * @author Rsl1122 + * @since 4.1.0 + */ +public class PlayerHackKickListener implements Listener { + + @EventHandler(priority = EventPriority.MONITOR) + public void onKick(PlayerViolationCommandEvent event) { + if (event.isCancelled()) { + return; + } + + Player player = event.getPlayer(); + UUID uuid = player.getUniqueId(); + HackType hackType = event.getHackType(); + long time = MiscUtils.getTime(); + int violations = AACAPIProvider.getAPI().getViolationLevel(player, hackType); + + HackObject hackObject = new HackObject(uuid, time, hackType, violations); + Plan plan = Plan.getInstance(); + plan.addToProcessQueue(new Processor(uuid) { + @Override + public void process() { + try { + new HackerTable((SQLDB) plan.getDB()).insertHackRow(hackObject); + } catch (SQLException e) { + Log.toLog(this.getClass().getName() + ":PlanViaVersionJoinListener", e); + } + } + }); + } +}