Initial commit: XeroAntiCheat v1.0.7
This commit is contained in:
283
src/main/java/com/xeroth/xeroanticheat/XeroAntiCheat.java
Normal file
283
src/main/java/com/xeroth/xeroanticheat/XeroAntiCheat.java
Normal file
@@ -0,0 +1,283 @@
|
||||
package com.xeroth.xeroanticheat;
|
||||
|
||||
import com.xeroth.xeroanticheat.checks.combat.*;
|
||||
import com.xeroth.xeroanticheat.checks.misc.*;
|
||||
import com.xeroth.xeroanticheat.checks.movement.*;
|
||||
import com.xeroth.xeroanticheat.check.Check;
|
||||
import com.xeroth.xeroanticheat.command.XACCommand;
|
||||
import com.xeroth.xeroanticheat.listener.CombatListener;
|
||||
import com.xeroth.xeroanticheat.listener.MiscListener;
|
||||
import com.xeroth.xeroanticheat.listener.MovementListener;
|
||||
import com.xeroth.xeroanticheat.manager.CheckManager;
|
||||
import com.xeroth.xeroanticheat.manager.ConfigManager;
|
||||
import com.xeroth.xeroanticheat.manager.DatabaseManager;
|
||||
import com.xeroth.xeroanticheat.manager.PunishmentManager;
|
||||
import com.xeroth.xeroanticheat.manager.ViolationManager;
|
||||
import com.xeroth.xeroanticheat.protocol.PacketListener;
|
||||
import com.xeroth.xeroanticheat.data.PlayerData;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* XeroAntiCheat - Lightweight, accurate anti-cheat for Paper 1.21.x
|
||||
*
|
||||
* This plugin provides comprehensive cheat detection including movement,
|
||||
* combat, and miscellaneous checks with minimal false positives.
|
||||
*/
|
||||
public final class XeroAntiCheat extends JavaPlugin {
|
||||
|
||||
private static XeroAntiCheat instance;
|
||||
|
||||
private ConfigManager configManager;
|
||||
private ViolationManager violationManager;
|
||||
private PunishmentManager punishmentManager;
|
||||
private CheckManager checkManager;
|
||||
private PacketListener packetListener;
|
||||
private DatabaseManager databaseManager;
|
||||
|
||||
private boolean protocolLibLoaded = false;
|
||||
|
||||
// Staff alert toggles
|
||||
private final Map<UUID, Boolean> alertToggles = new ConcurrentHashMap<>();
|
||||
|
||||
// Verbose targets (per-player debug output)
|
||||
private final Set<UUID> verboseTargets = ConcurrentHashMap.newKeySet();
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
instance = this;
|
||||
|
||||
// Check for ProtocolLib
|
||||
checkProtocolLib();
|
||||
|
||||
// Initialize managers
|
||||
initializeManagers();
|
||||
|
||||
// Register listeners
|
||||
registerListeners();
|
||||
|
||||
// Register commands
|
||||
registerCommands();
|
||||
|
||||
// Register checks
|
||||
registerChecks();
|
||||
|
||||
// Start decay task
|
||||
startDecayTask();
|
||||
|
||||
// Start potion effect refresh task
|
||||
startPotionRefreshTask();
|
||||
|
||||
// Start TimerCheck blink detection task
|
||||
startTimerBlinkTask();
|
||||
|
||||
getLogger().info("XeroAntiCheat v" + getDescription().getVersion() + " enabled!");
|
||||
if (protocolLibLoaded) {
|
||||
getLogger().info("ProtocolLib detected - packet-level checks enabled");
|
||||
} else {
|
||||
getLogger().info("ProtocolLib not found - using event-based detection");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
// Cancel all tasks
|
||||
Bukkit.getScheduler().cancelTasks(this);
|
||||
|
||||
// Save any pending data
|
||||
if (violationManager != null) {
|
||||
violationManager.saveAll();
|
||||
}
|
||||
|
||||
// Close database
|
||||
if (databaseManager != null) {
|
||||
databaseManager.close();
|
||||
}
|
||||
|
||||
getLogger().info("XeroAntiCheat disabled!");
|
||||
}
|
||||
|
||||
private void checkProtocolLib() {
|
||||
try {
|
||||
Class.forName("com.comphenix.protocol.ProtocolLibrary");
|
||||
protocolLibLoaded = true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
protocolLibLoaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeManagers() {
|
||||
configManager = new ConfigManager(this);
|
||||
configManager.loadConfig();
|
||||
|
||||
violationManager = new ViolationManager(this);
|
||||
punishmentManager = new PunishmentManager(this, violationManager);
|
||||
checkManager = new CheckManager(this);
|
||||
|
||||
databaseManager = new DatabaseManager(this);
|
||||
databaseManager.initialize();
|
||||
}
|
||||
|
||||
private void registerListeners() {
|
||||
getServer().getPluginManager().registerEvents(new MovementListener(this), this);
|
||||
getServer().getPluginManager().registerEvents(new CombatListener(this), this);
|
||||
getServer().getPluginManager().registerEvents(new MiscListener(this), this);
|
||||
|
||||
if (protocolLibLoaded) {
|
||||
packetListener = new PacketListener(this);
|
||||
packetListener.register();
|
||||
}
|
||||
}
|
||||
|
||||
private void registerCommands() {
|
||||
getCommand("xac").setExecutor(new XACCommand(this));
|
||||
}
|
||||
|
||||
private void registerChecks() {
|
||||
// Movement checks
|
||||
checkManager.registerCheck(new SpeedCheck(this));
|
||||
checkManager.registerCheck(new FlyCheck(this));
|
||||
checkManager.registerCheck(new JesusCheck(this));
|
||||
checkManager.registerCheck(new NoFallCheck(this));
|
||||
checkManager.registerCheck(new TimerCheck(this));
|
||||
checkManager.registerCheck(new SpiderCheck(this));
|
||||
checkManager.registerCheck(new GlideCheck(this));
|
||||
checkManager.registerCheck(new PhaseCheck(this));
|
||||
|
||||
// Combat checks
|
||||
checkManager.registerCheck(new KillAuraCheck(this));
|
||||
checkManager.registerCheck(new ReachCheck(this));
|
||||
checkManager.registerCheck(new CriticalCheck(this));
|
||||
checkManager.registerCheck(new AutoClickerCheck(this));
|
||||
|
||||
// VelocityCheck requires ProtocolLib
|
||||
if (protocolLibLoaded) {
|
||||
checkManager.registerCheck(new VelocityCheck(this));
|
||||
}
|
||||
|
||||
// Misc checks
|
||||
checkManager.registerCheck(new FastPlaceCheck(this));
|
||||
checkManager.registerCheck(new ScaffoldCheck(this));
|
||||
checkManager.registerCheck(new FastEatCheck(this));
|
||||
checkManager.registerCheck(new InventoryMoveCheck(this));
|
||||
|
||||
getLogger().info("Registered " + checkManager.getRegisteredChecks().size() + " checks");
|
||||
}
|
||||
|
||||
private void startDecayTask() {
|
||||
int interval = configManager.getInt("violation.decay_interval", 30) * 20;
|
||||
Bukkit.getScheduler().runTaskTimerAsynchronously(this, () -> {
|
||||
violationManager.decayAll();
|
||||
}, interval, interval);
|
||||
}
|
||||
|
||||
private void startPotionRefreshTask() {
|
||||
Bukkit.getScheduler().runTaskTimer(this, () -> {
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
PlayerData data = violationManager.getPlayerData(player);
|
||||
if (data == null) continue;
|
||||
|
||||
data.setHasSpeedEffect(player.hasPotionEffect(PotionEffectType.SPEED));
|
||||
data.setHasSlownessEffect(player.hasPotionEffect(PotionEffectType.SLOWNESS));
|
||||
data.setHasLevitation(player.hasPotionEffect(PotionEffectType.LEVITATION));
|
||||
data.setHasDolphinsGrace(player.hasPotionEffect(PotionEffectType.DOLPHINS_GRACE));
|
||||
data.setHasJumpBoost(player.hasPotionEffect(PotionEffectType.JUMP_BOOST));
|
||||
data.setHasSlowFalling(player.hasPotionEffect(PotionEffectType.SLOW_FALLING));
|
||||
|
||||
var speed = player.getPotionEffect(PotionEffectType.SPEED);
|
||||
data.setSpeedLevel(speed != null ? speed.getAmplifier() + 1 : 0);
|
||||
|
||||
var slowness = player.getPotionEffect(PotionEffectType.SLOWNESS);
|
||||
data.setSlownessLevel(slowness != null ? slowness.getAmplifier() + 1 : 0);
|
||||
|
||||
var jump = player.getPotionEffect(PotionEffectType.JUMP_BOOST);
|
||||
data.setJumpBoostLevel(jump != null ? jump.getAmplifier() + 1 : 0);
|
||||
}
|
||||
}, 10L, 10L);
|
||||
}
|
||||
|
||||
private void startTimerBlinkTask() {
|
||||
Bukkit.getScheduler().runTaskTimer(this, () -> {
|
||||
long now = System.currentTimeMillis();
|
||||
long threshold = configManager.getInt("checks.timer.blink_threshold_ms", 500);
|
||||
Check timerCheck = checkManager.getCheck("Timer");
|
||||
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
if (timerCheck != null && timerCheck.isBypassed(player)) continue;
|
||||
PlayerData data = violationManager.getPlayerData(player);
|
||||
if (data == null || data.getLastMovePacketTime() == 0) continue;
|
||||
|
||||
long gap = now - data.getLastMovePacketTime();
|
||||
if (gap > threshold) {
|
||||
violationManager.addViolation(player, "Timer", 2.0);
|
||||
punishmentManager.evaluate(player, "Timer");
|
||||
data.setLastMovePacketTime(now);
|
||||
}
|
||||
}
|
||||
}, 5L, 5L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload the plugin configuration and re-register checks
|
||||
*/
|
||||
public void reload() {
|
||||
configManager.loadConfig();
|
||||
violationManager.clearAll();
|
||||
getLogger().info("Configuration reloaded!");
|
||||
}
|
||||
|
||||
// Getters
|
||||
public static XeroAntiCheat getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public ConfigManager getConfigManager() {
|
||||
return configManager;
|
||||
}
|
||||
|
||||
public ViolationManager getViolationManager() {
|
||||
return violationManager;
|
||||
}
|
||||
|
||||
public PunishmentManager getPunishmentManager() {
|
||||
return punishmentManager;
|
||||
}
|
||||
|
||||
public CheckManager getCheckManager() {
|
||||
return checkManager;
|
||||
}
|
||||
|
||||
public DatabaseManager getDatabaseManager() {
|
||||
return databaseManager;
|
||||
}
|
||||
|
||||
public boolean isProtocolLibLoaded() {
|
||||
return protocolLibLoaded;
|
||||
}
|
||||
|
||||
public boolean isAlertsEnabled(java.util.UUID uuid) {
|
||||
return alertToggles.getOrDefault(uuid, true);
|
||||
}
|
||||
|
||||
public void setAlertsEnabled(java.util.UUID uuid, boolean enabled) {
|
||||
alertToggles.put(uuid, enabled);
|
||||
}
|
||||
|
||||
public boolean isVerboseTarget(UUID uuid) {
|
||||
return verboseTargets.contains(uuid);
|
||||
}
|
||||
|
||||
public void toggleVerboseTarget(UUID uuid) {
|
||||
if (!verboseTargets.remove(uuid)) {
|
||||
verboseTargets.add(uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user