diff --git a/pom.xml b/pom.xml
index 77465f5..4790645 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,13 +2,17 @@
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
+
+ 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
+ 9f5aaef74b
+ provided
+
+
+ ac.grim.grimac
+ grimac
+ 2.3.62
+ 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..f9d3b2a
--- /dev/null
+++ b/src/main/java/tc/oc/occ/cheaty/anticheat/GrimManager.java
@@ -0,0 +1,60 @@
+package tc.oc.occ.cheaty.anticheat;
+
+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;
+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) {
+ if (player == null) return false;
+
+ // 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;
+ 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..4f54152
--- /dev/null
+++ b/src/main/java/tc/oc/occ/cheaty/anticheat/GrimParticipationListener.java
@@ -0,0 +1,72 @@
+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) {
+ Player bukkitPlayer = event.getPlayer().getBukkit();
+ if (bukkitPlayer == null) return;
+
+ grimManager.setPlayerBypass(bukkitPlayer, false);
+ }
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onParticipantDespawn(ParticipantDespawnEvent event) {
+ Player bukkitPlayer = event.getPlayer().getBukkit();
+ if (bukkitPlayer == null) return;
+
+ grimManager.setPlayerBypass(bukkitPlayer, 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]