├── .github └── ISSUE_TEMPLATE │ ├── bug-or-plugin-incompatibility.md │ └── feature-request.md ├── .gitignore ├── .idea └── .gitignore ├── LICENSE ├── README.md ├── pom.xml └── src └── main ├── java └── de │ └── sportkanone123 │ └── clientdetector │ ├── bungeecord │ └── ClientDetectorBungee.java │ ├── spigot │ ├── ClientDetector.java │ ├── api │ │ ├── ClientDetectorAPI.java │ │ └── events │ │ │ ├── ClientDetectedEvent.java │ │ │ ├── ForgeModlistDetectedEvent.java │ │ │ └── ModDetectedEvent.java │ ├── bungee │ │ ├── BungeeManager.java │ │ └── DataType.java │ ├── client │ │ ├── Client.java │ │ └── processor │ │ │ ├── PacketProcessor.java │ │ │ └── PluginMessageProcessor.java │ ├── clientcontrol │ │ ├── ClientControl.java │ │ └── impl │ │ │ ├── Badlion.java │ │ │ ├── BetterSprinting.java │ │ │ ├── FiveZig.java │ │ │ ├── LabyMod.java │ │ │ ├── LunarClient.java │ │ │ └── WorldDownloader.java │ ├── command │ │ ├── Command.java │ │ └── impl │ │ │ ├── ClientDisabler.java │ │ │ ├── Forge.java │ │ │ ├── GUI.java │ │ │ ├── Help.java │ │ │ ├── Player.java │ │ │ └── Reload.java │ ├── discord │ │ └── DiscordWebhook.java │ ├── forgemod │ │ ├── ForgeHandler.java │ │ ├── ModList.java │ │ ├── legacy │ │ │ ├── ForgeHandler.java │ │ │ └── ForgeHandshake.java │ │ └── newerversion │ │ │ ├── ForgeHandler.java │ │ │ └── ForgeHandshake.java │ ├── hackdetector │ │ ├── HackDetector.java │ │ └── impl │ │ │ ├── AntiFastMath.java │ │ │ └── ChatExploit.java │ ├── listener │ │ ├── NetworkListener.java │ │ ├── PlayerListener.java │ │ └── PluginMessageListener.java │ ├── manager │ │ ├── AlertsManager.java │ │ ├── ClientManager.java │ │ ├── ConfigManager.java │ │ ├── DiscordManager.java │ │ ├── GeyserManager.java │ │ ├── MetricsManager.java │ │ ├── ModManager.java │ │ └── PlaceholderManager.java │ ├── mod │ │ ├── Mod.java │ │ └── processor │ │ │ ├── PacketProcessor.java │ │ │ └── PluginMessageProcessor.java │ └── packet │ │ ├── Packet.java │ │ └── processor │ │ └── PacketProcessor.java │ └── velocity │ └── ClientDetectorVelocity.java └── resources ├── bungee.yml ├── clientcontrol.yml ├── config.yml ├── message.yml └── plugin.yml /.github/ISSUE_TEMPLATE/bug-or-plugin-incompatibility.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug or Plugin Incompatibility 3 | about: Report issues with plugin incompatibility or other bugs. 4 | title: '' 5 | labels: bug 6 | assignees: Sportkanone123 7 | 8 | --- 9 | 10 | **General Information** 11 | Server version: (e.g.: Paper/Spigot 1.19.2) 12 | Client version: (e.g.: Vanilla/Fabric/Forge/Badlion/Lunar 1.19.2) 13 | Plugin version: (e.g.: 2.5.3) 14 | 15 | 16 | **Describe the bug** 17 | A clear and concise description of what the bug is. 18 | 19 | **To Reproduce** 20 | Steps to reproduce the behavior. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Suggest an idea for ClientDetector 4 | title: '' 5 | labels: enhancement 6 | assignees: Sportkanone123 7 | 8 | --- 9 | 10 | **Your suggestion/idea.** 11 | A clear and concise description of your idea and why it should be added to ClientDetector. 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.log 3 | *.jar 4 | 5 | *.war 6 | *.ear 7 | *.zip 8 | *.tar.gz 9 | *.rar 10 | *.xml 11 | 12 | target 13 | .fleet 14 | 15 | ClientDetector 2.0.iml 16 | 17 | hs_err_pid* -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![](https://img.shields.io/badge/license-GPLv3-blue)](https://github.com/Sportkanone123/ClientDetector/blob/master/LICENSE) 2 | [![CodeFactor](https://www.codefactor.io/repository/github/sportkanone123/clientdetector/badge/master)](https://www.codefactor.io/repository/github/sportkanone123/clientdetector/overview/master) 3 | 4 | # ClientDetector 5 | *A simple plugin to detect and manage a player's client/mods* 6 | 7 | ### Resources 8 | * [SpigotMC](https://www.spigotmc.org/resources/clientdetector.90375/) 9 | 10 | ### License 11 | This project is licensed under the GPLv3 License - see the [LICENSE](https://github.com/Sportkanone123/ClientDetector/blob/master/LICENSE) file for details 12 | 13 | ### Additional Information 14 | ClientDetector uses the PacketEvents API. Check it out here: https://github.com/retrooper/packetevents 15 | 16 | ### Clients 17 | * "Vanilla (Undetectable)" 18 | * "Forge" 19 | * "5zig Mod" 20 | * "LabyMod" 21 | * "Aristois (Experimental)" 22 | * "Vivecraft" 23 | * "MysteryMod" 24 | * "Hyperium" 25 | * "PXMod" 26 | * "Pixel Client" 27 | * "LiteLoader" 28 | * "PvPLounge Client" 29 | * "Fabric" 30 | * "Lunar Client" 31 | * "Rift" 32 | * "Cracked Vape" 33 | * "Winterware" 34 | * "Feather Client" 35 | 36 | ### Mods 37 | * "5zig Mod" 38 | * "Better Sprinting Mod" 39 | * "World Downloader" 40 | * "JourneyMap" 41 | * "WorldEditCUI" 42 | 43 | ### Forge Mods 44 | * All Forge Mods from 1.8 - 1.17.1 (with some limitations) 45 | 46 | ### Contributors 47 | 48 | 49 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | de.sportkanone123 8 | ClientDetector 9 | 2.5.6 10 | 11 | 12 | 8 13 | 8 14 | 15 | 16 | 17 | 18 | 19 | org.apache.maven.plugins 20 | maven-compiler-plugin 21 | 3.7.0 22 | 23 | 8 24 | 8 25 | -XDignore.symbol.file 26 | 27 | 28 | com.velocitypowered 29 | velocity-api 30 | 3.0.1 31 | 32 | 33 | 34 | 35 | 36 | org.apache.maven.plugins 37 | maven-shade-plugin 38 | 3.1.0 39 | 40 | 41 | package 42 | 43 | shade 44 | 45 | 46 | false 47 | ClientDetector 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | src/main/resources 56 | true 57 | 58 | 59 | 60 | 61 | 62 | 63 | codemc-snapshots 64 | https://repo.codemc.io/repository/maven-snapshots/ 65 | 66 | 67 | 68 | placeholderapi 69 | https://repo.extendedclip.com/content/repositories/placeholderapi/ 70 | 71 | 72 | 73 | spigot-repo 74 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 75 | 76 | 77 | 78 | bungeecord-repo 79 | https://oss.sonatype.org/content/repositories/snapshots 80 | 81 | 82 | 83 | dmulloy2-repo 84 | https://repo.dmulloy2.net/repository/public/ 85 | 86 | 87 | 88 | papermc 89 | https://repo.papermc.io/repository/maven-public/ 90 | 91 | 92 | 93 | 94 | 95 | com.github.retrooper.packetevents 96 | spigot 97 | 2.0.0-SNAPSHOT 98 | 99 | 100 | 101 | org.projectlombok 102 | lombok 103 | 1.18.26 104 | provided 105 | 106 | 107 | 108 | me.clip 109 | placeholderapi 110 | 2.11.3 111 | provided 112 | 113 | 114 | 115 | net.md-5 116 | bungeecord-api 117 | 1.16-R0.5-SNAPSHOT 118 | jar 119 | provided 120 | 121 | 122 | 123 | org.spigotmc 124 | spigot 125 | 1.16.5-R0.1-SNAPSHOT 126 | provided 127 | 128 | 129 | 130 | com.velocitypowered 131 | velocity-api 132 | 3.1.1 133 | provided 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/bungeecord/ClientDetectorBungee.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.bungeecord; 20 | 21 | import net.md_5.bungee.api.ProxyServer; 22 | import net.md_5.bungee.api.config.ServerInfo; 23 | import net.md_5.bungee.api.event.PlayerDisconnectEvent; 24 | import net.md_5.bungee.api.event.PluginMessageEvent; 25 | import net.md_5.bungee.api.plugin.Command; 26 | import net.md_5.bungee.api.plugin.Listener; 27 | import net.md_5.bungee.api.plugin.Plugin; 28 | import net.md_5.bungee.event.EventHandler; 29 | 30 | import java.nio.charset.StandardCharsets; 31 | import java.util.*; 32 | import java.util.concurrent.TimeUnit; 33 | 34 | public class ClientDetectorBungee extends Plugin implements Listener { 35 | public static Plugin plugin; 36 | private Map> queue = new HashMap<>(); 37 | 38 | @Override 39 | public void onEnable() { 40 | plugin = this; 41 | 42 | ProxyServer.getInstance().getPluginManager().registerListener(this, this); 43 | 44 | ProxyServer.getInstance().registerChannel("cd:bungee"); 45 | 46 | runQueue(); 47 | } 48 | 49 | public void runQueue() { 50 | getProxy().getScheduler().schedule(this, new Runnable() { 51 | @Override 52 | public void run() { 53 | for(ServerInfo serverInfo : queue.keySet()){ 54 | if(!serverInfo.getPlayers().isEmpty() && queue.get(serverInfo) != null){ 55 | List toRemove = new ArrayList<>(); 56 | for(byte[] data : queue.get(serverInfo)){ 57 | toRemove.add(data); 58 | serverInfo.sendData("cd:spigot", data); 59 | } 60 | queue.get(serverInfo).removeAll(toRemove); 61 | } 62 | } 63 | } 64 | }, 1, 1, TimeUnit.SECONDS); 65 | } 66 | 67 | @EventHandler 68 | public void onPluginMessage(PluginMessageEvent event) { 69 | if(event.getTag().equalsIgnoreCase("cd:bungee")){ 70 | sync(event.getData()); 71 | } 72 | } 73 | 74 | private void sync(String string){ 75 | sync(string.getBytes(StandardCharsets.UTF_8)); 76 | } 77 | 78 | private void sync(byte[] data){ 79 | for(ServerInfo server : ProxyServer.getInstance().getServers().values()){ 80 | if(server.getPlayers().isEmpty()){ 81 | if(queue.get(server) == null) queue.put(server, new ArrayList<>()); 82 | 83 | if(!new String(data, StandardCharsets.UTF_8).contains("CROSS_SERVER_MESSAGE")) 84 | queue.get(server).add(data); 85 | }else{ 86 | server.sendData("cd:spigot", data); 87 | } 88 | } 89 | } 90 | 91 | @EventHandler 92 | public void onLeave(PlayerDisconnectEvent e) { 93 | String placeholder = "@@"; 94 | sync("PLAYER_LEFT" + placeholder + e.getPlayer().getName()); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/ClientDetector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot; 20 | 21 | import com.github.retrooper.packetevents.PacketEvents; 22 | import com.github.retrooper.packetevents.manager.server.ServerVersion; 23 | import de.sportkanone123.clientdetector.spigot.bungee.BungeeManager; 24 | import de.sportkanone123.clientdetector.spigot.client.Client; 25 | import de.sportkanone123.clientdetector.spigot.clientcontrol.ClientControl; 26 | import de.sportkanone123.clientdetector.spigot.command.Command; 27 | import de.sportkanone123.clientdetector.spigot.forgemod.ModList; 28 | import de.sportkanone123.clientdetector.spigot.hackdetector.HackDetector; 29 | import de.sportkanone123.clientdetector.spigot.hackdetector.impl.AntiFastMath; 30 | import de.sportkanone123.clientdetector.spigot.listener.NetworkListener; 31 | import de.sportkanone123.clientdetector.spigot.listener.PlayerListener; 32 | import de.sportkanone123.clientdetector.spigot.listener.PluginMessageListener; 33 | import de.sportkanone123.clientdetector.spigot.manager.*; 34 | import de.sportkanone123.clientdetector.spigot.mod.Mod; 35 | import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder; 36 | import org.bukkit.Bukkit; 37 | import org.bukkit.ChatColor; 38 | import org.bukkit.plugin.Plugin; 39 | import org.bukkit.plugin.java.JavaPlugin; 40 | 41 | import java.io.IOException; 42 | import java.util.ArrayList; 43 | import java.util.HashMap; 44 | import java.util.UUID; 45 | 46 | 47 | public class ClientDetector extends JavaPlugin { 48 | public static Plugin plugin; 49 | public static ArrayList CLIENTS = new ArrayList(); 50 | public static ArrayList MODS = new ArrayList(); 51 | 52 | public static HashMap mcVersion = new HashMap(); 53 | public static HashMap forgeMods = new HashMap(); 54 | public static HashMap playerClient = new HashMap (); 55 | public static HashMap clientVersion = new HashMap (); 56 | public static HashMap> playerMods = new HashMap> (); 57 | public static HashMap> playerLabymodMods = new HashMap> (); 58 | public static HashMap> playerCommandsQueue = new HashMap>(); 59 | public static BungeeManager bungeeManager; 60 | 61 | @Override 62 | public void onLoad() { 63 | PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this)); 64 | PacketEvents.getAPI().getSettings() 65 | .checkForUpdates(false) 66 | .bStats(true) 67 | .debug(false); 68 | PacketEvents.getAPI().load(); 69 | } 70 | 71 | @Override 72 | public void onEnable() { 73 | plugin = this; 74 | 75 | new MetricsManager(this, 10745); 76 | 77 | Bukkit.getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', "&7[&3ClientDetector&7] (&aVersion&7) &aDetected Version &c" + PacketEvents.getAPI().getServerManager().getVersion().name())); 78 | Bukkit.getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', "&7[&3ClientDetector&7] (&aVersion&7) &aLoading settings for Version &c" + PacketEvents.getAPI().getServerManager().getVersion().name())); 79 | 80 | Bukkit.getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', "&7[&3ClientDetector&7] (&aProtocol&7) &aLoading protocols...")); 81 | PacketEvents.getAPI().getEventManager().registerListener(new NetworkListener()); 82 | PacketEvents.getAPI().init(); 83 | 84 | Bukkit.getMessenger().registerOutgoingPluginChannel(this, "clientdetector:sync"); 85 | Bukkit.getMessenger().registerOutgoingPluginChannel(this, "lunarclient:pm"); 86 | 87 | Bukkit.getMessenger().registerIncomingPluginChannel(this, "clientdetector:sync", new PluginMessageListener()); 88 | Bukkit.getMessenger().registerIncomingPluginChannel(this, "clientdetector:fix", new PluginMessageListener()); 89 | Bukkit.getMessenger().registerIncomingPluginChannel(this, "lunarclient:pm", new PluginMessageListener()); 90 | 91 | if(PacketEvents.getAPI().getServerManager().getVersion().isOlderThanOrEquals(ServerVersion.V_1_12_2)) 92 | Bukkit.getMessenger().registerIncomingPluginChannel(this, "CB-Client", new PluginMessageListener()); 93 | 94 | Bukkit.getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', "&7[&3ClientDetector&7] (&aConfig&7) &aLoading config(s)...")); 95 | saveDefaultConfig(); 96 | 97 | getCommand("clientdetector").setExecutor(new Command()); 98 | getCommand("client").setExecutor(new Command()); 99 | getCommand("forge").setExecutor(new Command()); 100 | getCommand("mods").setExecutor(new Command()); 101 | 102 | Bukkit.getPluginManager().registerEvents(new PlayerListener(), this); 103 | Bukkit.getPluginManager().registerEvents(new ClientControl(), this); 104 | 105 | if(ConfigManager.getConfig("config").getBoolean("hackdetector.chatexploit.enableChatExploit") || ConfigManager.getConfig("config").getBoolean("hackdetector.antifastmath.enableAntiFastMath")) 106 | Bukkit.getPluginManager().registerEvents(new HackDetector(), this); 107 | 108 | Bukkit.getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', "&7[&3ClientDetector&7] (&aDetection&7) &aLoading client detections...")); 109 | ClientManager.load(); 110 | Bukkit.getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', "&7[&3ClientDetector&7] (&aDetection&7) &aLoading mod detections...")); 111 | ModManager.load(); 112 | 113 | AlertsManager.load(); 114 | 115 | DiscordManager.load(); 116 | 117 | AntiFastMath.load(); 118 | 119 | if(ConfigManager.getConfig("config").getBoolean("bungee.enableBungeeClient")){ 120 | Bukkit.getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', "&7[&3ClientDetector&7] (&aDetection&7) &aLoading Bungee client...")); 121 | 122 | Bukkit.getMessenger().registerOutgoingPluginChannel(this, "cd:bungee"); 123 | Bukkit.getMessenger().registerIncomingPluginChannel(this, "cd:spigot", new PluginMessageListener()); 124 | 125 | bungeeManager = new BungeeManager(); 126 | } 127 | 128 | if(Bukkit.getServer().getPluginManager().isPluginEnabled("ViaVersion")){ 129 | Bukkit.getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', "&7[&3ClientDetector&7] (&aViaVersion&7) &aDetected ViaVersion " + Bukkit.getPluginManager().getPlugin("ViaVersion").getDescription().getVersion())); 130 | } 131 | 132 | if(Bukkit.getServer().getPluginManager().isPluginEnabled("ProtocolLib")){ 133 | Bukkit.getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', "&7[&3ClientDetector&7] (&aProtocolLib&7) &aDetected ProtocolLib " + Bukkit.getPluginManager().getPlugin("ProtocolLib").getDescription().getVersion())); 134 | } 135 | 136 | if(Bukkit.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI")){ 137 | Bukkit.getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', "&7[&3ClientDetector&7] (&aPlaceholderAPI&7) &aDetected PlaceholderAPI " + Bukkit.getPluginManager().getPlugin("PlaceholderAPI").getDescription().getVersion())); 138 | } 139 | 140 | if(Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null && getConfig().getBoolean("placeholder.enablePlaceholder")) 141 | new PlaceholderManager().register(); 142 | 143 | try { 144 | ConfigManager.loadConfig("message"); 145 | ConfigManager.loadConfig("clientcontrol"); 146 | 147 | if(PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_17)){ 148 | if(ConfigManager.optimizeConfig("config", "forge.simulateForgeHandshake", false)) 149 | Bukkit.getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', "&7[&3ClientDetector&7] &cIMPORTANT NOTIFICATION: &aForge modlist detection for 1.17 - 1.18.2 is currently marked as UNSTABLE and therefore will be automatically disabled!!")); 150 | } 151 | 152 | } catch (IOException e) { 153 | e.printStackTrace(); 154 | } 155 | 156 | Bukkit.getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', "&7[&3ClientDetector&7] &aStarted!")); 157 | 158 | } 159 | 160 | @Override 161 | public void onDisable() { 162 | PacketEvents.getAPI().terminate(); 163 | 164 | Bukkit.getMessenger().unregisterIncomingPluginChannel(plugin); 165 | Bukkit.getMessenger().unregisterOutgoingPluginChannel(plugin); 166 | 167 | ClientManager.unLoad(); 168 | ModManager.unLoad(); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/api/ClientDetectorAPI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.api; 20 | 21 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 22 | import de.sportkanone123.clientdetector.spigot.manager.GeyserManager; 23 | import org.bukkit.entity.Player; 24 | 25 | import java.util.ArrayList; 26 | import java.util.HashMap; 27 | import java.util.List; 28 | import java.util.Map; 29 | 30 | public class ClientDetectorAPI { 31 | public static String getPlayerClient(Player player){ 32 | if(ClientDetector.playerClient.get(player.getUniqueId()) != null) 33 | return ClientDetector.playerClient.get(player.getUniqueId()); 34 | return "Vanilla (Undetectable)"; 35 | } 36 | 37 | public static List getPlayerMods(Player player){ 38 | if(ClientDetector.playerMods.get(player.getUniqueId()) != null) 39 | return ClientDetector.playerMods.get(player.getUniqueId()); 40 | return new ArrayList(); 41 | } 42 | 43 | public static ArrayList getPlayerForgeMods(Player player){ 44 | if(ClientDetector.forgeMods.get(player.getUniqueId()) != null) 45 | return ClientDetector.forgeMods.get(player.getUniqueId()).getMods(); 46 | return new ArrayList(); 47 | } 48 | 49 | public static List getPlayerLabymodAddons(Player player){ 50 | if(ClientDetector.playerLabymodMods.get(player.getUniqueId()) != null) 51 | return ClientDetector.playerLabymodMods.get(player.getUniqueId()); 52 | return new ArrayList(); 53 | } 54 | 55 | public static Boolean isForgePlayer(Player player){ 56 | return ClientDetector.forgeMods != null && ClientDetector.forgeMods.get(player.getUniqueId()) != null && ClientDetector.forgeMods.get(player.getUniqueId()).getMods() != null && !ClientDetector.forgeMods.get(player.getUniqueId()).getMods().isEmpty(); 57 | } 58 | 59 | public static Boolean isBedrockPlayer(Player player){ 60 | return GeyserManager.isBedrockPlayer(player); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/api/events/ClientDetectedEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.api.events; 20 | 21 | import org.bukkit.entity.Player; 22 | import org.bukkit.event.Event; 23 | import org.bukkit.event.HandlerList; 24 | 25 | public class ClientDetectedEvent extends Event { 26 | private static final HandlerList handlers = new HandlerList(); 27 | private final Player player; 28 | private final String client; 29 | 30 | public ClientDetectedEvent(Player player, String client) { 31 | this.client = client; 32 | this.player = player; 33 | } 34 | 35 | public HandlerList getHandlers() { 36 | return handlers; 37 | } 38 | 39 | public Player getPlayer() { 40 | return player; 41 | } 42 | 43 | public String getClient() { 44 | return client; 45 | } 46 | 47 | public static HandlerList getHandlerList() { 48 | return handlers; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/api/events/ForgeModlistDetectedEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.api.events; 20 | 21 | import de.sportkanone123.clientdetector.spigot.forgemod.ModList; 22 | import org.bukkit.entity.Player; 23 | import org.bukkit.event.Event; 24 | import org.bukkit.event.HandlerList; 25 | 26 | public class ForgeModlistDetectedEvent extends Event { 27 | private static final HandlerList handlers = new HandlerList(); 28 | private final Player player; 29 | private final ModList modlist; 30 | 31 | public ForgeModlistDetectedEvent(Player player, ModList modlist) { 32 | this.modlist = modlist; 33 | this.player = player; 34 | } 35 | 36 | public HandlerList getHandlers() { 37 | return handlers; 38 | } 39 | 40 | public Player getPlayer() { 41 | return player; 42 | } 43 | 44 | public ModList getModlist() { 45 | return modlist; 46 | } 47 | 48 | public static HandlerList getHandlerList() { 49 | return handlers; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/api/events/ModDetectedEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.api.events; 20 | 21 | import org.bukkit.entity.Player; 22 | import org.bukkit.event.Event; 23 | import org.bukkit.event.HandlerList; 24 | 25 | public class ModDetectedEvent extends Event { 26 | private static final HandlerList handlers = new HandlerList(); 27 | private final Player player; 28 | private final String modName; 29 | 30 | public ModDetectedEvent(Player player, String modName) { 31 | this.modName = modName; 32 | this.player = player; 33 | } 34 | 35 | public HandlerList getHandlers() { 36 | return handlers; 37 | } 38 | 39 | public Player getPlayer() { 40 | return player; 41 | } 42 | 43 | public String getMod() { 44 | return modName; 45 | } 46 | 47 | public static HandlerList getHandlerList() { 48 | return handlers; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/bungee/BungeeManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.bungee; 20 | 21 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 22 | import de.sportkanone123.clientdetector.spigot.forgemod.ModList; 23 | import de.sportkanone123.clientdetector.spigot.manager.AlertsManager; 24 | import de.sportkanone123.clientdetector.spigot.manager.ConfigManager; 25 | import org.bukkit.Bukkit; 26 | import org.bukkit.entity.Player; 27 | import java.nio.charset.StandardCharsets; 28 | import java.util.ArrayList; 29 | import java.util.UUID; 30 | 31 | public class BungeeManager { 32 | public String placeholder = "@@"; 33 | 34 | private void sync(String string, Player player){ 35 | player.sendPluginMessage(ClientDetector.plugin, "cd:bungee", string.getBytes(StandardCharsets.UTF_8)); 36 | } 37 | 38 | private void sync(String string){ 39 | if(Bukkit.getOnlinePlayers().iterator().hasNext()){ 40 | Bukkit.getOnlinePlayers().iterator().next().sendPluginMessage(ClientDetector.plugin, "cd:bungee", string.getBytes(StandardCharsets.UTF_8)); 41 | } 42 | } 43 | 44 | public void syncList(DataType type, Player player, ArrayList list){ 45 | String str = ConfigManager.getConfig("config").getString("bungee.serverName") + placeholder + type.toString() + placeholder + player.getUniqueId(); 46 | 47 | for(int i = 0; i < list.size(); i++) 48 | str = str + placeholder + list.get(i); 49 | 50 | sync(str, player); 51 | } 52 | public void syncList(DataType type, Player player, String client){ 53 | String str = ConfigManager.getConfig("config").getString("bungee.serverName") + placeholder + type.toString() + placeholder + player.getUniqueId() + placeholder + client; 54 | 55 | sync(str, player); 56 | } 57 | 58 | public void syncList(DataType type, String message){ 59 | String str = ConfigManager.getConfig("config").getString("bungee.serverName") + placeholder + type.toString() + placeholder + ConfigManager.getConfig("config").getString("bungee.serverName") + placeholder + message; 60 | 61 | sync(str); 62 | } 63 | 64 | public void handleSyncMessage(String string){ 65 | String[] strings = string.split(placeholder); 66 | 67 | if(strings[1].equalsIgnoreCase("CLIENT_LIST") && strings.length == 4) { 68 | ClientDetector.playerClient.put(UUID.fromString(strings[2]), strings[3]); 69 | 70 | }else if(strings[1].equalsIgnoreCase("MOD_LIST") && strings.length >= 4) { 71 | ArrayList list = new ArrayList<>(); 72 | 73 | for(int i = 3; i < strings.length; i++) 74 | list.add(strings[i]); 75 | 76 | ClientDetector.playerMods.put(UUID.fromString(strings[2]), list); 77 | 78 | }else if(strings[1].equalsIgnoreCase("FORGE_MOD_LIST") && strings.length >= 4) { 79 | ArrayList list = new ArrayList<>(); 80 | 81 | for(int i = 3; i < strings.length; i++) 82 | list.add(strings[i]); 83 | 84 | ClientDetector.forgeMods.put(UUID.fromString(strings[2]), new ModList(list)); 85 | 86 | }else if(strings[1].equalsIgnoreCase("CROSS_SERVER_MESSAGE") && strings.length == 4) { 87 | String message = strings[2]; 88 | String server = strings[3]; 89 | 90 | AlertsManager.handleCrossServer(server, message); 91 | 92 | }else if(strings[0].equalsIgnoreCase("PLAYER_LEFT") && strings.length == 2) { 93 | UUID uuid; 94 | 95 | if(Bukkit.getPlayer(strings[1]) != null){ 96 | uuid = Bukkit.getPlayer(strings[1]).getUniqueId(); 97 | }else 98 | uuid = Bukkit.getOfflinePlayer(strings[1]).getUniqueId(); 99 | 100 | 101 | ClientDetector.playerClient.remove(uuid); 102 | ClientDetector.playerMods.remove(uuid); 103 | ClientDetector.playerLabymodMods.remove(uuid); 104 | ClientDetector.forgeMods.remove(uuid); 105 | ClientDetector.mcVersion.remove(uuid); 106 | ClientDetector.clientVersion.remove(uuid); 107 | AlertsManager.firstDetection.remove(uuid); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/bungee/DataType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.bungee; 20 | 21 | public enum DataType { 22 | CLIENT_LIST, 23 | MOD_LIST, 24 | FORGE_MOD_LIST, 25 | CROSS_SERVER_MESSAGE, 26 | PLAYER_LEFT; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/client/Client.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.client; 20 | 21 | import com.github.retrooper.packetevents.PacketEvents; 22 | import com.github.retrooper.packetevents.manager.server.ServerVersion; 23 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 24 | import de.sportkanone123.clientdetector.spigot.listener.PluginMessageListener; 25 | import org.bukkit.Bukkit; 26 | 27 | import java.nio.charset.StandardCharsets; 28 | import java.util.Arrays; 29 | import java.util.List; 30 | 31 | public class Client { 32 | private List channel; 33 | private List data; 34 | private String clientName; 35 | private Boolean onlyChannel; 36 | private Boolean hasVersion; 37 | private String splitCharacter; 38 | private Integer versionIndex; 39 | 40 | public Client(List channel, String data, String clientName, Boolean onlyChannel, Boolean hasVersion, String splitCharacter, Integer versionIndex){ 41 | this.channel = channel; 42 | this.data = Arrays.asList(data); 43 | this.clientName = clientName; 44 | this.onlyChannel = onlyChannel; 45 | this.hasVersion = hasVersion; 46 | this.splitCharacter = splitCharacter; 47 | this.versionIndex = versionIndex; 48 | } 49 | 50 | public Client(String channel, String data, String clientName, Boolean onlyChannel, Boolean hasVersion, String splitCharacter, Integer versionIndex){ 51 | this.channel = Arrays.asList(channel); 52 | this.data = Arrays.asList(data); 53 | this.clientName = clientName; 54 | this.onlyChannel = onlyChannel; 55 | this.hasVersion = hasVersion; 56 | this.splitCharacter = splitCharacter; 57 | this.versionIndex = versionIndex; 58 | } 59 | 60 | public Client(List channel, List data, String clientName, Boolean onlyChannel, Boolean hasVersion, String splitCharacter, Integer versionIndex){ 61 | this.channel = channel; 62 | this.data = data; 63 | this.clientName = clientName; 64 | this.onlyChannel = onlyChannel; 65 | this.hasVersion = hasVersion; 66 | this.splitCharacter = splitCharacter; 67 | this.versionIndex = versionIndex; 68 | } 69 | 70 | public Client(String channel, List data, String clientName, Boolean onlyChannel, Boolean hasVersion, String splitCharacter, Integer versionIndex){ 71 | this.channel = Arrays.asList(channel); 72 | this.data = data; 73 | this.clientName = clientName; 74 | this.onlyChannel = onlyChannel; 75 | this.hasVersion = hasVersion; 76 | this.splitCharacter = splitCharacter; 77 | this.versionIndex = versionIndex; 78 | } 79 | 80 | public List getChannel() { return channel; } 81 | 82 | public void setChannel(List channel) { this.channel = channel; } 83 | 84 | public List getData() { return data; } 85 | 86 | public void setData(List data) { this.data = data; } 87 | 88 | public String getClientName() { return clientName; } 89 | 90 | public void setClientName(String clientName) { this.clientName = clientName; } 91 | 92 | public Boolean getOnlyChannel() { return onlyChannel; } 93 | 94 | public void setOnlyChannel(Boolean onlyChannel) { this.onlyChannel = onlyChannel; } 95 | 96 | public Boolean getHasVersion() { return hasVersion; } 97 | 98 | public void setHasVersion(Boolean hasVersion) { this.hasVersion = hasVersion; } 99 | 100 | public String getSplitCharacter() { return splitCharacter; } 101 | 102 | public void setSplitCharacter(String splitCharacter) { this.splitCharacter = splitCharacter; } 103 | 104 | public Integer getVersionIndex() { return versionIndex; } 105 | 106 | public void setVersionIndex(Integer versionIndex) { this.versionIndex = versionIndex; } 107 | 108 | public Boolean isClient(String channel, byte[] data){ 109 | if(this.onlyChannel) { 110 | for (String ch : this.channel) { 111 | if (channel.equalsIgnoreCase(ch)) return true; 112 | } 113 | return false; 114 | }else { 115 | for (String ch : this.channel) { 116 | for(String dat : this.data){ 117 | if (channel.equalsIgnoreCase(ch) && new String(data, StandardCharsets.UTF_8).contains(dat)) return true; 118 | } 119 | } 120 | return false; 121 | } 122 | } 123 | 124 | public String getClientName(String channel, byte[] data){ 125 | if(isClient(channel, data)) 126 | return this.clientName; 127 | else 128 | return null; 129 | } 130 | 131 | public String getVersion(String channel, byte[] data){ 132 | if(isClient(channel, data)) { 133 | String dataString = new String(data, StandardCharsets.UTF_8); 134 | return dataString.split(this.splitCharacter)[this.versionIndex]; 135 | }else { 136 | return null; 137 | } 138 | } 139 | 140 | public void load(){ 141 | for(String str : this.channel){ 142 | if(PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_13)){ 143 | if(str.contains(":")){ 144 | Bukkit.getMessenger().registerIncomingPluginChannel(ClientDetector.plugin, str, new PluginMessageListener()); 145 | } 146 | }else{ 147 | Bukkit.getMessenger().registerIncomingPluginChannel(ClientDetector.plugin, str, new PluginMessageListener()); 148 | } 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/client/processor/PacketProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.client.processor; 20 | 21 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 22 | import de.sportkanone123.clientdetector.spigot.client.Client; 23 | import de.sportkanone123.clientdetector.spigot.manager.AlertsManager; 24 | import org.bukkit.entity.Player; 25 | 26 | import java.nio.charset.StandardCharsets; 27 | 28 | public class PacketProcessor { 29 | public static void handlePacket(Player player, String channel, byte[] data){ 30 | byte[] customData = new String(data, StandardCharsets.UTF_8).replace("(Velocity)", "").getBytes(StandardCharsets.UTF_8); 31 | 32 | for(Client client : ClientDetector.CLIENTS){ 33 | if(client.isClient(channel, customData) && ClientDetector.plugin.getConfig().getBoolean("client.enableClientDetection")){ 34 | if(client.getClientName() == "Vanilla (Undetectable)"){ 35 | if(ClientDetector.playerClient.get(player.getUniqueId()) == null){ 36 | ClientDetector.playerClient.put(player.getUniqueId(), client.getClientName()); 37 | 38 | if(ClientDetector.mcVersion.get(player.getUniqueId()) != null && client.getClientName() != null) 39 | ClientDetector.clientVersion.put(player.getUniqueId(), ClientDetector.mcVersion.get(player.getUniqueId())); 40 | 41 | AlertsManager.handleClientDetection(player); 42 | 43 | } 44 | }else{ 45 | if(ClientDetector.playerClient.get(player.getUniqueId()) == null || ClientDetector.playerClient.get(player.getUniqueId()) == "Vanilla (Undetectable)" || ClientDetector.playerClient.get(player) == "Unknown Client (Not Vanilla Minecraft)"){ 46 | ClientDetector.playerClient.put(player.getUniqueId(), client.getClientName()); 47 | 48 | if(client.getHasVersion() && client.getVersion(channel, customData) != null && ClientDetector.plugin.getConfig().getBoolean("client.enableVersionDetection")) 49 | ClientDetector.clientVersion.put(player.getUniqueId(), client.getVersion(channel, customData)); 50 | else 51 | ClientDetector.clientVersion.put(player.getUniqueId(), null); 52 | 53 | AlertsManager.handleClientDetection(player); 54 | 55 | } 56 | } 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/client/processor/PluginMessageProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.client.processor; 20 | 21 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 22 | import de.sportkanone123.clientdetector.spigot.client.Client; 23 | import de.sportkanone123.clientdetector.spigot.manager.AlertsManager; 24 | import de.sportkanone123.clientdetector.spigot.manager.ConfigManager; 25 | import org.bukkit.entity.Player; 26 | 27 | import java.nio.charset.StandardCharsets; 28 | 29 | public class PluginMessageProcessor { 30 | public static void handlePluginMessage(Player player, String channel, byte[] data) { 31 | if(new String(data, StandardCharsets.UTF_8).contains("(Velocity)")) 32 | ConfigManager.optimizeConfig("config", "velocity.enableVelocitySupport", true); 33 | 34 | byte[] customData = new String(data, StandardCharsets.UTF_8).replace("(Velocity)", "").getBytes(StandardCharsets.UTF_8); 35 | 36 | for (Client client : ClientDetector.CLIENTS) { 37 | if (client.isClient(channel, customData) && ClientDetector.plugin.getConfig().getBoolean("client.enableClientDetection")) { 38 | if (client.getClientName() == "Vanilla (Undetectable)") { 39 | if (ClientDetector.playerClient.get(player.getUniqueId()) == null) { 40 | ClientDetector.playerClient.put(player.getUniqueId(), client.getClientName()); 41 | 42 | if (ClientDetector.mcVersion.get(player.getUniqueId()) != null && client.getClientName() != null) 43 | ClientDetector.clientVersion.put(player.getUniqueId(), ClientDetector.mcVersion.get(player.getUniqueId())); 44 | 45 | AlertsManager.handleClientDetection(player); 46 | 47 | } 48 | } else { 49 | if (ClientDetector.playerClient.get(player.getUniqueId()) == null || ClientDetector.playerClient.get(player.getUniqueId()) == "Vanilla (Undetectable)" || ClientDetector.playerClient.get(player.getUniqueId()) == "Unknown Client (Not Vanilla Minecraft)") { 50 | ClientDetector.playerClient.put(player.getUniqueId(), client.getClientName()); 51 | 52 | if (client.getHasVersion() && client.getVersion(channel, customData) != null && ClientDetector.plugin.getConfig().getBoolean("client.enableVersionDetection")) 53 | ClientDetector.clientVersion.put(player.getUniqueId(), client.getVersion(channel, customData)); 54 | else 55 | ClientDetector.clientVersion.put(player.getUniqueId(), null); 56 | 57 | AlertsManager.handleClientDetection(player); 58 | 59 | } 60 | } 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/clientcontrol/ClientControl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.clientcontrol; 20 | 21 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 22 | import de.sportkanone123.clientdetector.spigot.clientcontrol.impl.*; 23 | import org.bukkit.Bukkit; 24 | import org.bukkit.entity.Player; 25 | import org.bukkit.event.EventHandler; 26 | import org.bukkit.event.Listener; 27 | import org.bukkit.event.player.PlayerJoinEvent; 28 | import org.bukkit.event.player.PlayerRegisterChannelEvent; 29 | 30 | public class ClientControl implements Listener { 31 | 32 | @EventHandler() 33 | public void onJoin(PlayerJoinEvent event){ 34 | Badlion.handle(event.getPlayer()); 35 | FiveZig.handle(event.getPlayer()); 36 | LabyMod.hande(event.getPlayer()); 37 | 38 | } 39 | 40 | @EventHandler 41 | public void onRegister(final PlayerRegisterChannelEvent event) { 42 | if (!event.getChannel().equalsIgnoreCase("lunarclient:pm")) { 43 | return; 44 | } 45 | LunarClient.handle(event.getPlayer()); 46 | } 47 | 48 | public static void handlePacket(Player player, String channel, byte[] data){ 49 | if(channel.equalsIgnoreCase("wdl:control") || channel.equalsIgnoreCase("WDL|INIT") || (channel.equalsIgnoreCase("REGISTER") && new String(data).contains("WDL|INIT"))) 50 | WorldDownloader.handle(player); 51 | 52 | if(channel.equalsIgnoreCase("bsm:settings")) 53 | BetterSprinting.handle(player); 54 | 55 | if(channel.equalsIgnoreCase("LABYMOD") || channel.equalsIgnoreCase("labymod3:main")){ 56 | LabyMod.handlePacket(player, data); 57 | } 58 | } 59 | 60 | public static void handlePluginMessage(Player player, String channel, byte[] data){ 61 | if(channel.equalsIgnoreCase("wdl:control") || channel.equalsIgnoreCase("WDL|INIT") || (channel.equalsIgnoreCase("REGISTER") && new String(data).contains("WDL|INIT"))) 62 | WorldDownloader.handle(player); 63 | 64 | if(channel.equalsIgnoreCase("bsm:settings")) 65 | BetterSprinting.handle(player); 66 | 67 | if(channel.equalsIgnoreCase("LABYMOD") || channel.equalsIgnoreCase("labymod3:main")){ 68 | LabyMod.handlePluginMessage(player, data); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/clientcontrol/impl/Badlion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.clientcontrol.impl; 20 | 21 | import com.github.retrooper.packetevents.PacketEvents; 22 | import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPluginMessage; 23 | import com.google.gson.Gson; 24 | import com.google.gson.GsonBuilder; 25 | import com.google.gson.JsonObject; 26 | import de.sportkanone123.clientdetector.spigot.manager.ConfigManager; 27 | import org.bukkit.configuration.MemorySection; 28 | import org.bukkit.entity.Player; 29 | 30 | import java.util.HashMap; 31 | import java.util.Map; 32 | 33 | /* 34 | More information can be found here: https://github.com/LunarClient/BukkitAPI 35 | */ 36 | public class Badlion { 37 | private static final Map modsDisallowed = new HashMap(); 38 | 39 | public static void handle(Player player){ 40 | Gson GSON = new GsonBuilder().enableComplexMapKeySerialization().disableHtmlEscaping().create(); 41 | 42 | /* 43 | · Animations 44 | · ArmorStatus 45 | · AutoFriend 46 | · AutoGG 47 | · AutoText 48 | · AutoTip 49 | · Block Overlay 50 | · BlockInfo 51 | · BossBar 52 | · Chat 53 | · Chunk Borders 54 | · Clear Glass 55 | · ClearWater 56 | · Clock 57 | · Combo Counter 58 | · Coordinates 59 | · CPS 60 | · Crosshair 61 | · Custom Fonts 62 | · Direction 63 | · EnchantGlint 64 | · FOV Changer 65 | · FPS 66 | · Fullbright 67 | · Hit Color 68 | · Hitboxes 69 | · InventoryBlur 70 | · Item Counter 71 | · Item Info 72 | · Item Physics 73 | · Item Tracker 74 | · JustEnoughItems 75 | · Keystrokes 76 | · LevelHead 77 | · Light Overlay 78 | · Memory 79 | · MiniMap 80 | · MLG Cobweb 81 | · MotionBlur 82 | · MumbleLink 83 | · Music 84 | · Name History 85 | · NickHider 86 | · NotEnoughUpdates 87 | · Notifications 88 | · Pack Display 89 | · Pack Tweaks 90 | · Particles 91 | · Perspective 92 | · Ping 93 | · Player Counter 94 | · PotionStatus 95 | · Protection 96 | · Quickplay 97 | · Reach Display 98 | · Replay 99 | · Saturation 100 | · Schematica 101 | · Scoreboard 102 | · Server Address 103 | · Shinypots 104 | · SkyblockAddons 105 | · Stopwatch 106 | · TcpNoDelay 107 | · TeamSpeak 108 | · TimeChanger 109 | · Timers 110 | · ToggleChat 111 | · ToggleSneak 112 | · ToggleSprint 113 | · Waypoints 114 | · WeatherChanger 115 | · World Edit CUI 116 | · Zoom 117 | */ 118 | 119 | for(String string : ((MemorySection) ConfigManager.getConfig("clientcontrol").get("badlion_disable")).getKeys(false)){ 120 | if(string.equalsIgnoreCase("ToggleSprint")){ 121 | if(ConfigManager.getConfig("clientcontrol").getBoolean("badlion_disable." + string + ".disableAll")) { 122 | modsDisallowed.put(string, new DisallowedMods(true, null, null)); 123 | }else if(ConfigManager.getConfig("clientcontrol").getBoolean("badlion_disable." + string + ".FlySpeed")){ 124 | JsonObject object = new JsonObject(); 125 | JsonObject object2 = new JsonObject(); 126 | object2.addProperty("disabled", true); 127 | object.add("flySpeed", object2); 128 | modsDisallowed.put(string, new DisallowedMods(false, object, null)); 129 | } 130 | } 131 | 132 | if(string.equalsIgnoreCase("ToggleSneak")){ 133 | if(ConfigManager.getConfig("clientcontrol").getBoolean("badlion_disable." + string + ".disableAll")) { 134 | modsDisallowed.put(string, new DisallowedMods(true, null, null)); 135 | }else if(ConfigManager.getConfig("clientcontrol").getBoolean("badlion_disable." + string + ".InventorySneak")){ 136 | JsonObject object = new JsonObject(); 137 | JsonObject object2 = new JsonObject(); 138 | object2.addProperty("disabled", true); 139 | object.add("inventorySneak", object2); 140 | modsDisallowed.put(string, new DisallowedMods(false, object, null)); 141 | } 142 | } 143 | 144 | if(ConfigManager.getConfig("clientcontrol").getBoolean("badlion_disable." + string)) 145 | modsDisallowed.put(string, new DisallowedMods(true, null, null)); 146 | } 147 | 148 | 149 | WrapperPlayServerPluginMessage costumPayload = new WrapperPlayServerPluginMessage("badlion:mods", GSON.toJson(modsDisallowed).getBytes()); 150 | PacketEvents.getAPI().getPlayerManager().sendPacket(player, costumPayload); 151 | } 152 | 153 | private static class DisallowedMods { 154 | private final boolean disabled; 155 | private final JsonObject extra_data; 156 | private final JsonObject settings; 157 | 158 | public DisallowedMods(boolean disabled, JsonObject extra_data, JsonObject settings){ 159 | this.disabled = disabled; 160 | this.extra_data = extra_data; 161 | this.settings = settings; 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/clientcontrol/impl/BetterSprinting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.clientcontrol.impl; 20 | 21 | import com.github.retrooper.packetevents.PacketEvents; 22 | import com.github.retrooper.packetevents.manager.server.ServerVersion; 23 | import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPluginMessage; 24 | import de.sportkanone123.clientdetector.spigot.manager.ConfigManager; 25 | import org.bukkit.entity.Player; 26 | 27 | import java.io.ByteArrayOutputStream; 28 | import java.io.DataOutputStream; 29 | import java.io.IOException; 30 | 31 | /* 32 | More information can be found here: https://github.com/chylex/Better-Sprinting 33 | */ 34 | public class BetterSprinting { 35 | 36 | public static void handle(Player player){ 37 | ByteArrayOutputStream msgbytes = new ByteArrayOutputStream(); 38 | DataOutputStream msgout = new DataOutputStream(msgbytes); 39 | 40 | if(ConfigManager.getConfig("clientcontrol").getBoolean("bettersprinting.disableAll")){ 41 | try { 42 | msgout.writeByte(1); 43 | } catch (IOException exception){ 44 | 45 | } 46 | }else{ 47 | try { 48 | msgout.writeByte(0); 49 | msgout.writeBoolean(!ConfigManager.getConfig("clientcontrol").getBoolean("bettersprinting.disableSurvivalFlyBoost")); 50 | msgout.writeBoolean(!ConfigManager.getConfig("clientcontrol").getBoolean("bettersprinting.disableAllDirs")); 51 | } catch (IOException exception){ 52 | 53 | } 54 | } 55 | 56 | 57 | 58 | 59 | WrapperPlayServerPluginMessage costumPayload; 60 | if(PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_13)) 61 | costumPayload = new WrapperPlayServerPluginMessage("bsm:settings", msgbytes.toByteArray()); 62 | else 63 | costumPayload = new WrapperPlayServerPluginMessage("BSM", msgbytes.toByteArray()); 64 | 65 | PacketEvents.getAPI().getPlayerManager().sendPacket(player, costumPayload); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/clientcontrol/impl/FiveZig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.clientcontrol.impl; 20 | 21 | import com.github.retrooper.packetevents.PacketEvents; 22 | import com.github.retrooper.packetevents.manager.server.ServerVersion; 23 | import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPluginMessage; 24 | import de.sportkanone123.clientdetector.spigot.manager.ConfigManager; 25 | import org.bukkit.entity.Player; 26 | 27 | import java.util.BitSet; 28 | 29 | public class FiveZig { 30 | public static void handle(Player player){ 31 | boolean[] features = new boolean[6]; 32 | 33 | features[0] = ConfigManager.getConfig("clientcontrol").getBoolean("fivezig.disablePotionEffectHud"); 34 | features[1] = ConfigManager.getConfig("clientcontrol").getBoolean("fivezig.disablePotionIndicatorVignette"); 35 | features[2] = ConfigManager.getConfig("clientcontrol").getBoolean("fivezig.disableArmourHud"); 36 | features[3] = ConfigManager.getConfig("clientcontrol").getBoolean("fivezig.disablePlayerSaturation"); 37 | features[4] = ConfigManager.getConfig("clientcontrol").getBoolean("fivezig.disableEntityHealthIndicator"); 38 | features[5] = ConfigManager.getConfig("clientcontrol").getBoolean("fivezig.disableAutoReconnect"); 39 | 40 | final BitSet disableBitSet = new BitSet(); 41 | 42 | // Set the according bits 43 | for (int i = 0; i < features.length; ++i) { 44 | disableBitSet.set(i, features[i]); 45 | } 46 | 47 | WrapperPlayServerPluginMessage costumPayload; 48 | 49 | if(PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_13)){ 50 | costumPayload = new WrapperPlayServerPluginMessage("the5zigmod:5zig_set", disableBitSet.toByteArray()); 51 | PacketEvents.getAPI().getPlayerManager().sendPacket(player, costumPayload); 52 | 53 | costumPayload = new WrapperPlayServerPluginMessage("l:5zig_set", disableBitSet.toByteArray()); 54 | PacketEvents.getAPI().getPlayerManager().sendPacket(player, costumPayload); 55 | }else{ 56 | costumPayload = new WrapperPlayServerPluginMessage("5zig_Set", disableBitSet.toByteArray()); 57 | PacketEvents.getAPI().getPlayerManager().sendPacket(player, costumPayload); 58 | } 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/clientcontrol/impl/WorldDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.clientcontrol.impl; 20 | 21 | import com.github.retrooper.packetevents.PacketEvents; 22 | import com.github.retrooper.packetevents.manager.server.ServerVersion; 23 | import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPluginMessage; 24 | import de.sportkanone123.clientdetector.spigot.manager.ConfigManager; 25 | import org.bukkit.entity.Player; 26 | 27 | import java.io.ByteArrayOutputStream; 28 | import java.io.DataOutputStream; 29 | import java.io.IOException; 30 | 31 | /* 32 | More information can be found here: https://github.com/Pokechu22/WorldDownloader-Serverside-Companion 33 | */ 34 | public class WorldDownloader { 35 | public static void handle(Player player){ 36 | ByteArrayOutputStream msgbytes = new ByteArrayOutputStream(); 37 | DataOutputStream msgout = new DataOutputStream(msgbytes); 38 | 39 | try { 40 | msgout.writeInt(0); 41 | msgout.writeBoolean(!ConfigManager.getConfig("clientcontrol").getBoolean("worlddownloader.disableAll")); 42 | } catch (IOException exception){ 43 | 44 | } 45 | 46 | WrapperPlayServerPluginMessage costumPayload; 47 | 48 | if(PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_13)){ 49 | costumPayload = new WrapperPlayServerPluginMessage("wdl:control", msgbytes.toByteArray()); 50 | PacketEvents.getAPI().getPlayerManager().sendPacket(player, costumPayload); 51 | }else{ 52 | costumPayload = new WrapperPlayServerPluginMessage("WDL|CONTROL", msgbytes.toByteArray()); 53 | PacketEvents.getAPI().getPlayerManager().sendPacket(player, costumPayload); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/command/Command.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.command; 20 | 21 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 22 | import de.sportkanone123.clientdetector.spigot.command.impl.*; 23 | import de.sportkanone123.clientdetector.spigot.manager.ConfigManager; 24 | import org.bukkit.Bukkit; 25 | import org.bukkit.ChatColor; 26 | import org.bukkit.command.CommandExecutor; 27 | import org.bukkit.command.CommandSender; 28 | 29 | public class Command implements CommandExecutor { 30 | 31 | @Override 32 | public boolean onCommand(CommandSender sender, org.bukkit.command.Command command, String label, String[] args) { 33 | if(command.getName().equalsIgnoreCase("clientdetector")){ 34 | if(sender instanceof org.bukkit.entity.Player){ 35 | if(!sender.hasPermission("clientdetector.command")){ 36 | String prefix = ConfigManager.getConfig("message").getString("prefix"); 37 | 38 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7&m-------&7" + prefix + "&7&m-------&7")); 39 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("message").getString("prefix") + " &7ClientDetector(" + Bukkit.getServer().getPluginManager().getPlugin("ClientDetector").getDescription().getVersion() + ") by Sportkanone123")); 40 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7&m-------&7" + prefix + "&7&m-------&7")); 41 | 42 | return false; 43 | } 44 | } 45 | 46 | if(args.length == 0){ 47 | String prefix = ConfigManager.getConfig("message").getString("prefix"); 48 | 49 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7&m-------&7" + prefix + "&7&m-------&7")); 50 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("message").getString("prefix") + " &7ClientDetector(" + Bukkit.getServer().getPluginManager().getPlugin("ClientDetector").getDescription().getVersion() + ") by Sportkanone123")); 51 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7&m-------&7" + prefix + "&7&m-------&7")); 52 | }else{ 53 | if(args[0].equalsIgnoreCase("help")) { 54 | Help.handle(sender, command, label, args); 55 | }else if(args[0].equalsIgnoreCase("player")){ 56 | Player.handle(sender, command, label, args); 57 | }else if(args[0].equalsIgnoreCase("forge")){ 58 | Forge.handle(sender, command, label, args); 59 | } 60 | } 61 | }else if(command.getName().equalsIgnoreCase("client")){ 62 | if(sender instanceof org.bukkit.entity.Player) 63 | if(!sender.hasPermission("clientdetector.command")) 64 | return false; 65 | 66 | if(args.length == 1){ 67 | String[] args_custom = new String[]{"player", "client", args[0]}; 68 | Player.handle(sender, command, label, args_custom); 69 | }else{ 70 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("message").getString("prefix") + " &cPlease use: /client ")); 71 | } 72 | }else if(command.getName().equalsIgnoreCase("forge")){ 73 | if(sender instanceof org.bukkit.entity.Player) 74 | if(!sender.hasPermission("clientdetector.command")) 75 | return false; 76 | 77 | if(args.length == 1){ 78 | String[] args_custom = new String[]{"forge", args[0]}; 79 | Forge.handle(sender, command, label, args_custom); 80 | }else{ 81 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("message").getString("prefix") + " &cPlease use: /forge ")); 82 | } 83 | 84 | }else if(command.getName().equalsIgnoreCase("mods")){ 85 | if(sender instanceof org.bukkit.entity.Player) 86 | if(!sender.hasPermission("clientdetector.command")) 87 | return false; 88 | 89 | if(args.length == 1){ 90 | String[] args_custom = new String[]{"player", "mods", args[0]}; 91 | Player.handle(sender, command, label, args_custom); 92 | }else{ 93 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("message").getString("prefix") + " &cPlease use: /mods ")); 94 | } 95 | } 96 | 97 | return false; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/command/impl/ClientDisabler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.command.impl; 20 | 21 | import org.bukkit.Bukkit; 22 | import org.bukkit.command.Command; 23 | import org.bukkit.command.CommandSender; 24 | 25 | public class ClientDisabler { 26 | /*public static boolean handle(CommandSender sender, Command command, String label, String[] args) { 27 | if(args.length == 3 && Bukkit.getPlayer(args[1]) != null){ 28 | if(args[2].equalsIgnoreCase("aristois")){ 29 | de.sportkanone123.clientdetector.spigot.clientdisabler.ClientDisabler.checkAristois(sender, Bukkit.getPlayer(args[1])); 30 | } 31 | }else if(args.length != 3){ 32 | 33 | } 34 | 35 | return false; 36 | }*/ 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/command/impl/Forge.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.command.impl; 20 | 21 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 22 | import de.sportkanone123.clientdetector.spigot.manager.ConfigManager; 23 | import org.bukkit.Bukkit; 24 | import org.bukkit.ChatColor; 25 | import org.bukkit.command.Command; 26 | import org.bukkit.command.CommandSender; 27 | 28 | import java.util.ArrayList; 29 | 30 | public class Forge { 31 | public static boolean handle(CommandSender sender, Command command, String label, String[] args) { 32 | if(args.length == 2){ 33 | if(Bukkit.getPlayer(args[1]) != null){ 34 | org.bukkit.entity.Player target = Bukkit.getPlayer(args[1]); 35 | 36 | if(ClientDetector.playerClient.get(target.getUniqueId()) != null && ClientDetector.playerClient.get(target.getUniqueId()).equalsIgnoreCase("Forge")){ 37 | if(ClientDetector.forgeMods != null && ClientDetector.forgeMods.get(target.getUniqueId()) != null && ClientDetector.forgeMods.get(target.getUniqueId()).getMods() != null && ClientDetector.forgeMods.get(target.getUniqueId()).getMods().size() != 0){ 38 | ArrayList message = (ArrayList) ConfigManager.getConfig("message").get("forge.usingforgemodlist"); 39 | 40 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', message.get(0).replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%player_name%", target.getName()))); 41 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', message.get(1).replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%player_name%", target.getName()))); 42 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', message.get(2).replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%player_name%", target.getName()))); 43 | 44 | for(String mod : ClientDetector.forgeMods.get(target.getUniqueId()).getMods()){ 45 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', message.get(3).replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%mod_name%", mod))); 46 | } 47 | 48 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', message.get(4).replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%player_name%", target.getName()))); 49 | }else{ 50 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("message").getString("forge.usingforgebutnomodlistreceived").replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%player_name%", args[1]))); 51 | } 52 | }else { 53 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("message").getString("forge.notusingforge").replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%player_name%", args[1]))); 54 | } 55 | }else{ 56 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("message").getString("error.playernotfound").replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%player_name%", args[1]))); 57 | } 58 | }else{ 59 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("message").getString("prefix") + " &cPlease use: /cd forge ")); 60 | } 61 | return false; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/command/impl/GUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.command.impl; 20 | 21 | import org.bukkit.command.Command; 22 | import org.bukkit.command.CommandSender; 23 | import org.bukkit.entity.Player; 24 | 25 | public class GUI { 26 | public static boolean handle(CommandSender sender, Command command, String label, String[] args) { 27 | Player p = (Player) sender; 28 | 29 | return false; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/command/impl/Help.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.command.impl; 20 | 21 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 22 | import de.sportkanone123.clientdetector.spigot.manager.ConfigManager; 23 | import org.bukkit.Bukkit; 24 | import org.bukkit.ChatColor; 25 | import org.bukkit.command.Command; 26 | import org.bukkit.command.CommandSender; 27 | import org.bukkit.entity.Player; 28 | 29 | public class Help { 30 | 31 | public static boolean handle(CommandSender sender, Command command, String label, String[] args) { 32 | if(sender instanceof Player){ 33 | Player p = (Player) sender; 34 | String prefix = ConfigManager.getConfig("message").getString("prefix"); 35 | p.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7&l-------&7" + prefix + "&7&7&l-------&7")); 36 | send_raw(p, " ┌──────────┐", "cd help"); 37 | send_raw(p, " │ Help │", "cd help"); 38 | send_raw(p, " └──────────┘", "cd help"); 39 | send_raw(p, " ┌──────────┐", "cd player"); 40 | send_raw(p, " │ Player │", "cd player"); 41 | send_raw(p, " └──────────┘", "cd player"); 42 | send_raw(p, " ┌──────────┐", "cd forge"); 43 | send_raw(p, " │ Forge │", "cd forge"); 44 | send_raw(p, " └──────────┘", "cd forge"); 45 | p.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7&l-------&7" + prefix + "&7&7&l-------&7")); 46 | }else{ 47 | sender.sendMessage("cd help -> Get help about the plugin."); 48 | sender.sendMessage("cd player -> Get information about a player."); 49 | sender.sendMessage("cd forge -> Get the Forge Modlist of a player."); 50 | } 51 | 52 | 53 | return false; 54 | } 55 | 56 | public static void send_raw(Player player, String text, String command){ 57 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + player.getName() + " {\"text\":\"" + text + "\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/" + command + "\"}}]"); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/command/impl/Player.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.command.impl; 20 | 21 | import com.github.retrooper.packetevents.PacketEvents; 22 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 23 | import de.sportkanone123.clientdetector.spigot.manager.ConfigManager; 24 | import org.bukkit.Bukkit; 25 | import org.bukkit.ChatColor; 26 | import org.bukkit.command.Command; 27 | import org.bukkit.command.CommandSender; 28 | 29 | import java.util.ArrayList; 30 | 31 | public class Player { 32 | public static boolean handle(CommandSender sender, Command command, String label, String[] args) { 33 | 34 | if(args.length >= 3){ 35 | if(Bukkit.getPlayer(args[2]) != null){ 36 | org.bukkit.entity.Player target = Bukkit.getPlayer(args[2]); 37 | if(args[1].equalsIgnoreCase("client")){ 38 | if(ClientDetector.playerClient.get(target.getUniqueId()) != null && ClientDetector.clientVersion.get(target.getUniqueId()) == null) { 39 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("message").getString("player.clientwithoutversion").replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%player_name%", target.getName()).replace("%player_uuid%", target.getUniqueId().toString()).replace("%client_name%", ClientDetector.playerClient.get(target.getUniqueId())))); 40 | }else if(ClientDetector.playerClient.get(target.getUniqueId()) != null && ClientDetector.clientVersion.get(target.getUniqueId()) != null) { 41 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("message").getString("player.clientwithversion").replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%player_name%", target.getName()).replace("%player_uuid%", target.getUniqueId().toString()).replace("%client_name%", ClientDetector.playerClient.get(target.getUniqueId())).replace("%client_version%", ClientDetector.clientVersion.get(target.getUniqueId())))); 42 | }else{ 43 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("message").getString("player.clientwithoutversion").replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%player_name%", target.getName()).replace("%player_uuid%", target.getUniqueId().toString()).replace("%client_name%", "Vanilla (Undetectable)"))); 44 | } 45 | }else if(args[1].equalsIgnoreCase("mods")){ 46 | if(ConfigManager.getConfig("message").getString("player.playermods") != null){ 47 | ArrayList message = (ArrayList) ConfigManager.getConfig("message").get("player.playermods"); 48 | 49 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', message.get(0).replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%player_name%", target.getName()))); 50 | if(ClientDetector.playerMods.get(target.getUniqueId()) != null){ 51 | for(String mod : ClientDetector.playerMods.get(target.getUniqueId())){ 52 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', message.get(1).replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%mod_name%", mod))); 53 | } 54 | } 55 | } 56 | }else if(args[1].equalsIgnoreCase("version")){ 57 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&' , ConfigManager.getConfig("message").getString("player.mcversion").replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%player_name%", target.getName()).replace("%mc_version%", PacketEvents.getAPI().getPlayerManager().getClientVersion(target).name().replace("v_", "").replaceAll("_", ".")))); 58 | }else if(args[1].equalsIgnoreCase("labyaddons")){ 59 | if(ConfigManager.getConfig("message").getString("player.playerlabymods") != null){ 60 | ArrayList message = (ArrayList) ConfigManager.getConfig("message").get("player.playermods"); 61 | 62 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', message.get(0).replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%player_name%", target.getName()))); 63 | if(ClientDetector.playerLabymodMods.get(target.getUniqueId()) != null){ 64 | for(String mod : ClientDetector.playerLabymodMods.get(target.getUniqueId())){ 65 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', message.get(1).replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%mod_name%", mod))); 66 | } 67 | } 68 | } 69 | } 70 | }else{ 71 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("message").getString("error.playernotfound").replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%player_name%", args[2]))); 72 | } 73 | }else if(args.length == 2){ 74 | if(args[1].equalsIgnoreCase("list")){ 75 | if(!Bukkit.getOnlinePlayers().isEmpty()){ 76 | for(org.bukkit.entity.Player player : Bukkit.getOnlinePlayers()){ 77 | if(ClientDetector.playerClient.get(player.getUniqueId()) != null){ 78 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("message").getString("player.clientlist").replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%player_name%", player.getName()).replace("%client_name%", ClientDetector.playerClient.get(player.getUniqueId())))); 79 | } 80 | } 81 | }else{ 82 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("message").getString("error.noplayersonline").replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")))); 83 | } 84 | } 85 | }else{ 86 | sender.sendMessage(ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("message").getString("prefix") + " &cPlease use: /cd player ")); 87 | } 88 | return false; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/command/impl/Reload.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.command.impl; 20 | 21 | import org.bukkit.command.Command; 22 | import org.bukkit.command.CommandSender; 23 | import org.bukkit.entity.Player; 24 | 25 | public class Reload { 26 | public static boolean handle(CommandSender sender, Command command, String label, String[] args) { 27 | org.bukkit.entity.Player p = (Player) sender; 28 | 29 | return false; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/discord/DiscordWebhook.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.discord; 20 | 21 | import javax.net.ssl.HttpsURLConnection; 22 | import java.awt.Color; 23 | import java.io.IOException; 24 | import java.io.OutputStream; 25 | import java.lang.reflect.Array; 26 | import java.net.URL; 27 | import java.util.ArrayList; 28 | import java.util.HashMap; 29 | import java.util.List; 30 | import java.util.Map; 31 | import java.util.Set; 32 | 33 | /** 34 | * Class used to execute Discord Webhooks 35 | * 36 | * Credits: 37 | * Made by k3kdude (https://gist.github.com/k3kdude) 38 | * GitHub: https://gist.github.com/k3kdude/fba6f6b37594eae3d6f9475330733bdb 39 | */ 40 | public class DiscordWebhook { 41 | 42 | private final String url; 43 | private final List embeds = new ArrayList<>(); 44 | 45 | /** 46 | * Constructs a new DiscordWebhook instance 47 | * 48 | * @param url The webhook URL obtained in Discord 49 | */ 50 | public DiscordWebhook(String url) { 51 | this.url = url; 52 | } 53 | 54 | public void addEmbed(EmbedObject embed) { 55 | this.embeds.add(embed); 56 | } 57 | 58 | public void execute() throws IOException { 59 | 60 | JSONObject json = new JSONObject(); 61 | 62 | if (!this.embeds.isEmpty()) { 63 | List embedObjects = new ArrayList<>(); 64 | 65 | for (EmbedObject embed : this.embeds) { 66 | JSONObject jsonEmbed = new JSONObject(); 67 | 68 | jsonEmbed.put("title", embed.getTitle()); 69 | jsonEmbed.put("description", embed.getDescription()); 70 | 71 | if (embed.getColor() != null) { 72 | Color color = embed.getColor(); 73 | int rgb = color.getRed(); 74 | rgb = (rgb << 8) + color.getGreen(); 75 | rgb = (rgb << 8) + color.getBlue(); 76 | 77 | jsonEmbed.put("color", rgb); 78 | } 79 | 80 | EmbedObject.Footer footer = embed.getFooter(); 81 | EmbedObject.Thumbnail thumbnail = embed.getThumbnail(); 82 | 83 | if (footer != null) { 84 | JSONObject jsonFooter = new JSONObject(); 85 | 86 | jsonFooter.put("text", footer.getText()); 87 | jsonFooter.put("icon_url", footer.getIconUrl()); 88 | jsonEmbed.put("footer", jsonFooter); 89 | } 90 | 91 | if (thumbnail != null) { 92 | JSONObject jsonThumbnail = new JSONObject(); 93 | 94 | jsonThumbnail.put("url", thumbnail.getUrl()); 95 | jsonEmbed.put("thumbnail", jsonThumbnail); 96 | } 97 | 98 | 99 | embedObjects.add(jsonEmbed); 100 | } 101 | 102 | json.put("embeds", embedObjects.toArray()); 103 | } 104 | 105 | URL url = new URL(this.url); 106 | HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); 107 | connection.addRequestProperty("Content-Type", "application/json"); 108 | connection.addRequestProperty("User-Agent", "ClientDetector-Webhook"); 109 | connection.setDoOutput(true); 110 | connection.setRequestMethod("POST"); 111 | 112 | OutputStream stream = connection.getOutputStream(); 113 | stream.write(json.toString().getBytes()); 114 | stream.flush(); 115 | stream.close(); 116 | 117 | connection.getInputStream().close(); //I'm not sure why but it doesn't work without getting the InputStream 118 | connection.disconnect(); 119 | } 120 | 121 | public static class EmbedObject { 122 | private String title; 123 | private String description; 124 | private Color color; 125 | 126 | private Footer footer; 127 | private Thumbnail thumbnail; 128 | 129 | public String getTitle() { 130 | return title; 131 | } 132 | 133 | public String getDescription() { 134 | return description; 135 | } 136 | 137 | public Color getColor() { 138 | return color; 139 | } 140 | 141 | public Footer getFooter() { 142 | return footer; 143 | } 144 | 145 | public Thumbnail getThumbnail() { 146 | return thumbnail; 147 | } 148 | 149 | public EmbedObject setTitle(String title) { 150 | this.title = title; 151 | return this; 152 | } 153 | 154 | public EmbedObject setDescription(String description) { 155 | this.description = description; 156 | return this; 157 | } 158 | 159 | 160 | public EmbedObject setColor(Color color) { 161 | this.color = color; 162 | return this; 163 | } 164 | 165 | public EmbedObject setFooter(String text, String icon) { 166 | this.footer = new Footer(text, icon); 167 | return this; 168 | } 169 | 170 | public EmbedObject setThumbnail(String url) { 171 | this.thumbnail = new Thumbnail(url); 172 | return this; 173 | } 174 | 175 | 176 | private class Footer { 177 | private final String text; 178 | private final String iconUrl; 179 | 180 | private Footer(String text, String iconUrl) { 181 | this.text = text; 182 | this.iconUrl = iconUrl; 183 | } 184 | 185 | private String getText() { 186 | return text; 187 | } 188 | 189 | private String getIconUrl() { 190 | return iconUrl; 191 | } 192 | } 193 | 194 | private class Thumbnail { 195 | private final String url; 196 | 197 | private Thumbnail(String url) { 198 | this.url = url; 199 | } 200 | 201 | private String getUrl() { 202 | return url; 203 | } 204 | } 205 | } 206 | 207 | private class JSONObject { 208 | 209 | private final HashMap map = new HashMap<>(); 210 | 211 | void put(String key, Object value) { 212 | if (value != null) { 213 | map.put(key, value); 214 | } 215 | } 216 | 217 | @Override 218 | public String toString() { 219 | StringBuilder builder = new StringBuilder(); 220 | Set> entrySet = map.entrySet(); 221 | builder.append("{"); 222 | 223 | int i = 0; 224 | for (Map.Entry entry : entrySet) { 225 | Object val = entry.getValue(); 226 | builder.append(quote(entry.getKey())).append(":"); 227 | 228 | if (val instanceof String) { 229 | builder.append(quote(String.valueOf(val))); 230 | } else if (val instanceof Integer) { 231 | builder.append(Integer.valueOf(String.valueOf(val))); 232 | } else if (val instanceof Boolean) { 233 | builder.append(val); 234 | } else if (val instanceof JSONObject) { 235 | builder.append(val); 236 | } else if (val.getClass().isArray()) { 237 | builder.append("["); 238 | int len = Array.getLength(val); 239 | for (int j = 0; j < len; j++) { 240 | builder.append(Array.get(val, j).toString()).append(j != len - 1 ? "," : ""); 241 | } 242 | builder.append("]"); 243 | } 244 | 245 | builder.append(++i == entrySet.size() ? "}" : ","); 246 | } 247 | 248 | return builder.toString(); 249 | } 250 | 251 | private String quote(String string) { 252 | return "\"" + string + "\""; 253 | } 254 | } 255 | 256 | } -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/forgemod/ForgeHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.forgemod; 20 | 21 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 22 | import de.sportkanone123.clientdetector.spigot.api.events.ClientDetectedEvent; 23 | import de.sportkanone123.clientdetector.spigot.bungee.DataType; 24 | import de.sportkanone123.clientdetector.spigot.client.Client; 25 | import de.sportkanone123.clientdetector.spigot.manager.ConfigManager; 26 | import org.bukkit.Bukkit; 27 | import org.bukkit.entity.Player; 28 | 29 | import java.util.ArrayList; 30 | import java.util.List; 31 | 32 | public class ForgeHandler { 33 | public static void handlePluginMessage(Player player, String channel, byte[] data){ 34 | if(channel.equalsIgnoreCase("FML|HS") || channel.equalsIgnoreCase("l:fmlhs") || (channel.equalsIgnoreCase("minecraft:brand") && new String(data).contains("forge")) || (channel.equalsIgnoreCase("MC|Brand") && new String(data).contains("forge"))){ 35 | if(ConfigManager.getConfig("config").getBoolean("forge.blockForge")){ 36 | if(!player.hasPermission("clientdetector.bypass") && !((ArrayList) ConfigManager.getConfig("config").get("forge.whitelistedPlayers")).contains(player.getName())){ 37 | if(player.isOnline()){ 38 | Bukkit.getScheduler().runTaskLater(ClientDetector.plugin, new Runnable(){ 39 | @Override 40 | public void run() { 41 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), ConfigManager.getConfig("config").getString("forge.punishCommandForge").replace("%player_name%", player.getName())); 42 | } 43 | }, 10l); 44 | }else{ 45 | if(ClientDetector.playerCommandsQueue.get(player.getUniqueId()) == null) 46 | ClientDetector.playerCommandsQueue.put(player.getUniqueId(), new ArrayList<>()); 47 | 48 | ClientDetector.playerCommandsQueue.get(player.getUniqueId()).add(ConfigManager.getConfig("config").getString("forge.punishCommandForge").replace("%player_name%", player.getName())); 49 | } 50 | } 51 | } 52 | } 53 | } 54 | 55 | public static void handleDetection(Player player, String mod){ 56 | if(ClientDetector.plugin.getConfig().getBoolean("forge.enableWhitelist")){ 57 | if(ClientDetector.plugin.getConfig().get("forge.whitelistedMods") != null){ 58 | List whitelist = (ArrayList) ClientDetector.plugin.getConfig().get("forge.whitelistedMods"); 59 | if(!whitelist.contains(mod) && !player.hasPermission("clientdetector.bypass") && !((ArrayList) ClientDetector.plugin.getConfig().get("forge.whitelistedPlayers")).contains(player.getName())){ 60 | if(player.isOnline()){ 61 | Bukkit.getScheduler().runTaskLater(ClientDetector.plugin, new Runnable(){ 62 | @Override 63 | public void run() { 64 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), ClientDetector.plugin.getConfig().getString("forge.punishCommandWhitelist").replace("%player_name%", player.getName()).replace("%mod_name%", mod).replace("%player_uuid%", player.getUniqueId().toString())); 65 | } 66 | }, 10l); 67 | }else{ 68 | if(ClientDetector.playerCommandsQueue.get(player.getUniqueId()) == null) 69 | ClientDetector.playerCommandsQueue.put(player.getUniqueId(), new ArrayList<>()); 70 | 71 | ClientDetector.playerCommandsQueue.get(player.getUniqueId()).add(ClientDetector.plugin.getConfig().getString("forge.punishCommandWhitelist").replace("%player_name%", player.getName()).replace("%mod_name%", mod).replace("%player_uuid%", player.getUniqueId().toString())); 72 | } 73 | } 74 | } 75 | } 76 | 77 | if(ClientDetector.plugin.getConfig().getBoolean("forge.enableBlacklist")){ 78 | if(ClientDetector.plugin.getConfig().get("forge.blacklistedMods") != null){ 79 | List blacklist = (ArrayList) ClientDetector.plugin.getConfig().get("forge.blacklistedMods"); 80 | if(blacklist.contains(mod) && !player.hasPermission("clientdetector.bypass") && !((ArrayList) ClientDetector.plugin.getConfig().get("forge.whitelistedPlayers")).contains(player.getName())){ 81 | if(player.isOnline()){ 82 | Bukkit.getScheduler().runTaskLater(ClientDetector.plugin, new Runnable(){ 83 | @Override 84 | public void run() { 85 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), ClientDetector.plugin.getConfig().getString("forge.punishCommandBlacklist").replace("%player_name%", player.getName()).replace("%mod_name%", mod).replace("%player_uuid%", player.getUniqueId().toString())); 86 | } 87 | }, 10l); 88 | }else{ 89 | if(ClientDetector.playerCommandsQueue.get(player.getUniqueId()) == null) 90 | ClientDetector.playerCommandsQueue.put(player.getUniqueId(), new ArrayList<>()); 91 | 92 | ClientDetector.playerCommandsQueue.get(player.getUniqueId()).add(ClientDetector.plugin.getConfig().getString("forge.punishCommandBlacklist").replace("%player_name%", player.getName()).replace("%mod_name%", mod).replace("%player_uuid%", player.getUniqueId().toString())); 93 | } 94 | } 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/forgemod/ModList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.forgemod; 20 | 21 | import java.util.ArrayList; 22 | 23 | public class ModList { 24 | private ArrayList mods = new ArrayList<>(); 25 | 26 | public ModList(ArrayList mods){ 27 | this.mods = mods; 28 | } 29 | 30 | public ArrayList getMods() { 31 | return mods; 32 | } 33 | 34 | public void setMods(ArrayList mods) { 35 | this.mods = mods; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/forgemod/legacy/ForgeHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.forgemod.legacy; 20 | 21 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 22 | import de.sportkanone123.clientdetector.spigot.api.events.ForgeModlistDetectedEvent; 23 | import de.sportkanone123.clientdetector.spigot.bungee.DataType; 24 | import de.sportkanone123.clientdetector.spigot.forgemod.ModList; 25 | import de.sportkanone123.clientdetector.spigot.manager.ConfigManager; 26 | import org.bukkit.Bukkit; 27 | import org.bukkit.entity.Player; 28 | 29 | import java.util.ArrayList; 30 | import java.util.Arrays; 31 | 32 | public class ForgeHandler { 33 | public static void handle(Player player, String channel, byte[] data){ 34 | if(ConfigManager.getConfig("config").getBoolean("forge.enableLegacyDetection")){ 35 | if(channel.equalsIgnoreCase("FML|HS") && data != null && data[0] == 2){ 36 | ClientDetector.forgeMods.put(player.getUniqueId(), getModList(data)); 37 | 38 | if(ClientDetector.bungeeManager != null && ConfigManager.getConfig("config").getBoolean("bungee.enableBungeeClient")) 39 | ClientDetector.bungeeManager.syncList(DataType.FORGE_MOD_LIST, player, ClientDetector.forgeMods.get(player.getUniqueId()).getMods()); 40 | 41 | for(String forgeMod : getModList(data).getMods()) 42 | de.sportkanone123.clientdetector.spigot.forgemod.ForgeHandler.handleDetection(player, forgeMod); 43 | 44 | Bukkit.getScheduler().runTask(ClientDetector.plugin, new Runnable(){ 45 | @Override 46 | public void run() { 47 | Bukkit.getPluginManager().callEvent(new ForgeModlistDetectedEvent(player, getModList(data))); 48 | } 49 | }); 50 | } 51 | } 52 | } 53 | 54 | public static ModList getModList(byte[] data){ 55 | ArrayList modList = new ArrayList<>(); 56 | 57 | boolean modname = false; 58 | String tempName = null; 59 | 60 | for (int i = 2; i < data.length; modname = !modname) 61 | { 62 | int i2 = i + data[i] + 1; 63 | byte[] range = Arrays.copyOfRange(data, i + 1, i2); 64 | 65 | String string = new String(range); 66 | 67 | if (modname) 68 | { 69 | modList.add(tempName); 70 | } 71 | else 72 | { 73 | tempName = string; 74 | } 75 | 76 | i = i2; 77 | } 78 | 79 | return new ModList(modList); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/forgemod/legacy/ForgeHandshake.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.forgemod.legacy; 20 | 21 | 22 | import com.github.retrooper.packetevents.PacketEvents; 23 | import com.github.retrooper.packetevents.manager.server.ServerVersion; 24 | import com.github.retrooper.packetevents.protocol.player.ClientVersion; 25 | import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPluginMessage; 26 | import org.bukkit.entity.Player; 27 | 28 | public class ForgeHandshake { 29 | 30 | 31 | // Channel ║ Bound To ║ Field Name ║ Field Type ║ Notes 32 | //══════════╬══════════╬══════════════════════╬═══════════════╬════════════ 33 | // FML|HS ║ Client ║ Discriminator ║ Byte ║ Always 0 for ServerHello 34 | // ║ ║ FML protocol Version ║ Byte ║ Determined from NetworkRegistery. Currently 2. 35 | // ║ ║ Override dimension ║ Optional Int ║ Only sent if protocol version is greater than 1. 36 | public static void sendServerHello(Player player, String channel){ 37 | WrapperPlayServerPluginMessage costumPayload = new WrapperPlayServerPluginMessage(channel, new byte[] {(byte) 0,(byte) 2,(byte) 0,(byte) 0,(byte) 0,(byte) 0 }); 38 | PacketEvents.getAPI().getPlayerManager().sendPacket(player, costumPayload); 39 | } 40 | 41 | 42 | // Channel ║ Bound To ║ Field Name ║ Field Type ║ Notes 43 | //══════════╬══════════╬══════════════════════╬═══════════════╬════════════ 44 | // FML|HS ║ Both ║ Discriminator ║ Byte ║ Always 2 for ModList 45 | // ║ ║ Number of mods ║ Varint ║ Number of mods below 46 | // ║ ║ Mods (name+version) ║ List(Str,Str) ║ 47 | public static void sendModList(Player player, String channel){ 48 | WrapperPlayServerPluginMessage costumPayload = new WrapperPlayServerPluginMessage(channel, new byte[] {(byte) 2,(byte) 0,(byte) 0,(byte) 0,(byte) 0 }); 49 | PacketEvents.getAPI().getPlayerManager().sendPacket(player, costumPayload); 50 | } 51 | 52 | 53 | // Channel ║ Bound To ║ Field Name ║ Field Type ║ Notes 54 | //══════════╬══════════╬══════════════════════╬═══════════════╬════════════ 55 | // FML|HS ║ Both ║ Discriminator ║ Byte ║ Always -1 (255) for HandshakeAck 56 | // ║ ║ Phase ║ Byte ║ The current phase, which is the ordinal (0-indexed) in the FMLHandshakeClientState or FMLHandshakeServerState enums (if the server is sending it, it is in the ServerState enum, and if the client is sending it, it is the ClientState enum). 57 | public static void sendHandshakeAck(Player player, Byte phase, String channel){ 58 | WrapperPlayServerPluginMessage costumPayload = new WrapperPlayServerPluginMessage(channel, new byte[] {(byte) -1, phase}); 59 | PacketEvents.getAPI().getPlayerManager().sendPacket(player, costumPayload); 60 | } 61 | 62 | 63 | // Channel ║ Bound To ║ Field Name ║ Field Type ║ Notes 64 | //══════════╬══════════╬══════════════════════╬═══════════════╬════════════ 65 | // FML|HS ║ Client ║ Discriminator ║ Byte ║ Always -2 (254) for HandshakeReset 66 | public static void sendHandshakeReset(Player player, String channel){ 67 | WrapperPlayServerPluginMessage costumPayload = new WrapperPlayServerPluginMessage(channel, new byte[] {(byte) -2,(byte) 0 }); 68 | PacketEvents.getAPI().getPlayerManager().sendPacket(player, costumPayload); 69 | } 70 | 71 | public static void sendHandshake(Player player){ 72 | if(PacketEvents.getAPI().getServerManager().getVersion().isOlderThanOrEquals(ServerVersion.V_1_12_2) && (PacketEvents.getAPI().getPlayerManager().getClientVersion(player).isNewerThanOrEquals(ClientVersion.V_1_8) && PacketEvents.getAPI().getPlayerManager().getClientVersion(player).isOlderThanOrEquals(ClientVersion.V_1_12_2))){ 73 | sendHandshakeReset(player, "FML|HS"); 74 | sendServerHello(player, "FML|HS"); 75 | sendModList(player, "FML|HS"); 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/forgemod/newerversion/ForgeHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.forgemod.newerversion; 20 | 21 | import com.github.retrooper.packetevents.PacketEvents; 22 | import com.github.retrooper.packetevents.event.simple.PacketLoginReceiveEvent; 23 | import com.github.retrooper.packetevents.manager.server.ServerVersion; 24 | import com.github.retrooper.packetevents.protocol.packettype.PacketType; 25 | import com.github.retrooper.packetevents.wrapper.login.client.WrapperLoginClientLoginStart; 26 | import com.github.retrooper.packetevents.wrapper.login.client.WrapperLoginClientPluginResponse; 27 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 28 | import de.sportkanone123.clientdetector.spigot.api.events.ForgeModlistDetectedEvent; 29 | import de.sportkanone123.clientdetector.spigot.bungee.DataType; 30 | import de.sportkanone123.clientdetector.spigot.forgemod.ModList; 31 | import de.sportkanone123.clientdetector.spigot.manager.ConfigManager; 32 | import io.netty.buffer.ByteBuf; 33 | import io.netty.buffer.Unpooled; 34 | import io.netty.handler.codec.DecoderException; 35 | import org.bukkit.Bukkit; 36 | import org.bukkit.entity.Player; 37 | 38 | import java.nio.charset.StandardCharsets; 39 | import java.util.ArrayList; 40 | import java.util.HashMap; 41 | 42 | public class ForgeHandler { 43 | static HashMap channelToName = new HashMap<>(); 44 | static HashMap nameToModlist = new HashMap<>(); 45 | 46 | 47 | public static void handle(PacketLoginReceiveEvent event){ 48 | if(ConfigManager.getConfig("config").getBoolean("forge.enableNewerVersionDetection")){ 49 | if(event.getPacketType() == PacketType.Login.Client.LOGIN_START ) { 50 | if(ConfigManager.getConfig("config").getBoolean("forge.simulateForgeHandshake") && PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_13) && !ClientDetector.forgeMods.containsKey(new WrapperLoginClientLoginStart(event).getPlayerUUID().get()) && !ConfigManager.getConfig("config").getBoolean("velocity.enableVelocitySupport")) { 51 | ForgeHandshake.sendModList(event.getChannel()); 52 | channelToName.put(event.getChannel(), new WrapperLoginClientLoginStart(event).getUsername()); 53 | } 54 | 55 | }else if(event.getPacketType() == PacketType.Login.Client.LOGIN_PLUGIN_RESPONSE) { 56 | if(!ConfigManager.getConfig("config").getBoolean("velocity.enableVelocitySupport")) 57 | event.setCancelled(true); 58 | 59 | try { 60 | nameToModlist.put(channelToName.get(event.getChannel()), getModList(new WrapperLoginClientPluginResponse(event).getData())); 61 | }catch (NullPointerException e){ 62 | 63 | } 64 | } 65 | } 66 | } 67 | 68 | public static void handleJoin(Player player){ 69 | if(nameToModlist.containsKey(player.getName())){ 70 | ClientDetector.forgeMods.put(player.getUniqueId(), nameToModlist.get(player.getName())); 71 | 72 | if(ClientDetector.bungeeManager != null && ConfigManager.getConfig("config").getBoolean("bungee.enableBungeeClient")) 73 | ClientDetector.bungeeManager.syncList(DataType.FORGE_MOD_LIST, player, ClientDetector.forgeMods.get(player.getUniqueId()).getMods()); 74 | 75 | for(String forgeMod : nameToModlist.get(player.getName()).getMods()) 76 | de.sportkanone123.clientdetector.spigot.forgemod.ForgeHandler.handleDetection(player, forgeMod); 77 | 78 | Bukkit.getScheduler().runTask(ClientDetector.plugin, new Runnable(){ 79 | @Override 80 | public void run() { 81 | Bukkit.getPluginManager().callEvent(new ForgeModlistDetectedEvent(player, nameToModlist.get(player.getName()))); 82 | } 83 | }); 84 | } 85 | } 86 | 87 | public static ModList getModList(byte[] data){ 88 | ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(data); 89 | 90 | ArrayList modList = new ArrayList<>(); 91 | 92 | if (getInt(wrappedBuffer) != 2) { 93 | return new ModList(modList); 94 | } 95 | 96 | for (int i = getInt(wrappedBuffer), i2 = 0; i2 < i; ++i2) { 97 | modList.add(getString(wrappedBuffer)); 98 | } 99 | 100 | return new ModList(modList); 101 | } 102 | 103 | public static String getString(final ByteBuf byteBuf) { 104 | int i = getInt(byteBuf); 105 | int i2; 106 | if (i > (i2 = 256) * 4) { 107 | throw new DecoderException("The received encoded string buffer length is longer than maximum allowed (" + i + " > " + i2 * 4 + ")"); 108 | } 109 | if (i < 0) { 110 | throw new DecoderException("The received encoded string buffer length is less than zero! Weird string!"); 111 | } 112 | String string = byteBuf.toString(byteBuf.readerIndex(), i, StandardCharsets.UTF_8); 113 | byteBuf.readerIndex(byteBuf.readerIndex() + i); 114 | if (string.length() > i2) { 115 | throw new DecoderException("The received string length is longer than maximum allowed (" + i + " > " + i2 + ")"); 116 | } 117 | return string; 118 | } 119 | 120 | public static int getInt(final ByteBuf byteBuf) { 121 | int i = 0; 122 | int i2 = 0; 123 | byte byte1; 124 | do { 125 | byte1 = byteBuf.readByte(); 126 | i |= (byte1 & 0x7F) << i2++ * 7; 127 | if (i2 > 5) { 128 | throw new RuntimeException("VarInt too big"); 129 | } 130 | } while ((byte1 & 0x80) == 0x80); 131 | return i; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/forgemod/newerversion/ForgeHandshake.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.forgemod.newerversion; 20 | 21 | import com.github.retrooper.packetevents.PacketEvents; 22 | import com.github.retrooper.packetevents.protocol.ConnectionState; 23 | import com.github.retrooper.packetevents.wrapper.login.server.WrapperLoginServerPluginRequest; 24 | 25 | public class ForgeHandshake { 26 | public static void sendModList(Object channel){ 27 | 28 | WrapperLoginServerPluginRequest wrappedPacketLoginOutCustomPayload = new WrapperLoginServerPluginRequest(/*Random ID*/111111, "fml:handshake", new byte[] { 1, 0, 0, 0 }); 29 | PacketEvents.getAPI().getPlayerManager().sendPacket(channel, wrappedPacketLoginOutCustomPayload); 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/hackdetector/HackDetector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.hackdetector; 20 | 21 | import de.sportkanone123.clientdetector.spigot.hackdetector.impl.AntiFastMath; 22 | import de.sportkanone123.clientdetector.spigot.hackdetector.impl.ChatExploit; 23 | import org.bukkit.entity.Player; 24 | import org.bukkit.event.EventHandler; 25 | import org.bukkit.event.Listener; 26 | import org.bukkit.event.player.AsyncPlayerChatEvent; 27 | import org.bukkit.event.player.PlayerJoinEvent; 28 | import org.bukkit.event.player.PlayerMoveEvent; 29 | import org.bukkit.event.player.PlayerQuitEvent; 30 | 31 | public class HackDetector implements Listener { 32 | public static void startChatCheck(Player player){ 33 | ChatExploit.startDetection(player); 34 | } 35 | 36 | @EventHandler 37 | public void onChat(AsyncPlayerChatEvent event){ 38 | ChatExploit.handleChat(event.getPlayer(), event); 39 | } 40 | 41 | @EventHandler 42 | public void onMove(PlayerMoveEvent event){ 43 | ChatExploit.handleMovement(event.getPlayer(), event); 44 | AntiFastMath.handleMovement(event.getPlayer(), event); 45 | } 46 | 47 | @EventHandler 48 | public void onJoin(PlayerJoinEvent event){ 49 | AntiFastMath.handleJoin(event.getPlayer(), event); 50 | } 51 | 52 | @EventHandler 53 | public void onQuit(PlayerQuitEvent event){ 54 | AntiFastMath.handleQuit(event.getPlayer(), event); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/hackdetector/impl/AntiFastMath.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * Credits: 19 | * AntiFastMath is based on AntiFastMath by MWHunter which is Licensed under MIT License. 20 | * Author: MWHunter, edited by Sportkanone123 21 | * GitHub: https://github.com/MWHunter/AntiFastMath 22 | */ 23 | 24 | 25 | package de.sportkanone123.clientdetector.spigot.hackdetector.impl; 26 | 27 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 28 | import de.sportkanone123.clientdetector.spigot.manager.ConfigManager; 29 | import org.bukkit.Bukkit; 30 | import org.bukkit.ChatColor; 31 | import org.bukkit.entity.Player; 32 | import org.bukkit.event.player.PlayerJoinEvent; 33 | import org.bukkit.event.player.PlayerMoveEvent; 34 | import org.bukkit.event.player.PlayerQuitEvent; 35 | import org.bukkit.scheduler.BukkitScheduler; 36 | import org.bukkit.util.Vector; 37 | 38 | import java.util.HashMap; 39 | import java.util.function.Consumer; 40 | 41 | public class AntiFastMath { 42 | static HashMap vanillaPrecision = new HashMap<>(); 43 | static HashMap fastMathPrecision = new HashMap<>(); 44 | static HashMap playerSamples = new HashMap<>(); 45 | static HashMap checkPlayer = new HashMap<>(); 46 | 47 | static int multiplier = 1000; //10000 48 | 49 | public static void handleMovement(Player player, PlayerMoveEvent event){ 50 | if(ConfigManager.getConfig("config").getBoolean("hackdetector.antifastmath.enableAntiFastMath")){ 51 | if(checkPlayer.get(player) != null && checkPlayer.get(player)){ 52 | Vector movement = event.getTo().toVector().subtract(event.getFrom().toVector()); 53 | Vector vanillaMovement = getVanillaMathMovement(movement, (float) (0.1), event.getFrom().getYaw()); 54 | Vector fastMathMovement = getFastMathMovement(movement, (float) (0.1), event.getFrom().getYaw()); 55 | 56 | double lowVanilla = Math.min(Math.abs(vanillaMovement.getX()), Math.abs(vanillaMovement.getZ())); 57 | double lowOptifine = Math.min(Math.abs(fastMathMovement.getX()), Math.abs(fastMathMovement.getZ())); 58 | 59 | double vanillaRunning = vanillaPrecision.get(event.getPlayer()); 60 | double optifineRunning = fastMathPrecision.get(event.getPlayer()); 61 | 62 | double xDistance = event.getFrom().getX() - event.getTo().getX(); 63 | double zDistance = event.getFrom().getZ() - event.getTo().getZ(); 64 | 65 | if ((lowVanilla < 1e-5 || lowOptifine < 1e-5) && ((xDistance * xDistance) + (zDistance * zDistance) > 0.01)) { 66 | vanillaRunning = vanillaRunning * 15 / 16 + lowVanilla; 67 | optifineRunning = optifineRunning * 15 / 16 + lowOptifine; 68 | 69 | vanillaPrecision.put(event.getPlayer(), vanillaRunning); 70 | fastMathPrecision.put(event.getPlayer(), optifineRunning); 71 | 72 | int count = playerSamples.get(event.getPlayer()); 73 | playerSamples.put(event.getPlayer(), count + 1); 74 | 75 | if (count == ConfigManager.getConfig("config").getInt("hackdetector.antifastmath.checkAfterCounts") && optifineRunning * multiplier < vanillaRunning) { 76 | checkPlayer.put(player, false); 77 | 78 | for(Player player1 : Bukkit.getOnlinePlayers()){ 79 | if(player1.hasPermission(ConfigManager.getConfig("config").getString("alerts.notificationPermission"))){ 80 | player1.sendMessage(ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("message").getString("hackdetector.antifastmath.usingfastmath").replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%player_name%", player.getName()).replace("%player_uuid%", player.getUniqueId().toString()))); 81 | } 82 | } 83 | 84 | if(ConfigManager.getConfig("config").getBoolean("hackdetector.antifastmath.enablePunishment")){ 85 | if(!player.hasPermission("clientdetector.bypass")){ 86 | BukkitScheduler scheduler = Bukkit.getServer().getScheduler(); 87 | scheduler.runTask(ClientDetector.plugin, () -> { 88 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("config").getString("hackdetector.antifastmath.punishCommand").replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%player_name%", player.getName()).replace("%player_uuid%", player.getUniqueId().toString()))); 89 | }); 90 | } 91 | } 92 | } 93 | } 94 | } 95 | } 96 | } 97 | 98 | public static void handleJoin(Player player, PlayerJoinEvent event){ 99 | vanillaPrecision.put(player, 0D); 100 | fastMathPrecision.put(player, 0D); 101 | playerSamples.put(player, 0); 102 | checkPlayer.put(player, true); 103 | } 104 | 105 | public static void handleQuit(Player player, PlayerQuitEvent event){ 106 | vanillaPrecision.remove(event.getPlayer()); 107 | fastMathPrecision.remove(event.getPlayer()); 108 | playerSamples.remove(event.getPlayer()); 109 | checkPlayer.put(player, false); 110 | } 111 | 112 | public static void load(){ 113 | OptifineMath.load(); 114 | 115 | for(Player player : Bukkit.getOnlinePlayers()){ 116 | vanillaPrecision.put(player, 0D); 117 | fastMathPrecision.put(player, 0D); 118 | playerSamples.put(player, 0); 119 | checkPlayer.put(player, true); 120 | } 121 | } 122 | 123 | public static Vector getVanillaMathMovement(Vector wantedMovement, float f, float f2) { 124 | float f3 = VanillaMath.sin(f2 * 0.017453292f); 125 | float f4 = VanillaMath.cos(f2 * 0.017453292f); 126 | 127 | float bestTheoreticalX = (float) (f3 * wantedMovement.getZ() + f4 * wantedMovement.getX()) / (f3 * f3 + f4 * f4) / f; 128 | float bestTheoreticalZ = (float) (-f3 * wantedMovement.getX() + f4 * wantedMovement.getZ()) / (f3 * f3 + f4 * f4) / f; 129 | 130 | return new Vector(bestTheoreticalX, 0, bestTheoreticalZ); 131 | } 132 | 133 | public static Vector getFastMathMovement(Vector wantedMovement, float f, float f2) { 134 | float f3 = OptifineMath.sin(f2 * 0.017453292f); 135 | float f4 = OptifineMath.cos(f2 * 0.017453292f); 136 | 137 | float bestTheoreticalX = (float) (f3 * wantedMovement.getZ() + f4 * wantedMovement.getX()) / (f3 * f3 + f4 * f4) / f; 138 | float bestTheoreticalZ = (float) (-f3 * wantedMovement.getX() + f4 * wantedMovement.getZ()) / (f3 * f3 + f4 * f4) / f; 139 | 140 | return new Vector(bestTheoreticalX, 0, bestTheoreticalZ); 141 | } 142 | 143 | public static class VanillaMath { 144 | private static final float[] SIN = make(new float[65536], arrf -> { 145 | for (int i = 0; i < arrf.length; ++i) { 146 | arrf[i] = (float) Math.sin((double) i * 3.141592653589793 * 2.0 / 65536.0); 147 | } 148 | }); 149 | 150 | public static float sin(float f) { 151 | return SIN[(int) (f * 10430.378f) & 0xFFFF]; 152 | } 153 | 154 | public static float cos(float f) { 155 | return SIN[(int) (f * 10430.378f + 16384.0f) & 0xFFFF]; 156 | } 157 | 158 | public static float sqrt(float f) { 159 | return (float) Math.sqrt(f); 160 | } 161 | 162 | public static T make(T t, Consumer consumer) { 163 | consumer.accept(t); 164 | return t; 165 | } 166 | } 167 | 168 | public static class OptifineMath { 169 | private static final float[] SIN_TABLE_FAST = new float[4096]; 170 | private static final float radToIndex = roundToFloat(651.8986469044033D); 171 | 172 | public static void load(){ 173 | for (int j = 0; j < SIN_TABLE_FAST.length; ++j) { 174 | SIN_TABLE_FAST[j] = roundToFloat(Math.sin((double) j * Math.PI * 2.0D / 4096.0D)); 175 | } 176 | } 177 | 178 | public static float sin(float value) { 179 | return SIN_TABLE_FAST[(int) (value * radToIndex) & 4095]; 180 | } 181 | 182 | public static float cos(float value) { 183 | return SIN_TABLE_FAST[(int) (value * radToIndex + 1024.0F) & 4095]; 184 | } 185 | 186 | public static float roundToFloat(double d) { 187 | return (float) ((double) Math.round(d * 1.0E8D) / 1.0E8D); 188 | } 189 | } 190 | } -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/hackdetector/impl/ChatExploit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | package de.sportkanone123.clientdetector.spigot.hackdetector.impl; 21 | 22 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 23 | import de.sportkanone123.clientdetector.spigot.manager.ConfigManager; 24 | import net.md_5.bungee.api.chat.ClickEvent; 25 | import net.md_5.bungee.api.chat.TextComponent; 26 | import org.bukkit.Bukkit; 27 | import org.bukkit.ChatColor; 28 | import org.bukkit.entity.Player; 29 | import org.bukkit.event.player.AsyncPlayerChatEvent; 30 | import org.bukkit.event.player.PlayerMoveEvent; 31 | import org.bukkit.scheduler.BukkitScheduler; 32 | 33 | import java.util.ArrayList; 34 | import java.util.HashMap; 35 | import java.util.UUID; 36 | 37 | public class ChatExploit { 38 | static HashMap verificationStarted = new HashMap<>(); 39 | static HashMap randomString = new HashMap<>(); 40 | static HashMap secondsLeft = new HashMap<>(); 41 | 42 | public static void startDetection(Player player){ 43 | if(ConfigManager.getConfig("config").getBoolean("hackdetector.chatexploit.enableChatExploit") && !player.hasPermission("clientdetector.bypass")){ 44 | verificationStarted.put(player, true); 45 | randomString.put(player, UUID.randomUUID().toString()); 46 | secondsLeft.put(player, ConfigManager.getConfig("config").getInt("hackdetector.chatexploit.kickAfterSeconds")); 47 | 48 | sendMessage(player); 49 | 50 | BukkitScheduler scheduler = Bukkit.getServer().getScheduler(); 51 | scheduler.scheduleSyncRepeatingTask(ClientDetector.plugin, () -> { 52 | if (verificationStarted.containsKey(player)) { 53 | if (secondsLeft.get(player) - 1 == 0) { 54 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("config").getString("hackdetector.chatexploit.punishCommand").replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%player_name%", player.getName()).replace("%player_uuid%", player.getUniqueId().toString()))); 55 | } else { 56 | secondsLeft.put(player, secondsLeft.get(player) - 1); 57 | sendMessage(player); 58 | } 59 | } 60 | }, 0L, 20L); 61 | } 62 | } 63 | 64 | public static void handleChat(Player player, AsyncPlayerChatEvent event){ 65 | if(randomString.containsKey(player) && event.getMessage().equalsIgnoreCase(".say " + randomString.get(player))){ 66 | verificationStarted.remove(player); 67 | 68 | event.setCancelled(true); 69 | 70 | player.sendMessage(ChatColor.translateAlternateColorCodes('&', ConfigManager.getConfig("message").getString("hackdetector.chatexploit.success").replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")))); 71 | } 72 | } 73 | 74 | public static void handleMovement(Player player, PlayerMoveEvent event){ 75 | if(verificationStarted.containsKey(player) && ConfigManager.getConfig("config").getBoolean("hackdetector.chatexploit.disableMoving")){ 76 | event.setCancelled(true); 77 | } 78 | } 79 | 80 | public static void sendMessage(Player player){ 81 | if(ConfigManager.getConfig("message").get("hackdetector.chatexploit.clickabletext") != null){ 82 | ArrayList messages = (ArrayList) ConfigManager.getConfig("message").get("hackdetector.chatexploit.clickabletext"); 83 | TextComponent componentBuilder = new TextComponent(); 84 | 85 | for(String string: messages){ 86 | componentBuilder = new TextComponent(); 87 | 88 | componentBuilder.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, ".say " + randomString.get(player))); 89 | componentBuilder.setText(ChatColor.translateAlternateColorCodes('&', string.replace("%prefix%", ConfigManager.getConfig("message").getString("prefix")).replace("%time%", secondsLeft.get(player).toString()))); 90 | 91 | player.spigot().sendMessage(componentBuilder); 92 | } 93 | 94 | } 95 | } 96 | 97 | public static void handleQuit(Player player){ 98 | verificationStarted.remove(player); 99 | randomString.remove(player); 100 | secondsLeft.remove(player); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/listener/NetworkListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.listener; 20 | 21 | import com.github.retrooper.packetevents.event.PacketListenerPriority; 22 | import com.github.retrooper.packetevents.event.SimplePacketListenerAbstract; 23 | import com.github.retrooper.packetevents.event.simple.PacketLoginReceiveEvent; 24 | import com.github.retrooper.packetevents.event.simple.PacketPlayReceiveEvent; 25 | import de.sportkanone123.clientdetector.spigot.packet.processor.PacketProcessor; 26 | 27 | 28 | public class NetworkListener extends SimplePacketListenerAbstract { 29 | 30 | public NetworkListener() { 31 | super(PacketListenerPriority.HIGH); 32 | } 33 | 34 | 35 | @Override 36 | public void onPacketPlayReceive(PacketPlayReceiveEvent event) { 37 | PacketProcessor.handlePacket(event); 38 | } 39 | 40 | @Override 41 | public void onPacketLoginReceive(PacketLoginReceiveEvent event) { 42 | PacketProcessor.handleLoginPacket(event); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/listener/PlayerListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.listener; 20 | 21 | import com.github.retrooper.packetevents.PacketEvents; 22 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 23 | import de.sportkanone123.clientdetector.spigot.forgemod.legacy.ForgeHandshake; 24 | import de.sportkanone123.clientdetector.spigot.hackdetector.HackDetector; 25 | import de.sportkanone123.clientdetector.spigot.hackdetector.impl.ChatExploit; 26 | import de.sportkanone123.clientdetector.spigot.manager.AlertsManager; 27 | import de.sportkanone123.clientdetector.spigot.manager.ConfigManager; 28 | import de.sportkanone123.clientdetector.spigot.manager.GeyserManager; 29 | import org.bukkit.Bukkit; 30 | import org.bukkit.event.EventHandler; 31 | import org.bukkit.event.Listener; 32 | import org.bukkit.event.player.PlayerJoinEvent; 33 | import org.bukkit.event.player.PlayerQuitEvent; 34 | 35 | import java.util.ArrayList; 36 | import java.util.List; 37 | 38 | public class PlayerListener implements Listener { 39 | 40 | @EventHandler 41 | public static void onJoin(PlayerJoinEvent event) { 42 | 43 | if (ClientDetector.plugin.getConfig().getBoolean("forge.simulateForgeHandshake") && !ClientDetector.forgeMods.containsKey(event.getPlayer().getUniqueId())) 44 | ForgeHandshake.sendHandshake(event.getPlayer()); 45 | 46 | de.sportkanone123.clientdetector.spigot.forgemod.newerversion.ForgeHandler.handleJoin(event.getPlayer()); 47 | 48 | if (GeyserManager.isBedrockPlayer(event.getPlayer())) 49 | AlertsManager.handleGeyserDetection(event.getPlayer()); 50 | 51 | /* Needed for Cracked Vape detection */ 52 | if(ConfigManager.getConfig("config").getBoolean("hackdetector.detectcrackedvape.enableDetectCrackedVape")) 53 | event.getPlayer().sendMessage("§8 §8 §1 §3 §3 §7 §8 "); 54 | 55 | 56 | if (ClientDetector.plugin.getConfig().getBoolean("client.enableMinecraftVersionDetection")) { 57 | ClientDetector.mcVersion.put(event.getPlayer().getUniqueId(), PacketEvents.getAPI().getPlayerManager().getClientVersion(event.getPlayer()).name().replace("V_", "").replaceAll("_", ".")); 58 | } 59 | 60 | if (ConfigManager.getConfig("config").getBoolean("alerts.disablevanillamessages")) 61 | event.setJoinMessage(null); 62 | 63 | HackDetector.startChatCheck(event.getPlayer()); 64 | 65 | if (ClientDetector.playerCommandsQueue.get(event.getPlayer().getUniqueId()) != null && !ClientDetector.playerCommandsQueue.get(event.getPlayer().getUniqueId()).isEmpty()) { 66 | List toRemove = new ArrayList<>(); 67 | for (String string : ClientDetector.playerCommandsQueue.get(event.getPlayer().getUniqueId())) { 68 | toRemove.add(string); 69 | Bukkit.getScheduler().runTask(ClientDetector.plugin, new Runnable() { 70 | @Override 71 | public void run() { 72 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), string); 73 | } 74 | }); 75 | } 76 | ClientDetector.playerCommandsQueue.get(event.getPlayer().getUniqueId()).removeAll(toRemove); 77 | } 78 | } 79 | 80 | @EventHandler 81 | public static void onQuit(PlayerQuitEvent event) { 82 | 83 | if (ClientDetector.bungeeManager == null || !ConfigManager.getConfig("config").getBoolean("bungee.enableBungeeClient")) { 84 | ClientDetector.playerClient.remove(event.getPlayer().getUniqueId()); 85 | ClientDetector.playerMods.remove(event.getPlayer().getUniqueId()); 86 | ClientDetector.playerLabymodMods.remove(event.getPlayer().getUniqueId()); 87 | ClientDetector.forgeMods.remove(event.getPlayer().getUniqueId()); 88 | ClientDetector.mcVersion.remove(event.getPlayer().getUniqueId()); 89 | ClientDetector.clientVersion.remove(event.getPlayer().getUniqueId()); 90 | AlertsManager.firstDetection.remove(event.getPlayer().getUniqueId()); 91 | } 92 | 93 | if(event.getQuitMessage() != null && !event.getQuitMessage().isEmpty()) 94 | if(event.getQuitMessage().contains("Internal Exception: io.netty.codec.DecoderException: Badly compressed packet - size of 2 is below server threshold of 256") || event.getQuitMessage().contains("mismatched mod channel list")) 95 | ConfigManager.optimizeConfig("config", "forge.simulateForgeHandshake", false); 96 | 97 | if (ConfigManager.getConfig("config").getBoolean("alerts.disablevanillamessages")) 98 | event.setQuitMessage(null); 99 | 100 | ChatExploit.handleQuit(event.getPlayer()); 101 | 102 | if (ClientDetector.playerCommandsQueue.get(event.getPlayer().getUniqueId()) != null && !ClientDetector.playerCommandsQueue.get(event.getPlayer().getUniqueId()).isEmpty()) { 103 | ClientDetector.playerCommandsQueue.get(event.getPlayer().getUniqueId()).clear(); 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/listener/PluginMessageListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.listener; 20 | 21 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 22 | import org.bukkit.entity.Player; 23 | 24 | import java.nio.charset.StandardCharsets; 25 | 26 | public class PluginMessageListener implements org.bukkit.plugin.messaging.PluginMessageListener { 27 | @Override 28 | public void onPluginMessageReceived(String channel, Player player, byte[] data) { 29 | if(channel.equalsIgnoreCase("cd:spigot")){ 30 | ClientDetector.bungeeManager.handleSyncMessage(new String(data, StandardCharsets.UTF_8)); 31 | }else{ 32 | de.sportkanone123.clientdetector.spigot.mod.processor.PluginMessageProcessor.handlePluginMessage(player, channel, data); 33 | de.sportkanone123.clientdetector.spigot.client.processor.PluginMessageProcessor.handlePluginMessage(player, channel, data); 34 | 35 | de.sportkanone123.clientdetector.spigot.clientcontrol.ClientControl.handlePluginMessage(player, channel, data); 36 | 37 | de.sportkanone123.clientdetector.spigot.forgemod.legacy.ForgeHandler.handle(player, channel, data); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/manager/ClientManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.manager; 20 | 21 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 22 | import de.sportkanone123.clientdetector.spigot.bungee.DataType; 23 | import de.sportkanone123.clientdetector.spigot.client.Client; 24 | import org.bukkit.Bukkit; 25 | import org.bukkit.entity.Player; 26 | 27 | import java.util.ArrayList; 28 | import java.util.Arrays; 29 | import java.util.List; 30 | 31 | public class ClientManager { 32 | 33 | public static void load(){ 34 | 35 | /* 36 | Tested 37 | */ 38 | ClientDetector.CLIENTS.add(new Client(Arrays.asList("FML|HS", "l:fmlhs"), "", "Forge", true, false, null, null)); 39 | ClientDetector.CLIENTS.add(new Client(Arrays.asList("5zig_Set", "l:5zig_set"), "", "5zig Mod", true, false, null, null)); 40 | ClientDetector.CLIENTS.add(new Client(Arrays.asList("LABYMOD", "LMC", "labymod3:main"), "", "LabyMod", true, false, null, null)); 41 | ClientDetector.CLIENTS.add(new Client("vanilla", "vanilla", "Aristois (Experimental)", false, false, null, null)); 42 | ClientDetector.CLIENTS.add(new Client("vivecraft:data", "", "Vivecraft", true, false, null, null)); 43 | ClientDetector.CLIENTS.add(new Client("mysterymod:mm", "", "MysteryMod", true, false, null, null)); 44 | ClientDetector.CLIENTS.add(new Client("hyperium", "", "Hyperium", true, false, null, null)); 45 | ClientDetector.CLIENTS.add(new Client("PX|Version", "", "PXMod", true, false, null, null)); 46 | ClientDetector.CLIENTS.add(new Client("MC|Pixel", "", "Pixel Client", true, false, null, null)); 47 | 48 | ClientDetector.CLIENTS.add(new Client(Arrays.asList("MC|Brand", "minecraft:brand"), "vanilla", "Vanilla (Undetectable)", false, false, null, null)); 49 | ClientDetector.CLIENTS.add(new Client(Arrays.asList("MC|Brand", "minecraft:brand"), "LiteLoader", "LiteLoader", false, false, null, null)); 50 | ClientDetector.CLIENTS.add(new Client(Arrays.asList("MC|Brand", "minecraft:brand"), "PLC18", "PvPLounge Client", false, false, null, null)); 51 | ClientDetector.CLIENTS.add(new Client(Arrays.asList("MC|Brand", "minecraft:brand"), "fabric", "Fabric", false, false, null, null)); 52 | ClientDetector.CLIENTS.add(new Client(Arrays.asList("MC|Brand", "minecraft:brand"), "lunarclient", "Lunar Client", false, true, ":", 1)); 53 | ClientDetector.CLIENTS.add(new Client(Arrays.asList("MC|Brand", "minecraft:brand"), Arrays.asList("forge", "fml", "fml,forge"), "Forge", false, false, null, null)); 54 | ClientDetector.CLIENTS.add(new Client(Arrays.asList("MC|Brand", "minecraft:brand"), "PolarClient", "Polar Client", false, false, null, null)); 55 | ClientDetector.CLIENTS.add(new Client(Arrays.asList("MC|Brand", "minecraft:brand"), "rift", "Rift", false, false, null, null)); 56 | 57 | ClientDetector.CLIENTS.add(new Client("REGISTER", "CB-Client", "CheatBreaker", false, false, null, null)); 58 | 59 | 60 | /* 61 | Not tested 62 | */ 63 | ClientDetector.CLIENTS.add(new Client("LOLIMAHACKER", "", "Cracked Vape", true, false, null, null)); 64 | ClientDetector.CLIENTS.add(new Client("LC|Brand", "", "Winterware", true, false, null, null)); 65 | 66 | ClientDetector.CLIENTS.add(new Client(Arrays.asList("MC|Brand", "minecraft:brand"), "Subsystem", "Easy Minecraft Client", false, false, null, null)); 67 | ClientDetector.CLIENTS.add(new Client(Arrays.asList("MC|Brand", "minecraft:brand"), "Minecraft-Console-Client", "Console Client", false, true, "/", 1)); 68 | ClientDetector.CLIENTS.add(new Client(Arrays.asList("MC|Brand", "minecraft:brand"), "Vanilla", "Jigsaw", false, false, null, null)); 69 | ClientDetector.CLIENTS.add(new Client(Arrays.asList("MC|Brand", "minecraft:brand"), "Feather Fabric", "Feather Client", false, false, null, null)); 70 | } 71 | 72 | public static void unLoad(){ 73 | ClientDetector.CLIENTS = new ArrayList(); 74 | } 75 | 76 | public static void handleDetection(Player player, String client){ 77 | if(ClientDetector.bungeeManager != null && ConfigManager.getConfig("config").getBoolean("bungee.enableBungeeClient")){ 78 | ClientDetector.bungeeManager.syncList(DataType.CLIENT_LIST, player, client); 79 | } 80 | 81 | if(ConfigManager.getConfig("config").getBoolean("client.enableWhitelist")){ 82 | if(ConfigManager.getConfig("config").get("client.whitelistedClients") != null){ 83 | List whitelist = (ArrayList) ConfigManager.getConfig("config").get("client.whitelistedClients"); 84 | if(!whitelist.contains(client) && !player.hasPermission("clientdetector.bypass") && !((ArrayList) ClientDetector.plugin.getConfig().get("client.whitelistedPlayers")).contains(player.getName())) { 85 | if(player.isOnline()){ 86 | Bukkit.getScheduler().runTask(ClientDetector.plugin, new Runnable() { 87 | @Override 88 | public void run() { 89 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), ConfigManager.getConfig("config").getString("client.punishCommandWhitelist").replace("%player_name%", player.getName()).replace("%client_name%", client).replace("%player_uuid%", player.getUniqueId().toString())); 90 | } 91 | }); 92 | }else{ 93 | if(ClientDetector.playerCommandsQueue.get(player.getUniqueId()) == null) 94 | ClientDetector.playerCommandsQueue.put(player.getUniqueId(), new ArrayList<>()); 95 | 96 | ClientDetector.playerCommandsQueue.get(player.getUniqueId()).add(ConfigManager.getConfig("config").getString("client.punishCommandWhitelist").replace("%player_name%", player.getName()).replace("%client_name%", client).replace("%player_uuid%", player.getUniqueId().toString())); 97 | } 98 | } 99 | } 100 | } 101 | 102 | if(ConfigManager.getConfig("config").getBoolean("client.enableBlacklist")){ 103 | if(ClientDetector.plugin.getConfig().get("client.blacklistedClients") != null){ 104 | List blacklist = (ArrayList) ConfigManager.getConfig("config").get("client.blacklistedClients"); 105 | if(blacklist.contains(client) && !player.hasPermission("clientdetector.bypass") && !((ArrayList) ConfigManager.getConfig("config").get("client.whitelistedPlayers")).contains(player.getName())){ 106 | if(player.isOnline()){ 107 | Bukkit.getScheduler().runTask(ClientDetector.plugin, new Runnable() { 108 | @Override 109 | public void run() { 110 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), ConfigManager.getConfig("config").getString("client.punishCommandBlacklist").replace("%player_name%", player.getName()).replace("%client_name%", client).replace("%player_uuid%", player.getUniqueId().toString())); 111 | } 112 | }); 113 | }else{ 114 | if(ClientDetector.playerCommandsQueue.get(player.getUniqueId()) == null) 115 | ClientDetector.playerCommandsQueue.put(player.getUniqueId(), new ArrayList<>()); 116 | 117 | ClientDetector.playerCommandsQueue.get(player.getUniqueId()).add(ConfigManager.getConfig("config").getString("client.punishCommandBlacklist").replace("%player_name%", player.getName()).replace("%client_name%", client).replace("%player_uuid%", player.getUniqueId().toString())); 118 | } 119 | } 120 | } 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/manager/ConfigManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.manager; 20 | 21 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 22 | import org.bukkit.Bukkit; 23 | import org.bukkit.ChatColor; 24 | import org.bukkit.configuration.InvalidConfigurationException; 25 | import org.bukkit.configuration.file.FileConfiguration; 26 | import org.bukkit.configuration.file.YamlConfiguration; 27 | import org.bukkit.plugin.Plugin; 28 | 29 | import java.io.File; 30 | import java.io.IOException; 31 | import java.nio.file.Files; 32 | import java.nio.file.LinkOption; 33 | import java.nio.file.Paths; 34 | import java.util.HashMap; 35 | 36 | public class ConfigManager { 37 | private static final Plugin plugin = ClientDetector.plugin ; 38 | static HashMap files = new HashMap(); 39 | static HashMap configurations = new HashMap(); 40 | 41 | public static void loadConfig(String string) throws IOException { 42 | File file = new File(plugin.getDataFolder(), string + ".yml"); 43 | if(!file.exists()){ 44 | file.getParentFile().mkdirs(); 45 | try { 46 | plugin.saveResource(string + ".yml", false); 47 | }catch (IllegalArgumentException e){ 48 | 49 | } 50 | FileConfiguration configuration = new YamlConfiguration(); 51 | try{ 52 | configuration.load(file); 53 | files.put(string, file); 54 | configurations.put(string, configuration); 55 | } catch(IOException | InvalidConfigurationException e){ 56 | System.out.println("[ClientDetector] Error loading files, please contact the developer and send him this stacktrace:"); 57 | e.printStackTrace(); 58 | } 59 | }else{ 60 | FileConfiguration configuration = new YamlConfiguration(); 61 | try{ 62 | configuration.load(file); 63 | files.put(string, file); 64 | configurations.put(string, configuration); 65 | } catch(IOException | InvalidConfigurationException e){ 66 | System.out.println("[ClientDetector] Error loading files, please contact the developer and send him this stacktrace:"); 67 | e.printStackTrace(); 68 | } 69 | } 70 | 71 | } 72 | 73 | public static void saveConfig(String string){ 74 | try { 75 | if(files.get(string) != null && configurations.get(string) != null){ 76 | configurations.get(string).save(files.get(string)); 77 | configurations.put(string, YamlConfiguration.loadConfiguration(files.get(string))); 78 | }else{ 79 | loadConfig(string); 80 | if(files.get(string) != null && configurations.get(string) != null){ 81 | configurations.get(string).save(files.get(string)); 82 | configurations.put(string, YamlConfiguration.loadConfiguration(files.get(string))); 83 | } 84 | } 85 | } catch (IOException e) { 86 | System.out.println("[ClientDetector] Error saving files, please contact the developer and send him this stacktrace:"); 87 | e.printStackTrace(); 88 | } 89 | } 90 | 91 | public static FileConfiguration getConfig(String string) { 92 | if(configurations.get(string) != null){ 93 | return configurations.get(string); 94 | }else{ 95 | try { 96 | loadConfig(string); 97 | if(configurations.get(string) != null){ 98 | return configurations.get(string); 99 | } 100 | } catch (IOException e) { 101 | e.printStackTrace(); 102 | } 103 | } 104 | return new YamlConfiguration(); 105 | } 106 | 107 | public static void reloadConfig(String string) throws IOException { 108 | if(files.get(string) != null && configurations.get(string) != null){ 109 | configurations.put(string, YamlConfiguration.loadConfiguration(files.get(string))); 110 | }else{ 111 | loadConfig(string); 112 | if(files.get(string) != null && configurations.get(string) != null){ 113 | configurations.put(string, YamlConfiguration.loadConfiguration(files.get(string))); 114 | } 115 | } 116 | } 117 | 118 | public static boolean optimizeConfig(String config, String path, Object value){ 119 | File file = new File(plugin.getDataFolder(), "data" + File.separator + "log" + ".yml"); 120 | 121 | if(!file.exists()) { 122 | try { 123 | file.getParentFile().mkdirs(); 124 | file.createNewFile(); 125 | 126 | if(!getConfig(config).get(path).equals(value) && !getConfig("data" + File.separator + "log").contains("automation.config_optimization." + path.replace(".", "_"))){ 127 | getConfig(config).set(path, value); 128 | getConfig("data" + File.separator + "log").set("automation.config_optimization." + path.replace(".", "_"), true); 129 | 130 | saveConfig(config); 131 | saveConfig("data" + File.separator + "log"); 132 | 133 | Bukkit.getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', "&7[&3ClientDetector&7] (&aConfigOptimizer&7) &c We detected a problem with your configuration, it will be updated automatically: Config file: '" + config + ".yml', path: '" + path + "'")); 134 | 135 | return true; 136 | } 137 | } catch (IOException e) { 138 | e.printStackTrace(); 139 | } 140 | } 141 | 142 | return false; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/manager/DiscordManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.manager; 20 | 21 | import de.sportkanone123.clientdetector.spigot.discord.DiscordWebhook; 22 | import org.bukkit.entity.Player; 23 | 24 | import java.awt.*; 25 | import java.io.IOException; 26 | import java.net.MalformedURLException; 27 | import java.net.URL; 28 | 29 | public class DiscordManager { 30 | private static URL url; 31 | 32 | public static boolean load(){ 33 | if(ConfigManager.getConfig("config").get("discord.webHookUrl") != null && !ConfigManager.getConfig("config").get("discord.webHookUrl").equals("") && !ConfigManager.getConfig("config").get("discord.webHookUrl").equals(" ")){ 34 | try { 35 | url = new URL(ConfigManager.getConfig("config").getString("discord.webHookUrl")); 36 | return true; 37 | } catch (MalformedURLException e) { 38 | return false; 39 | } 40 | }else { 41 | return false; 42 | } 43 | } 44 | 45 | public static void handle(Player player, String clientName){ 46 | if(url != null){ 47 | DiscordWebhook webhook = new DiscordWebhook(url.toString()); 48 | 49 | if(!ConfigManager.getConfig("config").getBoolean("discord.disableEmbedFooter")){ 50 | webhook.addEmbed(new DiscordWebhook.EmbedObject() 51 | .setTitle(ConfigManager.getConfig("config").getString("discord.embedTitle").replace("%player_name%", player.getName()).replace("%player_uuid%", player.getUniqueId().toString()).replace("%client_name%", clientName).replace("%line_break%", "\n")) 52 | .setDescription(ConfigManager.getConfig("config").getString("discord.embedMessage").replace("%player_name%", player.getName()).replace("%player_uuid%", player.getUniqueId().toString()).replace("%client_name%", clientName).replace("%line_break%", "\n")) 53 | .setColor(Color.LIGHT_GRAY) 54 | .setThumbnail("https://crafatar.com/avatars/" + player.getUniqueId()) 55 | .setFooter("Check out ClientDetctor on SpigotMC: https://www.spigotmc.org/resources/clientdetector.90375/", "https://www.spigotmc.org/data/resource_icons/90/90375.jpg?1616258526")); 56 | 57 | }else{ 58 | webhook.addEmbed(new DiscordWebhook.EmbedObject() 59 | .setTitle(ConfigManager.getConfig("config").getString("discord.embedTitle").replace("%player_name%", player.getName()).replace("%player_uuid%", player.getUniqueId().toString()).replace("%client_name%", clientName).replace("%line_break%", "\n")) 60 | .setDescription(ConfigManager.getConfig("config").getString("discord.embedMessage").replace("%player_name%", player.getName()).replace("%player_uuid%", player.getUniqueId().toString()).replace("%client_name%", clientName).replace("%line_break%", "\n")) 61 | .setColor(Color.LIGHT_GRAY) 62 | .setThumbnail("https://crafatar.com/avatars/" + player.getUniqueId())); 63 | 64 | } 65 | 66 | try { 67 | webhook.execute(); //Handle exception 68 | } catch (IOException e) { 69 | e.printStackTrace(); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/manager/GeyserManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.manager; 20 | 21 | import com.github.retrooper.packetevents.PacketEvents; 22 | import org.bukkit.entity.Player; 23 | 24 | public class GeyserManager { 25 | public static boolean isBedrockPlayer(Player player){ 26 | //ToDo 27 | return false; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/manager/ModManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.manager; 20 | 21 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 22 | import de.sportkanone123.clientdetector.spigot.bungee.DataType; 23 | import de.sportkanone123.clientdetector.spigot.mod.Mod; 24 | import org.bukkit.Bukkit; 25 | import org.bukkit.entity.Player; 26 | 27 | import java.util.ArrayList; 28 | import java.util.Arrays; 29 | import java.util.List; 30 | import java.util.Locale; 31 | 32 | public class ModManager { 33 | 34 | public static void load(){ 35 | ClientDetector.MODS.add(new Mod(Arrays.asList("5zig_Set", "l:5zig_set", "the5zigmod:5zig_set"), Arrays.asList(""), "5zig Mod", true)); 36 | ClientDetector.MODS.add(new Mod(Arrays.asList("BSprint", "BSM", "l:bsprint", "l:bsm"), Arrays.asList(""), "Better Sprinting Mod", true)); 37 | ClientDetector.MODS.add(new Mod(Arrays.asList("WDL|INIT", "WDL|CONTROL", "wdl:request", "wdl:init", "wdl:control"), Arrays.asList(""), "World Downloader", true)); 38 | ClientDetector.MODS.add(new Mod(Arrays.asList("journeymap_channel", "journeymap:channel"), Arrays.asList(""), "JourneyMap", true)); 39 | ClientDetector.MODS.add(new Mod(Arrays.asList("WECUI"), Arrays.asList(""), "WorldEditCUI", true)); 40 | } 41 | 42 | public static void unLoad(){ 43 | ClientDetector.MODS = new ArrayList(); 44 | } 45 | 46 | public static void handleDetection(Player player, String mod){ 47 | if(ClientDetector.bungeeManager != null && ConfigManager.getConfig("config").getBoolean("bungee.enableBungeeClient")) 48 | ClientDetector.bungeeManager.syncList(DataType.MOD_LIST, player, ClientDetector.playerMods.get(player.getUniqueId())); 49 | 50 | if(ConfigManager.getConfig("config").getBoolean("mods.enableWhitelist")){ 51 | if(ConfigManager.getConfig("config").get("mods.whitelistedMods") != null) { 52 | List whitelist = (ArrayList) ConfigManager.getConfig("config").get("mods.whitelistedMods"); 53 | if ((!whitelist.contains(mod) && !whitelist.contains(mod.toLowerCase(Locale.ROOT))) && !player.hasPermission("clientdetector.bypass") && !((ArrayList) ConfigManager.getConfig("config").get("mods.whitelistedPlayers")).contains(player.getName())) { 54 | if(player.isOnline()){ 55 | Bukkit.getScheduler().runTask(ClientDetector.plugin, new Runnable() { 56 | @Override 57 | public void run() { 58 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), ConfigManager.getConfig("config").getString("mods.punishCommandWhitelist").replace("%player_name%", player.getName()).replace("%mod_name%", mod).replace("%player_uuid%", player.getUniqueId().toString())); 59 | } 60 | }); 61 | }else{ 62 | if(ClientDetector.playerCommandsQueue.get(player.getUniqueId()) == null) 63 | ClientDetector.playerCommandsQueue.put(player.getUniqueId(), new ArrayList<>()); 64 | 65 | ClientDetector.playerCommandsQueue.get(player.getUniqueId()).add(ConfigManager.getConfig("config").getString("mods.punishCommandWhitelist").replace("%player_name%", player.getName()).replace("%mod_name%", mod).replace("%player_uuid%", player.getUniqueId().toString())); 66 | } 67 | } 68 | } 69 | } 70 | 71 | if(ConfigManager.getConfig("config").getBoolean("mods.enableBlacklist")){ 72 | if(ConfigManager.getConfig("config").get("mods.blacklistedMods") != null){ 73 | List blacklist = (ArrayList) ClientDetector.plugin.getConfig().get("mods.blacklistedMods"); 74 | if((blacklist.contains(mod) || blacklist.contains(mod.toLowerCase(Locale.ROOT))) && !player.hasPermission("clientdetector.bypass") && !((ArrayList) ConfigManager.getConfig("config").get("mods.whitelistedPlayers")).contains(player.getName())){ 75 | if(player.isOnline()){ 76 | Bukkit.getScheduler().runTask(ClientDetector.plugin, new Runnable() { 77 | @Override 78 | public void run() { 79 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), ConfigManager.getConfig("config").getString("mods.punishCommandBlacklist").replace("%player_name%", player.getName()).replace("%mod_name%", mod).replace("%player_uuid%", player.getUniqueId().toString())); 80 | } 81 | }); 82 | }else{ 83 | if(ClientDetector.playerCommandsQueue.get(player.getUniqueId()) == null) 84 | ClientDetector.playerCommandsQueue.put(player.getUniqueId(), new ArrayList<>()); 85 | 86 | ClientDetector.playerCommandsQueue.get(player.getUniqueId()).add(ConfigManager.getConfig("config").getString("mods.punishCommandBlacklist").replace("%player_name%", player.getName()).replace("%mod_name%", mod).replace("%player_uuid%", player.getUniqueId().toString())); 87 | } 88 | } 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/manager/PlaceholderManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.manager; 20 | 21 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 22 | import me.clip.placeholderapi.expansion.PlaceholderExpansion; 23 | import org.bukkit.entity.Player; 24 | import org.bukkit.plugin.Plugin; 25 | 26 | public class PlaceholderManager extends PlaceholderExpansion { 27 | static Plugin plugin = ClientDetector.plugin; 28 | 29 | public boolean persist() { 30 | return true; 31 | } 32 | 33 | public boolean canRegister() { 34 | return true; 35 | } 36 | 37 | public String getAuthor() { 38 | return plugin.getDescription().getAuthors().toString(); 39 | } 40 | 41 | public String getIdentifier() { 42 | return "clientdetector"; 43 | } 44 | 45 | public String getVersion() { 46 | return plugin.getDescription().getVersion(); 47 | } 48 | 49 | public String onPlaceholderRequest(Player player, String identifier) { 50 | if(identifier.equalsIgnoreCase("client_name")){ 51 | if(ClientDetector.playerClient.get(player.getUniqueId()) != null) 52 | return ClientDetector.playerClient.get(player.getUniqueId()); 53 | return "Vanilla (Undetectable)"; 54 | } 55 | if(identifier.equalsIgnoreCase("client_version")){ 56 | if(ClientDetector.clientVersion.get(player.getUniqueId()) != null) 57 | return ClientDetector.clientVersion.get(player.getUniqueId()); 58 | return "unknown"; 59 | } 60 | if(identifier.equalsIgnoreCase("forge_user")){ 61 | if(ClientDetector.forgeMods.get(player.getUniqueId()).getMods() == null || ClientDetector.forgeMods.get(player.getUniqueId()).getMods().isEmpty()) 62 | return "false"; 63 | return "true"; 64 | } 65 | if(identifier.equalsIgnoreCase("bedrock_player")){ 66 | return String.valueOf(GeyserManager.isBedrockPlayer(player)); 67 | } 68 | if(identifier.equalsIgnoreCase("forge_list")){ 69 | if(ClientDetector.forgeMods.get(player.getUniqueId()) == null) 70 | return "notusingforge"; 71 | 72 | if(ClientDetector.forgeMods.get(player.getUniqueId()).getMods().isEmpty()) 73 | return "unknown"; 74 | 75 | String string = ""; 76 | for(String mod : ClientDetector.forgeMods.get(player.getUniqueId()).getMods()) 77 | string = string + mod + "; "; 78 | 79 | return string; 80 | } 81 | if(identifier.equalsIgnoreCase("labymod_addons")){ 82 | if(ClientDetector.playerLabymodMods.get(player.getUniqueId()) == null) 83 | return "notusinglabymod"; 84 | 85 | if(ClientDetector.playerLabymodMods.get(player.getUniqueId()).isEmpty()) 86 | return "unknown"; 87 | 88 | String string = ""; 89 | for(String mod : ClientDetector.playerLabymodMods.get(player.getUniqueId())) 90 | string = string + mod + "; "; 91 | 92 | return string; 93 | } 94 | 95 | if(identifier.equalsIgnoreCase("minecraft_version")){ 96 | if(ClientDetector.mcVersion.get(player.getUniqueId()) != null) 97 | return ClientDetector.mcVersion.get(player.getUniqueId()); 98 | return "unknown"; 99 | } 100 | return null; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/mod/Mod.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.mod; 20 | 21 | import com.github.retrooper.packetevents.PacketEvents; 22 | import com.github.retrooper.packetevents.manager.server.ServerVersion; 23 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 24 | import de.sportkanone123.clientdetector.spigot.listener.PluginMessageListener; 25 | import org.bukkit.Bukkit; 26 | 27 | import java.nio.charset.StandardCharsets; 28 | import java.util.Arrays; 29 | import java.util.List; 30 | 31 | public class Mod { 32 | private List channel; 33 | private List data; 34 | private String modName; 35 | private Boolean onlyChannel; 36 | 37 | public Mod(List channel, String data, String modName, Boolean onlyChannel){ 38 | this.channel = channel; 39 | this.data = Arrays.asList(data); 40 | this.modName = modName; 41 | this.onlyChannel = onlyChannel; 42 | } 43 | 44 | public Mod(String channel, String data, String modName, Boolean onlyChannel){ 45 | this.channel = Arrays.asList(channel); 46 | this.data = Arrays.asList(data); 47 | this.modName = modName; 48 | this.onlyChannel = onlyChannel; 49 | } 50 | 51 | public Mod(List channel, List data, String modName, Boolean onlyChannel){ 52 | this.channel = channel; 53 | this.data = data; 54 | this.modName = modName; 55 | this.onlyChannel = onlyChannel; 56 | } 57 | 58 | public Mod(String channel, List data, String modName, Boolean onlyChannel){ 59 | this.channel = Arrays.asList(channel); 60 | this.data = data; 61 | this.modName = modName; 62 | this.onlyChannel = onlyChannel; 63 | } 64 | 65 | public List getChannel() { return channel; } 66 | 67 | public void setChannel(List channel) { this.channel = channel; } 68 | 69 | public List getData() { return data; } 70 | 71 | public void setData(List data) { this.data = data; } 72 | 73 | public String getModName() { return modName; } 74 | 75 | public void setModName(String modName) { this.modName = modName; } 76 | 77 | public Boolean getOnlyChannel() { return onlyChannel; } 78 | 79 | public void setOnlyChannel(Boolean onlyChannel) { this.onlyChannel = onlyChannel; } 80 | 81 | public Boolean isMod(String channel, byte[] data){ 82 | if(this.onlyChannel) { 83 | for (String ch : this.channel) { 84 | if (channel.equalsIgnoreCase(ch)) return true; 85 | } 86 | return false; 87 | }else { 88 | for (String ch : this.channel) { 89 | for(String dat : this.data){ 90 | if (channel.equalsIgnoreCase(ch) && new String(data, StandardCharsets.UTF_8).contains(dat)) return true; 91 | } 92 | } 93 | return false; 94 | } 95 | } 96 | 97 | public String getModName(String channel, byte[] data){ 98 | if(isMod(channel, data)) 99 | return this.modName; 100 | else 101 | return null; 102 | } 103 | 104 | public void load(){ 105 | for(String str : this.channel) { 106 | if(PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_13)){ 107 | if(str.contains(":")){ 108 | Bukkit.getMessenger().registerIncomingPluginChannel(ClientDetector.plugin, str, new PluginMessageListener()); 109 | } 110 | }else{ 111 | Bukkit.getMessenger().registerIncomingPluginChannel(ClientDetector.plugin, str, new PluginMessageListener()); 112 | } 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/mod/processor/PacketProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.mod.processor; 20 | 21 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 22 | import de.sportkanone123.clientdetector.spigot.api.events.ModDetectedEvent; 23 | import de.sportkanone123.clientdetector.spigot.manager.AlertsManager; 24 | import de.sportkanone123.clientdetector.spigot.manager.ModManager; 25 | import de.sportkanone123.clientdetector.spigot.mod.Mod; 26 | import org.bukkit.Bukkit; 27 | import org.bukkit.entity.Player; 28 | 29 | import java.nio.charset.StandardCharsets; 30 | import java.util.ArrayList; 31 | 32 | public class PacketProcessor { 33 | public static void handlePacket(Player player, String channel, byte[] data){ 34 | byte[] customData = new String(data, StandardCharsets.UTF_8).replace("(Velocity)", "").getBytes(StandardCharsets.UTF_8); 35 | 36 | if(ClientDetector.plugin.getConfig().getBoolean("mods.enableModDetection")){ 37 | for(Mod mod : ClientDetector.MODS){ 38 | if(mod.isMod(channel, customData)){ 39 | if(ClientDetector.playerMods.get(player.getUniqueId()) == null) 40 | ClientDetector.playerMods.put(player.getUniqueId(), new ArrayList()); 41 | 42 | ClientDetector.playerMods.get(player.getUniqueId()).add(mod.getModName()); 43 | 44 | Bukkit.getScheduler().runTask(ClientDetector.plugin, new Runnable(){ 45 | @Override 46 | public void run() { 47 | Bukkit.getPluginManager().callEvent(new ModDetectedEvent(player, mod.getModName())); 48 | } 49 | }); 50 | 51 | AlertsManager.handleModlistDetection(player, mod.getModName()); 52 | 53 | ModManager.handleDetection(player, mod.getModName()); 54 | } 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/mod/processor/PluginMessageProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.mod.processor; 20 | 21 | import de.sportkanone123.clientdetector.spigot.ClientDetector; 22 | import de.sportkanone123.clientdetector.spigot.api.events.ModDetectedEvent; 23 | import de.sportkanone123.clientdetector.spigot.manager.AlertsManager; 24 | import de.sportkanone123.clientdetector.spigot.manager.ModManager; 25 | import de.sportkanone123.clientdetector.spigot.mod.Mod; 26 | import org.bukkit.Bukkit; 27 | import org.bukkit.entity.Player; 28 | 29 | import java.nio.charset.StandardCharsets; 30 | import java.util.ArrayList; 31 | 32 | public class PluginMessageProcessor { 33 | public static void handlePluginMessage(Player player, String channel, byte[] data){ 34 | byte[] customData = new String(data, StandardCharsets.UTF_8).replace("(Velocity)", "").getBytes(StandardCharsets.UTF_8); 35 | 36 | if(ClientDetector.plugin.getConfig().getBoolean("mods.enableModDetection")){ 37 | for(Mod mod : ClientDetector.MODS){ 38 | if(mod.isMod(channel, customData)){ 39 | if(ClientDetector.playerMods.get(player.getUniqueId()) == null) 40 | ClientDetector.playerMods.put(player.getUniqueId(), new ArrayList()); 41 | 42 | ClientDetector.playerMods.get(player.getUniqueId()).add(mod.getModName()); 43 | 44 | Bukkit.getScheduler().runTask(ClientDetector.plugin, new Runnable(){ 45 | @Override 46 | public void run() { 47 | Bukkit.getPluginManager().callEvent(new ModDetectedEvent(player, mod.getModName())); 48 | } 49 | }); 50 | 51 | AlertsManager.handleModlistDetection(player, mod.getModName()); 52 | 53 | ModManager.handleDetection(player, mod.getModName()); 54 | } 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/packet/Packet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /*package de.sportkanone123.clientdetector.spigot.packet; 20 | 21 | import io.github.retrooper.packetevents.packettype.PacketType; 22 | import io.github.retrooper.packetevents.packetwrappers.NMSPacket; 23 | 24 | public class Packet { 25 | private final NMSPacket rawPacket; 26 | private final byte packetId; 27 | 28 | public Packet(NMSPacket rawPacket, byte packetId) { 29 | this.rawPacket = rawPacket; 30 | this.packetId = packetId; 31 | } 32 | 33 | public NMSPacket getRawPacket(){ return rawPacket; } 34 | 35 | public byte getPacketId(){ return packetId; } 36 | 37 | public boolean isCustomPayload() { return packetId == PacketType.Play.Client.CUSTOM_PAYLOAD; } 38 | } 39 | */ -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/spigot/packet/processor/PacketProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ClientDetector - https://github.com/Sportkanone123/ClientDetector 3 | * Copyright (C) 2021 Sportkanone123 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package de.sportkanone123.clientdetector.spigot.packet.processor; 20 | 21 | import com.github.retrooper.packetevents.event.simple.PacketLoginReceiveEvent; 22 | import com.github.retrooper.packetevents.event.simple.PacketPlayReceiveEvent; 23 | import com.github.retrooper.packetevents.protocol.packettype.PacketType; 24 | import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPluginMessage; 25 | import org.bukkit.entity.Player; 26 | 27 | import java.nio.charset.StandardCharsets; 28 | 29 | public class PacketProcessor { 30 | 31 | public static void handlePacket(PacketPlayReceiveEvent event){ 32 | if(event.getPacketType() == PacketType.Play.Client.PLUGIN_MESSAGE){ 33 | WrapperPlayClientPluginMessage wrapperPlayClientPluginMessage = new WrapperPlayClientPluginMessage(event); 34 | 35 | if(event.getPlayer() != null && ((Player) event.getPlayer()) != null && ((Player) event.getPlayer()).getUniqueId() != null){ 36 | Player player = (Player) event.getPlayer(); 37 | String channel = wrapperPlayClientPluginMessage.getChannelName(); 38 | byte[] data = wrapperPlayClientPluginMessage.getData(); 39 | 40 | de.sportkanone123.clientdetector.spigot.client.processor.PacketProcessor.handlePacket(player, channel, data); 41 | de.sportkanone123.clientdetector.spigot.mod.processor.PacketProcessor.handlePacket(player, channel, data); 42 | 43 | de.sportkanone123.clientdetector.spigot.forgemod.legacy.ForgeHandler.handle(player, channel, data); 44 | 45 | de.sportkanone123.clientdetector.spigot.clientcontrol.ClientControl.handlePacket(player, channel, data); 46 | de.sportkanone123.clientdetector.spigot.forgemod.ForgeHandler.handlePluginMessage(player, channel, data); 47 | } 48 | } 49 | } 50 | 51 | public static void handleLoginPacket(PacketLoginReceiveEvent event){ 52 | de.sportkanone123.clientdetector.spigot.forgemod.newerversion.ForgeHandler.handle(event); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/de/sportkanone123/clientdetector/velocity/ClientDetectorVelocity.java: -------------------------------------------------------------------------------- 1 | package de.sportkanone123.clientdetector.velocity; 2 | 3 | import com.google.inject.Inject; 4 | import com.velocitypowered.api.event.Subscribe; 5 | import com.velocitypowered.api.event.connection.DisconnectEvent; 6 | import com.velocitypowered.api.event.connection.PluginMessageEvent; 7 | import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; 8 | import com.velocitypowered.api.plugin.annotation.DataDirectory; 9 | import com.velocitypowered.api.proxy.ProxyServer; 10 | import com.velocitypowered.api.proxy.messages.LegacyChannelIdentifier; 11 | import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; 12 | import com.velocitypowered.api.proxy.server.RegisteredServer; 13 | 14 | import java.nio.charset.StandardCharsets; 15 | import java.nio.file.Path; 16 | import java.util.ArrayList; 17 | import java.util.HashMap; 18 | import java.util.List; 19 | import java.util.Map; 20 | import java.util.concurrent.TimeUnit; 21 | import java.util.logging.Logger; 22 | 23 | @com.velocitypowered.api.plugin.Plugin( 24 | id = "clientdetector", 25 | name = "ClientDetector", 26 | version = "2.5.5", 27 | description = "A simple plugin to detect and manage a player's client/mods", 28 | authors = {"Sportkanone123"} 29 | ) 30 | public class ClientDetectorVelocity { 31 | 32 | public static final LegacyChannelIdentifier LEGACY_BUNGEE_CHANNEL = new LegacyChannelIdentifier("cd:bungee"); 33 | public static final MinecraftChannelIdentifier MODERN_BUNGEE_CHANNEL = MinecraftChannelIdentifier.create("cd", "bungee"); 34 | public static final MinecraftChannelIdentifier MODERN_SPIGOT_CHANNEL = MinecraftChannelIdentifier.create("cd", "spigot"); 35 | 36 | private ProxyServer server; 37 | private Logger logger; 38 | private Path dataDirectory; 39 | private Map> queue = new HashMap<>(); 40 | 41 | @Inject 42 | public ClientDetectorVelocity(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) { 43 | this.server = server; 44 | this.logger = logger; 45 | this.dataDirectory = dataDirectory; 46 | } 47 | 48 | @Subscribe 49 | public void onProxyInitialization(ProxyInitializeEvent event) { 50 | //this.server.getEventManager().register(this, this); (Velocity already auto registered the main class) 51 | this.server.getChannelRegistrar().register(LEGACY_BUNGEE_CHANNEL, MODERN_BUNGEE_CHANNEL); 52 | 53 | runQueue(); 54 | } 55 | 56 | public void runQueue() { 57 | this.server.getScheduler().buildTask(this, new Runnable() { 58 | @Override 59 | public void run() { 60 | for(RegisteredServer registeredServer : queue.keySet()){ 61 | if(!registeredServer.getPlayersConnected().isEmpty() && queue.get(registeredServer) != null){ 62 | List toRemove = new ArrayList<>(); 63 | for(byte[] data : queue.get(registeredServer)){ 64 | toRemove.add(data); 65 | registeredServer.sendPluginMessage(MODERN_SPIGOT_CHANNEL, data); 66 | } 67 | queue.get(registeredServer).removeAll(toRemove); 68 | } 69 | } 70 | } 71 | }).repeat(1, TimeUnit.SECONDS); 72 | } 73 | 74 | @Subscribe 75 | public void onPluginMessage(PluginMessageEvent event) { 76 | System.out.println(event.getIdentifier() + " // " + new java.lang.String(event.getData())); 77 | if (event.getIdentifier().getId().equalsIgnoreCase("cd:bungee")) { 78 | sync(event.getData()); 79 | } 80 | } 81 | 82 | private void sync(String string){ 83 | sync(string.getBytes(StandardCharsets.UTF_8)); 84 | } 85 | 86 | private void sync(byte[] data){ 87 | for(RegisteredServer server : this.server.getAllServers()){ 88 | if(server.getPlayersConnected().isEmpty()){ 89 | if(queue.get(server) == null) queue.put(server, new ArrayList<>()); 90 | 91 | if(!new String(data, StandardCharsets.UTF_8).contains("CROSS_SERVER_MESSAGE")) 92 | queue.get(server).add(data); 93 | }else{ 94 | server.sendPluginMessage(MODERN_SPIGOT_CHANNEL, data); 95 | } 96 | } 97 | } 98 | 99 | @Subscribe 100 | public void onDisconnect(DisconnectEvent e) { 101 | String placeholder = "@@"; 102 | sync("PLAYER_LEFT" + placeholder + e.getPlayer().getUsername()); 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /src/main/resources/bungee.yml: -------------------------------------------------------------------------------- 1 | name: ClientDetector 2 | version: 2.5.6 3 | author: Sportkanone123 4 | main: de.sportkanone123.clientdetector.bungeecord.ClientDetectorBungee 5 | description: A simple plugin to detect and manage a player's client/mods 6 | -------------------------------------------------------------------------------- /src/main/resources/config.yml: -------------------------------------------------------------------------------- 1 | # _____ _ _ _ _____ _ _ 2 | # / ____| (_) | | | __ \ | | | | 3 | #| | | |_ ___ _ __ | |_| | | | ___| |_ ___ ___| |_ ___ _ __ 4 | #| | | | |/ _ \ '_ \| __| | | |/ _ \ __/ _ \/ __| __/ _ \| '__| 5 | #| |____| | | __/ | | | |_| |__| | __/ || __/ (__| || (_) | | 6 | # \_____|_|_|\___|_| |_|\__|_____/ \___|\__\___|\___|\__\___/|_| 7 | 8 | # ┌─────────────────────────────┐ 9 | # │ Client detection settings │ 10 | # └─────────────────────────────┘ 11 | client: 12 | #Should ClientDetector try to detect the client that a player uses? [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'true'] 13 | enableClientDetection: true 14 | #Should ClientDetector try to detect the version of the client that the player is using? Only a few client's (Lunar, Labymod, ...) support this detection! [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'true'] 15 | enableVersionDetection: true 16 | #Should ClientDetector detect the MC version of a player? [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'true'] 17 | enableMinecraftVersionDetection: true 18 | 19 | #List of players that will bypass all client punishments. [OPTIONS: 'anyList', PLACEHOLDERS: none, DEFAULT: [- examplePlayer]] 20 | whitelistedPlayers: 21 | - examplePlayer 22 | 23 | #If a players' client is detected the plugin will check if it is whitelisted, if not the punish command will be executed (only if this is enabled). [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'false'] 24 | enableWhitelist: false 25 | #Command that will be executed through the console if it's not on the whitelist. [OPTIONS: 'anyString', PLACEHOLDERS: ['%player_name%', '%player_uuid%', '%client_name%'], DEFAULT:'kick %player_name% %mod_name% is not allowed on this server'] 26 | punishCommandWhitelist: "kick %player_name% %client_name% is not allowed on this server" 27 | #List of whitelisted clients (name of detected clients can be found here: https://github.com/Sportkanone123/ClientDetector/blob/master/README.md). [OPTIONS: 'anyList', PLACEHOLDERS: none, DEFAULT: [- exampleMod]] 28 | whitelistedClients: 29 | - exampleClient 30 | 31 | #If a players' client is detected, and it is on the blacklist, the punish command will be executed trough the console (only if this is enabled). [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'false'] 32 | enableBlacklist: false 33 | #Command that will be executed through the console if the client is on the blacklist. [OPTIONS: 'anyString', PLACEHOLDERS: ['%player_name%', '%player_uuid%', '%client_name%'], DEFAULT:'kick %player_name% %mod_name% is not allowed on this server'] 34 | punishCommandBlacklist: "kick %player_name% %client_name% is not allowed on this server" 35 | #List of blacklisted clients (name of detected clients can be found here: https://github.com/Sportkanone123/ClientDetector/blob/master/README.md). [OPTIONS: 'anyList', PLACEHOLDERS: none, DEFAULT: [- exampleMod]] 36 | blacklistedClients: 37 | - exampleClient 38 | 39 | 40 | # ┌─────────────────────────────┐ 41 | # │ Mod detection settings │ 42 | # └─────────────────────────────┘ 43 | mods: 44 | #Should ClientDetector try to detect the mods that a player uses (not only forge mods)? [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'true'] 45 | enableModDetection: true 46 | 47 | #List of players that will bypass all mod punishments. [OPTIONS: 'anyList', PLACEHOLDERS: none, DEFAULT: [- examplePlayer]] 48 | whitelistedPlayers: 49 | - examplePlayer 50 | 51 | #If a player joins with mods the plugin will check if all mods are whitelisted, if not the punish command will be executed (only if this is enabled). [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'false'] 52 | enableWhitelist: false 53 | #Command that will be executed through the console if not all mods that a player are whitelisted. [OPTIONS: 'anyString', PLACEHOLDERS: ['%player_name%', '%player_uuid%', '%mod_name%'], DEFAULT:'kick %player_name% %mod_name% is not allowed on this server'] 54 | punishCommandWhitelist: "kick %player_name% %mod_name% is not allowed on this server" 55 | #List of whitelisted mods (name of detected mods can be found here: https://github.com/Sportkanone123/ClientDetector/blob/master/README.md). [OPTIONS: 'anyList', PLACEHOLDERS: none, DEFAULT: [- exampleMod]] 56 | whitelistedMods: 57 | - exampleMod 58 | 59 | #If a player join and one or more of his mods are on this list, the punish command will be executed trough the console (only if this is enabled). [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'false'] 60 | enableBlacklist: false 61 | #Command that will be executed through the console if one or more of his mods are on the blacklist. [OPTIONS: 'anyString', PLACEHOLDERS: ['%player_name%', '%player_uuid%', '%mod_name%'], DEFAULT:'kick %player_name% %mod_name% is not allowed on this server'] 62 | punishCommandBlacklist: "kick %player_name% %mod_name% is not allowed on this server" 63 | #List of blacklisted mods (name of detected mods can be found here: https://github.com/Sportkanone123/ClientDetector/blob/master/README.md). [OPTIONS: 'anyList', PLACEHOLDERS: none, DEFAULT: [- exampleMod]] 64 | blacklistedMods: 65 | - exampleMod 66 | 67 | 68 | # ┌─────────────────────────────┐ 69 | # │ Alerts settings │ 70 | # └─────────────────────────────┘ 71 | alerts: 72 | #Should the notifications be sent when a player's client/mods are detected? [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'true'] 73 | enableNotifications: true 74 | #Should the notifications be sent on every server that ClientDetector is installed on, on your network? (This only works if bungee.enableBungeeClient is enabled!) [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'true'] 75 | crossServerNotifications: true 76 | #Should only important notifications be sent to the player's to avoid spamming? [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'false'] 77 | limitNotifications: false 78 | #Everybody with this permission will get notifications about a player's client [OPTIONS: 'any.valid.permission', PLACEHOLDERS: none, DEFAULT:'clientdetecor.notify'] 79 | notificationPermission: 'clientdetector.notify' 80 | #Should vanilla join/leave messages be disabled? [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'false'] 81 | disablevanillamessages: false 82 | 83 | 84 | # ┌─────────────────────────────┐ 85 | # │ Placeholder settings │ 86 | # └─────────────────────────────┘ 87 | placeholder: 88 | #Should placeholder be enabled? [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'true'] 89 | enablePlaceholder: true 90 | 91 | 92 | # ┌─────────────────────────────┐ 93 | # │ Forge settings │ 94 | # └─────────────────────────────┘ 95 | forge: 96 | #Should forge mod detection be enabled for legacy(1.8-1.12.2) versions? [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'true'] 97 | enableLegacyDetection: true 98 | #Should forge mod detection be enabled for newer(1.13+) versions? [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'true'] 99 | enableNewerVersionDetection: true 100 | #Should the plugin send a "fake" handshake, this is required to get the modlist of a forge player. [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'true'] 101 | simulateForgeHandshake: true 102 | 103 | #List of players that will bypass all forge punishments. [OPTIONS: 'anyList', PLACEHOLDERS: none, DEFAULT: [- examplePlayer]] 104 | whitelistedPlayers: 105 | - examplePlayer 106 | 107 | #Should all player's that join with forge get kicked? [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'false'] 108 | blockForge: false 109 | #Command that will be executed through the console if one or more of his mods are on the blacklist. [OPTIONS: 'anyString', PLACEHOLDERS: ['%player_name%', '%player_uuid%'], DEFAULT:'kick %player_name% Forge is not allowed on this server'] 110 | punishCommandForge: "kick %player_name% Forge is not allowed on this Server" 111 | 112 | #If a player joins with forge the plugin will check if all forge mods are whitelisted, if not the punish command will be executed (only if this is enabled). [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'false'] 113 | enableWhitelist: false 114 | #Command that will be executed through the console if not all forge mods that a player are whitelisted. [OPTIONS: 'anyString', PLACEHOLDERS: ['%player_name%', '%player_uuid%', '%mod_name%'], DEFAULT:'kick %player_name% %mod_name% is not allowed on this server'] 115 | punishCommandWhitelist: "kick %player_name% %mod_name% is not allowed on this server" 116 | #List of whitelisted mods (name = ModID). [OPTIONS: 'anyList', PLACEHOLDERS: none, DEFAULT: [- exampleMod]] 117 | whitelistedMods: 118 | - exampleMod 119 | 120 | #If a player join and one or more of his forge mods are on this list, the punish command will be executed trough the console (only if this is enabled). [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'false'] 121 | enableBlacklist: false 122 | #Command that will be executed through the console if one or more of his forge mods are on the blacklist. [OPTIONS: 'anyString', PLACEHOLDERS: ['%player_name%', '%player_uuid%', '%mod_name%'], DEFAULT:'kick %player_name% %mod_name% is not allowed on this server'] 123 | punishCommandBlacklist: "kick %player_name% %mod_name% is not allowed on this server" 124 | #List of blacklisted mods (name = ModID). [OPTIONS: 'anyList', PLACEHOLDERS: none, DEFAULT: [- exampleMod]] 125 | blacklistedMods: 126 | - exampleMod 127 | 128 | 129 | # ┌─────────────────────────────┐ 130 | # │ Cross Server Sync Settings │ 131 | # └─────────────────────────────┘ 132 | bungee: 133 | #Do you want to use the BungeeCord feature? (Only enable if you use Bungeecord) [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT: 'false'] 134 | enableBungeeClient: false 135 | #Name of this Spigot/Paper/Bukkit/... server. [OPTIONS: 'anyString'', PLACEHOLDERS: none, DEFAULT: 'LOBBY'] 136 | serverName: "LOBBY" 137 | 138 | 139 | 140 | # ┌─────────────────────────────┐ 141 | # │ Discord settings │ 142 | # └─────────────────────────────┘ 143 | discord: 144 | #Discord WebHook Url. [OPTIONS: 'anyString', PLACEHOLDERS: none, DEFAULT: ""] 145 | webHookUrl: "" 146 | #Title of the embed message. [OPTIONS: 'anyString', PLACEHOLDERS: ['%player_name%', '%player_uuid%', '%client_name%', '%line_break%'], DEFAULT: "ClientDetector"] 147 | embedTitle: "ClientDetector" 148 | #Message of the embed message. [OPTIONS: 'anyString', PLACEHOLDERS: ['%player_name%', '%player_uuid%', '%client_name%', '%line_break%'], DEFAULT: ""] 149 | embedMessage: "%player_name% joined using %client_name%" 150 | #Should the footer be disabled. [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'false'] 151 | disableEmbedFooter: false 152 | #Should only important notifications be sent to the discord? [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'false'] 153 | limitNotifications: false 154 | 155 | 156 | # ┌─────────────────────────────┐ 157 | # │ HackDetector settings │ 158 | # └─────────────────────────────┘ 159 | hackdetector: 160 | chatexploit: 161 | #If a player joins they have to click on a message to continue playing. [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'false'] 162 | enableChatExploit: false 163 | #Should the player be allowed to move while he is tested. [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'true'] 164 | disableMoving: true 165 | #Seconds after which the player gets kicked if he does not pass the test. [OPTIONS: 'anyInteger', PLACEHOLDERS: none, DEFAULT:'20'] 166 | kickAfterSeconds: 20 167 | #Command that will be executed through the console if he fails the test. [OPTIONS: 'anyString', PLACEHOLDERS: ['%player_name%', '%player_uuid%', '%prefix%'], DEFAULT:'kick %player_name% %prefix% &aYou failed the test. \n&7(&fIf you think this is an error, please rejoin and click the message&7)'] 168 | punishCommand: "kick %player_name% %prefix% &aYou failed the test. \n&7(&fIf you think this is an error, please rejoin and click the message&7)" 169 | 170 | antifastmath: 171 | #ClienDetector can check if a player is using FastMath by analysing his movement. [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'false'] 172 | enableAntiFastMath: false 173 | #If FastMath is not detected set this Integer higher (min: 1, max: 50) [OPTIONS: 'anyInteger', PLACEHOLDERS: none, DEFAULT:'20'] 174 | checkAfterCounts: 20 175 | #Should the player be punished if he uses FastMath (FastMath doesn't indicate a hack client directly, but it doesn't exist in vanilla minecaft) . [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'false'] 176 | enablePunishment: false 177 | #Command that will be executed through the console if he fails the test. [OPTIONS: 'anyString', PLACEHOLDERS: ['%player_name%', '%player_uuid%', '%prefix%'], DEFAULT:'kick %player_name% %prefix% &aPlease use Vanilla Minecraft!'] 178 | punishCommand: "kick %player_name% %prefix% &aPlease use Vanilla Minecraft!" 179 | 180 | detectcrackedvape: 181 | #ClienDetector can check if a player is using cracked Vape by sending one line to the player when joining, it is displayed as an empty line. [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT:'true'] 182 | enableDetectCrackedVape: true 183 | 184 | # ┌─────────────────────────────┐ 185 | # │ HackDetector settings │ 186 | # └─────────────────────────────┘ 187 | velocity: 188 | #Do you want to use the Velocity feature? (Only enable if you use Velocity) [OPTIONS: 'true'/'false', PLACEHOLDERS: none, DEFAULT: 'false'] 189 | enableVelocitySupport: false 190 | -------------------------------------------------------------------------------- /src/main/resources/message.yml: -------------------------------------------------------------------------------- 1 | prefix: "&7[&3ClientDetector&7]" 2 | 3 | detection: 4 | #Message that will be sent when a player's client (and client version) was detected. [OPTIONS: "anyString", PLACEHOLDERS: ['%prefix%', '%player_name%', '%player_uuid%', '%client_name%', '%client_version%'], DEFAULT: "%prefix% &c%player_name% &7joined using &c%client_name% &7(&8version: &c%client_version%&7)"] 5 | clientdetectionmessagewithversion: "%prefix% &c%player_name% &7joined using &c%client_name% &7(&8version: &c%client_version%&7)" 6 | #Message that will be sent when a player's client was detected. [OPTIONS: "anyString", PLACEHOLDERS: ['%prefix%', '%player_name%', '%player_uuid%', '%client_name%'], DEFAULT: "%prefix% &c%player_name% &7joined using &c%client_name%"] 7 | clientdetectionmessagewithoutversion: "%prefix% &c%player_name% &7joined using &c%client_name%" 8 | #Message that will be sent if CrossServerNotifications are enabled. [OPTIONS: "anyString", PLACEHOLDERS: ['%prefix%', '%server_name%', '%%cross_server_message%'], DEFAULT: "%prefix% &c%player_name% &7joined using &c%client_name%"] 9 | clientdetectionmessagecrossserver: "&7[&c%server_name%&7] %cross_server_message%" 10 | #Message that will be sent when a bedrock player joins your server. [OPTIONS: "anyString", PLACEHOLDERS: ['%prefix%', '%player_name%', '%player_uuid%'], DEFAULT: "%prefix% &c%player_name% &7uses &cMinecraft Bedrock Edition"] 11 | geyserdetectionmessage: "%prefix% &c%player_name% &7uses &cMinecraft Bedrock Edition" 12 | #Message that will be sent when player joins and one or more mods are detected. [OPTIONS: "anyString", PLACEHOLDERS: ['%prefix%', '%player_name%', '%player_uuid%', '%mod_name%'], DEFAULT: "%prefix% &c%player_name% &7joined using &c%mod_name%"] 13 | moddetectionmessage: "%prefix% &c%player_name% &7joined using &c%mod_name%" 14 | 15 | forge: 16 | #Answer to command when the player does not use forge. [OPTIONS: "anyString", PLACEHOLDERS: ['%prefix%', '%player_name%', '%player_uuid%'], DEFAULT: "%prefix% &c%player_name% &7does not use Forge!"] 17 | notusingforge: "%prefix% &c%player_name% &7does not use Forge!" 18 | #Answer to command when the player uses forge, but no modlist was detected. [OPTIONS: "anyString", PLACEHOLDERS: ['%prefix%', '%player_name%', '%player_uuid%'], DEFAULT: "%prefix% &c%player_name% &7uses Forge, but his Forge modlist was not detected!"] 19 | usingforgebutnomodlistreceived: "%prefix% &c%player_name% &7uses Forge, but his Forge modlist was not detected!" 20 | #Answer to command when the player uses forge, and his modlist was detected. [OPTIONS: "List[anyString]", PLACEHOLDERS: ['%prefix%', '%player_name%', '%player_uuid%'], DEFAULT: ["&7&m------------------- %prefix% &7&m-------------------", "&c%player_name%&7's mods:", " ", "&8&m- &c%mod_name% &7(&c%mod_version%&7)", "&7&m------------------- %prefix% &7&m-------------------"]] 21 | usingforgemodlist: 22 | - "&7&m------------------- %prefix% &7&m-------------------" 23 | - "&c%player_name%&7's Forge mods:" 24 | - "" 25 | - "&8&m- &c%mod_name%" 26 | - "&7&m------------------- %prefix% &7&m-------------------" 27 | 28 | player: 29 | #Answer to command when a player's client was detected. [OPTIONS: "anyString", PLACEHOLDERS: ['%prefix%', '%player_name%', '%client_name%', '%client_version%'], DEFAULT: "%prefix% &c%player_name% &7is using &c%client_name% &7(&8version: &c%client_version%&7)"] 30 | clientwithversion: "%prefix% &c%player_name% &7is using &c%client_name% &7(&8version: &c%client_version%&7)" 31 | #Answer to command when a player's client was detected, but not it's version. [OPTIONS: "anyString", PLACEHOLDERS: ['%prefix%', '%player_name%', '%client_name%'], DEFAULT: "%prefix% &c%player_name% &7is using &c%client_name%"] 32 | clientwithoutversion: "%prefix% &c%player_name% &7is using &c%client_name%" 33 | #Answer to command when a player's MC version was detected. [OPTIONS: "anyString", PLACEHOLDERS: ['%prefix%', '%player_name%', '%mc_version%'], DEFAULT: "%prefix% &c%player_name% &7is using &c%mc_version%"] 34 | mcversion: "%prefix% &c%player_name% &7is using &c%mc_version%" 35 | #Answer to command when mods were detected. [OPTIONS: "List[anyString]", PLACEHOLDERS: ['%player_name%', '%mod_name%'], DEFAULT: ["&c%player_name%&7's mods:", "&8&m- &c%mod_name%"]] 36 | playermods: 37 | - "&c%player_name%&7's mods:" 38 | - "&8&m- &c%mod_name%" 39 | #Answer to command when LabyMod addons were detected. [OPTIONS: "List[anyString]", PLACEHOLDERS: ['%player_name%', '%mod_name%'], DEFAULT: ["&c%player_name%&7's mods:", "&8&m- &c%mod_name%"]] 40 | playerlabymods: 41 | - "&c%player_name%&7's LabyMod mods:" 42 | - "&8&m- &c%mod_name%" 43 | #Answer to command when players are online. [OPTIONS: "anyString", PLACEHOLDERS: ['%prefix%', '%player_name%', '%client_name%'], DEFAULT: "%prefix% &c%player% &8&m- &c%mod_name%"] 44 | clientlist: "%prefix% &c%player_name% &8&m- &c%client_name%" 45 | 46 | 47 | error: 48 | #Answer to command when the player is not online. [OPTIONS: "anyString", PLACEHOLDERS: ['%prefix%', '%player_name%', '%player_uuid%'], DEFAULT: "%prefix% &c%player_name% &7is not online!"] 49 | playernotfound: "%prefix% &c%player_name% &7is not online!" 50 | #Answer to command when the player has no permission to execute it. [OPTIONS: "anyString", PLACEHOLDERS: ['%prefix%'], DEFAULT: "%prefix% &cYou do not have permission to do that!"] 51 | nopermission: "%prefix% &cYou do not have permission to do that!" 52 | #Answer to command when it was executed through the console, but the command can only be used by players. [OPTIONS: "anyString", PLACEHOLDERS: ['%prefix%'], DEFAULT: "%prefix% &cThis command can only be used by players!"] 53 | onlyplayercanusecommand: "%prefix% &cThis command can only be used by players!" 54 | #Answer to command when the player is not online. [OPTIONS: "anyString", PLACEHOLDERS: ['%prefix%'], DEFAULT: "%prefix% &cCurrently there are no players online!"] 55 | noplayersonline: "%prefix% &cCurrently there are no players online!" 56 | 57 | hackdetector: 58 | chatexploit: 59 | #Text that will be sent to the player (the player has to click on it to pass the test). [OPTIONS: "anyString", PLACEHOLDERS: ['%prefix%', '%time%]] 60 | clickabletext: 61 | - " " 62 | - " " 63 | - " " 64 | - " " 65 | - " " 66 | - " " 67 | - " " 68 | - " " 69 | - " " 70 | - " " 71 | - " " 72 | - " " 73 | - " " 74 | - " " 75 | - " " 76 | - " " 77 | - " " 78 | - " " 79 | - " " 80 | - " " 81 | - "%prefix% &bPlease click this message to continue playing! You have %time% seconds left." 82 | #Message that will be sent to the player when he passes the test. [OPTIONS: "anyString", PLACEHOLDERS: ['%prefix%'], DEFAULT: "%prefix% &aYou have successfully passed the test."] 83 | success: "%prefix% &aYou have successfully passed the test." 84 | antifastmath: 85 | #Message if player is using FastMath. [OPTIONS: "anyString", PLACEHOLDERS: ['%prefix%', '%player_name%', '%player_uuid%'], DEFAULT: "%prefix% &c%player_name% &7is using &cFastMath!"] 86 | usingfastmath: "%prefix% &c%player_name% &7is using &cFastMath!" 87 | -------------------------------------------------------------------------------- /src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: ClientDetector 2 | version: 2.5.6 3 | author: Sportkanone123 4 | main: de.sportkanone123.clientdetector.spigot.ClientDetector 5 | description: A simple plugin to detect and manage a player's client/mods 6 | load: POSTWORLD 7 | api-version: 1.13 8 | 9 | softdepend: [PlaceholderAPI, ProtocolLib, ViaVersion] 10 | 11 | commands: 12 | clientdetector: 13 | aliases: cd 14 | client: 15 | forge: 16 | mods: --------------------------------------------------------------------------------