From d1af4f93773f8245e552e4bb635a550a11336983 Mon Sep 17 00:00:00 2001 From: Pugzy Date: Wed, 11 Oct 2023 19:14:17 +0100 Subject: [PATCH 1/5] Toggle grim for non-match participants --- pom.xml | 16 +++++ src/main/java/tc/oc/occ/cheaty/Cheaty.java | 8 +++ .../oc/occ/cheaty/anticheat/GrimManager.java | 50 ++++++++++++++ .../anticheat/GrimParticipationListener.java | 66 +++++++++++++++++++ .../tc/oc/occ/cheaty/anticheat/GrimUtil.java | 32 +++++++++ .../oc/occ/cheaty/commands/GrimCommands.java | 65 ++++++++++++++++++ src/main/resources/plugin.yml | 2 +- 7 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java create mode 100644 src/main/java/tc/oc/occ/cheaty/anticheat/GrimParticipationListener.java create mode 100644 src/main/java/tc/oc/occ/cheaty/anticheat/GrimUtil.java create mode 100644 src/main/java/tc/oc/occ/cheaty/commands/GrimCommands.java diff --git a/pom.xml b/pom.xml index 77465f5..00d7499 100644 --- a/pom.xml +++ b/pom.xml @@ -9,6 +9,10 @@ + + jitpack.io + https://jitpack.io + pgm-repo-snapshots https://repo.pgm.fyi/snapshots @@ -60,6 +64,18 @@ 0.2-SNAPSHOT provided + + com.github.MWHunter + GrimAPI + c3a80bd + provided + + + ac.grim.grimac + grimac + 2.3.45 + provided + diff --git a/src/main/java/tc/oc/occ/cheaty/Cheaty.java b/src/main/java/tc/oc/occ/cheaty/Cheaty.java index aa1ebd8..362e561 100644 --- a/src/main/java/tc/oc/occ/cheaty/Cheaty.java +++ b/src/main/java/tc/oc/occ/cheaty/Cheaty.java @@ -2,6 +2,8 @@ import co.aikar.commands.BukkitCommandManager; import org.bukkit.plugin.java.JavaPlugin; +import tc.oc.occ.cheaty.anticheat.GrimManager; +import tc.oc.occ.cheaty.anticheat.GrimUtil; import tc.oc.occ.cheaty.commands.AdminCommands; import tc.oc.occ.cheaty.commands.BotCommands; import tc.oc.occ.cheaty.commands.CheatNotifyCommand; @@ -10,6 +12,7 @@ public class Cheaty extends JavaPlugin { private DiscordBot bot; private BotConfig config; + private GrimManager grimManager; private BukkitCommandManager commands; @Override @@ -19,6 +22,7 @@ public void onEnable() { this.config = new BotConfig(getConfig()); this.bot = new DiscordBot(config, getLogger()); + this.grimManager = GrimUtil.createManager(); this.setupCommands(); this.registerListeners(); @@ -36,10 +40,14 @@ public void setupCommands() { commands.registerCommand(new BotCommands()); commands.registerCommand(new AdminCommands()); commands.registerCommand(new CheatNotifyCommand()); + + GrimUtil.createCommands(grimManager, commands); } private void registerListeners() { this.getServer().getPluginManager().registerEvents(new BotListener(bot), this); + + GrimUtil.registerListeners(grimManager, this); } public void reloadBotConfig() { diff --git a/src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java b/src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java new file mode 100644 index 0000000..9398e02 --- /dev/null +++ b/src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java @@ -0,0 +1,50 @@ +package tc.oc.occ.cheaty.anticheat; + +import ac.grim.grimac.GrimAbstractAPI; +import ac.grim.grimac.GrimUser; +import ac.grim.grimac.player.GrimPlayer; +import javax.annotation.Nullable; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.plugin.RegisteredServiceProvider; + +public class GrimManager { + + private GrimAbstractAPI api; + + public GrimManager() { + GrimAbstractAPI api = null; + RegisteredServiceProvider provider = + Bukkit.getServicesManager().getRegistration(GrimAbstractAPI.class); + if (provider != null) api = provider.getProvider(); + if (api == null) return; + + this.api = api; + } + + public boolean setPlayerBypass(Player player, boolean shouldBypass) { + GrimUser grimUser = api.getGrimUser(player); + if (!(grimUser instanceof GrimPlayer)) return false; + + GrimPlayer grimPlayer = (GrimPlayer) grimUser; + grimPlayer.disableGrim = shouldBypass; + + return true; + } + + public boolean togglePlayerBypass(Player player) { + GrimPlayer grimPlayer = getGrimPlayer(player); + if (grimPlayer == null) return true; + + grimPlayer.disableGrim = !grimPlayer.disableGrim; + + return grimPlayer.disableGrim; + } + + public @Nullable GrimPlayer getGrimPlayer(Player player) { + GrimUser grimUser = api.getGrimUser(player); + if (!(grimUser instanceof GrimPlayer)) return null; + + return (GrimPlayer) grimUser; + } +} diff --git a/src/main/java/tc/oc/occ/cheaty/anticheat/GrimParticipationListener.java b/src/main/java/tc/oc/occ/cheaty/anticheat/GrimParticipationListener.java new file mode 100644 index 0000000..00ff9c5 --- /dev/null +++ b/src/main/java/tc/oc/occ/cheaty/anticheat/GrimParticipationListener.java @@ -0,0 +1,66 @@ +package tc.oc.occ.cheaty.anticheat; + +import ac.grim.grimac.player.GrimPlayer; +import java.util.function.BooleanSupplier; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitRunnable; +import tc.oc.pgm.spawns.events.ParticipantDespawnEvent; +import tc.oc.pgm.spawns.events.ParticipantSpawnEvent; + +public class GrimParticipationListener implements Listener { + + private final Plugin plugin; + private final GrimManager grimManager; + + public GrimParticipationListener(Plugin plugin, GrimManager grimManager) { + this.plugin = plugin; + this.grimManager = grimManager; + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onPlayerJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + new ResolverTask( + () -> { + if (!player.isOnline()) return true; + if (player.spigot().getCollidesWithEntities()) return true; + + GrimPlayer grimPlayer = grimManager.getGrimPlayer(player); + if (grimPlayer == null) return false; + + grimManager.setPlayerBypass(player, true); + return true; + }) + .runTaskTimer(plugin, 1L, 5L); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onParticipantSpawn(ParticipantSpawnEvent event) { + grimManager.setPlayerBypass(event.getPlayer().getBukkit(), false); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onParticipantDespawn(ParticipantDespawnEvent event) { + grimManager.setPlayerBypass(event.getPlayer().getBukkit(), true); + } + + public static class ResolverTask extends BukkitRunnable { + + private final BooleanSupplier task; + private int attempts = 0; + + public ResolverTask(BooleanSupplier task) { + this.task = task; + } + + @Override + public void run() { + if (task.getAsBoolean() || attempts++ >= 20) this.cancel(); + } + } +} diff --git a/src/main/java/tc/oc/occ/cheaty/anticheat/GrimUtil.java b/src/main/java/tc/oc/occ/cheaty/anticheat/GrimUtil.java new file mode 100644 index 0000000..5196362 --- /dev/null +++ b/src/main/java/tc/oc/occ/cheaty/anticheat/GrimUtil.java @@ -0,0 +1,32 @@ +package tc.oc.occ.cheaty.anticheat; + +import co.aikar.commands.BukkitCommandManager; +import tc.oc.occ.cheaty.Cheaty; +import tc.oc.occ.cheaty.commands.GrimCommands; + +public class GrimUtil { + + public static GrimManager createManager() { + try { + Class.forName("ac.grim.grimac.GrimAC"); + return new GrimManager(); + } catch (ClassNotFoundException ignored) { + return null; + } + } + + public static void createCommands(GrimManager grimManager, BukkitCommandManager commands) { + if (grimManager == null) return; + + commands.registerCommand(new GrimCommands(grimManager)); + } + + public static void registerListeners(GrimManager grimManager, Cheaty plugin) { + if (grimManager == null) return; + + plugin + .getServer() + .getPluginManager() + .registerEvents(new GrimParticipationListener(plugin, grimManager), plugin); + } +} diff --git a/src/main/java/tc/oc/occ/cheaty/commands/GrimCommands.java b/src/main/java/tc/oc/occ/cheaty/commands/GrimCommands.java new file mode 100644 index 0000000..0d25eba --- /dev/null +++ b/src/main/java/tc/oc/occ/cheaty/commands/GrimCommands.java @@ -0,0 +1,65 @@ +package tc.oc.occ.cheaty.commands; + +import ac.grim.grimac.player.GrimPlayer; +import co.aikar.commands.BaseCommand; +import co.aikar.commands.InvalidCommandArgument; +import co.aikar.commands.annotation.CommandAlias; +import co.aikar.commands.annotation.CommandPermission; +import co.aikar.commands.annotation.Dependency; +import co.aikar.commands.annotation.Description; +import co.aikar.commands.annotation.Optional; +import co.aikar.commands.annotation.Subcommand; +import co.aikar.commands.annotation.Syntax; +import co.aikar.commands.bukkit.contexts.OnlinePlayer; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import tc.oc.occ.cheaty.Cheaty; +import tc.oc.occ.cheaty.anticheat.GrimManager; + +@CommandAlias("cheaty") +public class GrimCommands extends BaseCommand { + + private final GrimManager grimManager; + @Dependency private Cheaty plugin; + + public GrimCommands(GrimManager grimManager) { + this.grimManager = grimManager; + } + + @Subcommand("grim status") + @Description("Check the bypass status of player") + @Syntax("[player]") + @CommandPermission("cheaty.admin") + public void status(CommandSender sender, @Optional OnlinePlayer player) { + Player target = getTargetPlayer(sender, player); + + GrimPlayer grimPlayer = grimManager.getGrimPlayer(target); + if (grimPlayer == null) + throw new InvalidCommandArgument("Unable to resolve target as grim player"); + + boolean status = grimPlayer.disableGrim; + + sender.sendMessage( + target.getDisplayName() + " Status: " + ((status) ? "Except" : "Not Exempt")); + } + + @Subcommand("grim toggle") + @Description("Toggles bypass status of player") + @Syntax("[player]") + @CommandPermission("cheaty.admin") + public void toggle(CommandSender sender, @Optional OnlinePlayer player) { + Player target = getTargetPlayer(sender, player); + boolean toggleStatus = grimManager.togglePlayerBypass(target); + + sender.sendMessage( + target.getDisplayName() + " Status: " + ((toggleStatus) ? "Except" : "Not Exempt")); + } + + private Player getTargetPlayer(CommandSender sender, OnlinePlayer onlinePlayer) { + if (onlinePlayer != null) return onlinePlayer.getPlayer(); + + if (sender instanceof Player) return ((Player) sender).getPlayer(); + + throw new InvalidCommandArgument("Unable to resolve target player"); + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index f666fa4..4502d39 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -3,4 +3,4 @@ main: tc.oc.occ.cheaty.Cheaty description: A minecraft to discord bot version: ${project.version} author: applenick -softdepend: [PGM, AutoKiller, Idly] +softdepend: [PGM, AutoKiller, Idly, GrimAC] From c004742b1d882fadd5b1aad48ae0fae10472d0fb Mon Sep 17 00:00:00 2001 From: Pugzy Date: Sat, 14 Oct 2023 00:07:07 +0100 Subject: [PATCH 2/5] Add checks for null bukkit user --- .../cheaty/anticheat/GrimParticipationListener.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/tc/oc/occ/cheaty/anticheat/GrimParticipationListener.java b/src/main/java/tc/oc/occ/cheaty/anticheat/GrimParticipationListener.java index 00ff9c5..4f54152 100644 --- a/src/main/java/tc/oc/occ/cheaty/anticheat/GrimParticipationListener.java +++ b/src/main/java/tc/oc/occ/cheaty/anticheat/GrimParticipationListener.java @@ -41,12 +41,18 @@ public void onPlayerJoin(PlayerJoinEvent event) { @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) public void onParticipantSpawn(ParticipantSpawnEvent event) { - grimManager.setPlayerBypass(event.getPlayer().getBukkit(), false); + Player bukkitPlayer = event.getPlayer().getBukkit(); + if (bukkitPlayer == null) return; + + grimManager.setPlayerBypass(bukkitPlayer, false); } @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) public void onParticipantDespawn(ParticipantDespawnEvent event) { - grimManager.setPlayerBypass(event.getPlayer().getBukkit(), true); + Player bukkitPlayer = event.getPlayer().getBukkit(); + if (bukkitPlayer == null) return; + + grimManager.setPlayerBypass(bukkitPlayer, true); } public static class ResolverTask extends BukkitRunnable { From 2034281396b4a26e967b0a20a250baa8faedef4a Mon Sep 17 00:00:00 2001 From: Pugzy Date: Sun, 29 Oct 2023 09:32:42 +0000 Subject: [PATCH 3/5] Add null check when setting bypass of player --- src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java b/src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java index 9398e02..9dd6d6b 100644 --- a/src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java +++ b/src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java @@ -23,6 +23,7 @@ public GrimManager() { } public boolean setPlayerBypass(Player player, boolean shouldBypass) { + if (player == null) return false; GrimUser grimUser = api.getGrimUser(player); if (!(grimUser instanceof GrimPlayer)) return false; From ae213ba25727d1f764c803a84cca0ffb1c42874f Mon Sep 17 00:00:00 2001 From: Pugzy Date: Sat, 11 Nov 2023 16:52:02 +0000 Subject: [PATCH 4/5] Add try catch to "fix" NPE issue --- pom.xml | 2 +- .../java/tc/oc/occ/cheaty/anticheat/GrimManager.java | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 00d7499..37f70d7 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 tc.oc.occ Cheaty - 1.2.0-SNAPSHOT + 1.2.1-SNAPSHOT Cheaty A minecraft to discord java plugin for anti-cheat logging diff --git a/src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java b/src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java index 9dd6d6b..7c2e6a5 100644 --- a/src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java +++ b/src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java @@ -24,7 +24,16 @@ public GrimManager() { public boolean setPlayerBypass(Player player, boolean shouldBypass) { if (player == null) return false; - GrimUser grimUser = api.getGrimUser(player); + + // Grim can internally throw an NPE when getting a player that is being removed + // This occurs when a player disconnects + GrimUser grimUser; + try { + grimUser = api.getGrimUser(player); + } catch (NullPointerException ignored) { + return false; + } + if (!(grimUser instanceof GrimPlayer)) return false; GrimPlayer grimPlayer = (GrimPlayer) grimUser; From 8d2e52346e2e496d368d6282674715d8f2db3ea3 Mon Sep 17 00:00:00 2001 From: Pugzy Date: Mon, 6 May 2024 11:11:40 +0100 Subject: [PATCH 5/5] Bump GrimAC versions --- pom.xml | 4 ++-- src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 37f70d7..4790645 100644 --- a/pom.xml +++ b/pom.xml @@ -67,13 +67,13 @@ com.github.MWHunter GrimAPI - c3a80bd + 9f5aaef74b provided ac.grim.grimac grimac - 2.3.45 + 2.3.62 provided diff --git a/src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java b/src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java index 7c2e6a5..f9d3b2a 100644 --- a/src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java +++ b/src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java @@ -1,7 +1,7 @@ package tc.oc.occ.cheaty.anticheat; -import ac.grim.grimac.GrimAbstractAPI; -import ac.grim.grimac.GrimUser; +import ac.grim.grimac.api.GrimAbstractAPI; +import ac.grim.grimac.api.GrimUser; import ac.grim.grimac.player.GrimPlayer; import javax.annotation.Nullable; import org.bukkit.Bukkit;