package com.xeroth.xeroanticheat.check; import com.xeroth.xeroanticheat.XeroAntiCheat; import com.xeroth.xeroanticheat.data.PlayerData; import org.bukkit.Bukkit; import org.bukkit.entity.Player; /** * Abstract base class for all anti-cheat checks. * All checks must extend this class and implement the check logic. */ public abstract class Check { protected final XeroAntiCheat plugin; protected final String name; protected final String configPath; private boolean enabled; public Check(XeroAntiCheat plugin, String name) { this.plugin = plugin; this.name = name; this.configPath = "checks." + name.toLowerCase() + "."; this.enabled = true; } /** * Execute the check logic. * * @param data Player data for the player being checked * @param player The player being checked */ public abstract void check(PlayerData data, Player player); /** * Called when the check detects a violation. * * @param data Player data * @param player The player * @param weight Violation weight to add */ protected void flag(PlayerData data, Player player, double weight) { if (!isEnabled()) return; if (player.hasPermission("xac.bypass")) return; if (player.hasPermission("xac.bypass." + getCategory())) return; if (player.hasPermission("xac.bypass." + name.toLowerCase())) return; plugin.getViolationManager().addViolation(player, name, weight); plugin.getPunishmentManager().evaluate(player, name); } /** * Simplified flag with default weight */ protected void flag(PlayerData data, Player player) { flag(data, player, 1.0); } /** * Get the check name */ public String getName() { return name; } /** * Check if this check is enabled */ public boolean isEnabled() { return enabled && plugin.getConfigManager().getBoolean(configPath + "enabled", true); } /** * Set enabled state */ public void setEnabled(boolean enabled) { this.enabled = enabled; } /** * Get a configuration value */ protected boolean getConfigBoolean(String key, boolean defaultValue) { return plugin.getConfigManager().getBoolean(configPath + key, defaultValue); } /** * Get a configuration value */ protected int getConfigInt(String key, int defaultValue) { return plugin.getConfigManager().getInt(configPath + key, defaultValue); } /** * Get a configuration value */ protected double getConfigDouble(String key, double defaultValue) { return plugin.getConfigManager().getDouble(configPath + key, defaultValue); } /** * Get a configuration value */ protected String getConfigString(String key, String defaultValue) { return plugin.getConfigManager().getString(configPath + key, defaultValue); } public String getCategory() { String pkg = getClass().getPackageName(); if (pkg.endsWith("movement")) return "movement"; if (pkg.endsWith("combat")) return "combat"; return "misc"; } /** * Returns true if the given player should be exempt from this check, * based on the three-tier bypass permission hierarchy: * xac.bypass → xac.bypass.<category> → xac.bypass.<checkname> * * @param player The player to test * @return true if the player has any applicable bypass permission */ public boolean isBypassed(Player player) { return player.hasPermission("xac.bypass") || player.hasPermission("xac.bypass." + getCategory()) || player.hasPermission("xac.bypass." + name.toLowerCase()); } protected void setback(Player player, PlayerData data) { if (!getConfigBoolean("setback", false)) return; org.bukkit.Location safe = data.getLastSafeLocation(); if (safe == null) return; data.clearPositionHistory(); player.teleport(safe); } protected boolean isServerLagging() { if (!plugin.getConfigManager().getBoolean("tps.enabled", true)) return false; double tps = Bukkit.getTPS()[0]; double minTps = plugin.getConfigManager().getDouble("tps.min_tps_threshold", 18.0); return tps < minTps; } }