diff --git a/src/fr/neatmonster/nocheatplus/CommandHandler.java b/src/fr/neatmonster/nocheatplus/CommandHandler.java index e433ae6a..0ce20b65 100644 --- a/src/fr/neatmonster/nocheatplus/CommandHandler.java +++ b/src/fr/neatmonster/nocheatplus/CommandHandler.java @@ -8,6 +8,8 @@ import org.bukkit.entity.Player; import fr.neatmonster.nocheatplus.checks.blockbreak.BlockBreakConfig; import fr.neatmonster.nocheatplus.checks.blockplace.BlockPlaceConfig; +import fr.neatmonster.nocheatplus.checks.chat.ChatConfig; +import fr.neatmonster.nocheatplus.checks.fight.FightConfig; import fr.neatmonster.nocheatplus.checks.moving.MovingConfig; import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfigManager; @@ -63,6 +65,8 @@ public class CommandHandler implements CommandExecutor { ConfigManager.init(plugin); BlockBreakConfig.clear(); BlockPlaceConfig.clear(); + ChatConfig.clear(); + FightConfig.clear(); MovingConfig.clear(); sender.sendMessage(ChatColor.RED + "NCP: " + ChatColor.WHITE + "Configuration reloaded!"); diff --git a/src/fr/neatmonster/nocheatplus/NoCheatPlus.java b/src/fr/neatmonster/nocheatplus/NoCheatPlus.java index e6e13851..b6dc52b7 100644 --- a/src/fr/neatmonster/nocheatplus/NoCheatPlus.java +++ b/src/fr/neatmonster/nocheatplus/NoCheatPlus.java @@ -16,6 +16,7 @@ import fr.neatmonster.nocheatplus.checks.Workarounds; import fr.neatmonster.nocheatplus.checks.blockbreak.BlockBreakListener; import fr.neatmonster.nocheatplus.checks.blockplace.BlockPlaceListener; import fr.neatmonster.nocheatplus.checks.chat.ChatListener; +import fr.neatmonster.nocheatplus.checks.fight.FightListener; import fr.neatmonster.nocheatplus.checks.moving.MovingListener; import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfigManager; @@ -72,6 +73,7 @@ public class NoCheatPlus extends JavaPlugin implements Listener { listeners.add(new BlockBreakListener()); listeners.add(new BlockPlaceListener()); listeners.add(new ChatListener()); + listeners.add(new FightListener()); listeners.add(new MovingListener()); listeners.add(new Workarounds()); diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/Critical.java b/src/fr/neatmonster/nocheatplus/checks/fight/Critical.java new file mode 100644 index 00000000..e2a0a101 --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/fight/Critical.java @@ -0,0 +1,88 @@ +package fr.neatmonster.nocheatplus.checks.fight; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffectType; + +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; +import fr.neatmonster.nocheatplus.utilities.LagMeasureTask; +import fr.neatmonster.nocheatplus.utilities.PlayerLocation; + +/* + * MM'""""'YMM oo dP oo dP + * M' .mmm. `M 88 88 + * M MMMMMooM 88d888b. dP d8888P dP .d8888b. .d8888b. 88 + * M MMMMMMMM 88' `88 88 88 88 88' `"" 88' `88 88 + * M. `MMM' .M 88 88 88 88 88. ... 88. .88 88 + * MM. .dM dP dP dP dP `88888P' `88888P8 dP + * MMMMMMMMMMM + */ +/** + * A check used to verify that critical hits done by players are legit. + */ +public class Critical extends Check { + + public class CriticalEvent extends CheckEvent { + + public CriticalEvent(final Player player) { + super(player); + } + } + + public boolean check(final Player player) { + final FightConfig cc = FightConfig.getConfig(player); + final FightData data = FightData.getData(player); + + boolean cancel = false; + + // We'll need the PlayerLocation to know some important stuff. + final PlayerLocation location = new PlayerLocation(player.getLocation(), player); + + // Check if the hit was a critical hit (positive fall distance, entity in the air, not on ladder, not in liquid + // and without blindness effect). + if (player.getFallDistance() > 0f && !location.isOnGround() && !location.isOnLadder() && !location.isInLiquid() + && !player.hasPotionEffect(PotionEffectType.BLINDNESS)) + + // It was a critical hit, now check if the player has jumped or has sent a packet to mislead the server. + if (player.getFallDistance() < cc.criticalFallDistance + || Math.abs(player.getVelocity().getY()) < cc.criticalVelocity) { + final double deltaFallDistance = (cc.criticalFallDistance - player.getFallDistance()) + / cc.criticalFallDistance; + final double deltaVelocity = (cc.criticalVelocity - Math.abs(player.getVelocity().getY())) + / cc.criticalVelocity; + final double delta = deltaFallDistance > 0D ? deltaFallDistance + : 0D + deltaVelocity > 0D ? deltaVelocity : 0D; + + // Player failed the check, but this is influenced by lag so don't do it if there was lag. + if (!LagMeasureTask.skipCheck()) + // Increment the violation level. + data.criticalVL += delta; + + // Dispatch a critical event (API). + final CriticalEvent e = new CriticalEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Execute whatever actions are associated with this check and the violation level and find out if we + // should cancel the event. + cancel = !e.isCancelled() && executeActions(player, cc.criticalActions, data.criticalVL); + } + + return cancel; + } + + @Override + public String getParameter(final ParameterName wildcard, final Player player) { + if (wildcard == ParameterName.VIOLATIONS) + return String.valueOf(Math.round(FightData.getData(player).criticalVL)); + else + return super.getParameter(wildcard, player); + } + + @Override + protected boolean isEnabled(final Player player) { + return !player.hasPermission(Permissions.FIGHT_CRITICAL) && FightConfig.getConfig(player).criticalCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/FightConfig.java b/src/fr/neatmonster/nocheatplus/checks/fight/FightConfig.java index 182dc962..257d2592 100644 --- a/src/fr/neatmonster/nocheatplus/checks/fight/FightConfig.java +++ b/src/fr/neatmonster/nocheatplus/checks/fight/FightConfig.java @@ -55,6 +55,11 @@ public class FightConfig { public final int angleThreshold; public final ActionList angleActions; + public final boolean criticalCheck; + public final double criticalFallDistance; + public final double criticalVelocity; + public final ActionList criticalActions; + /** * Instantiates a new fight configuration. * @@ -65,5 +70,10 @@ public class FightConfig { angleCheck = data.getBoolean(ConfPaths.FIGHT_ANGLE_CHECK); angleThreshold = data.getInt(ConfPaths.FIGHT_ANGLE_THRESHOLD); angleActions = data.getActionList(ConfPaths.FIGHT_ANGLE_ACTIONS, Permissions.FIGHT_ANGLE); + + criticalCheck = data.getBoolean(ConfPaths.FIGHT_CRITICAL_CHECK); + criticalFallDistance = data.getDouble(ConfPaths.FIGHT_CRITICAL_FALLDISTANCE); + criticalVelocity = data.getDouble(ConfPaths.FIGHT_CRITICAL_VELOCITY); + criticalActions = data.getActionList(ConfPaths.FIGHT_CRITICAL_ACTIONS, Permissions.FIGHT_CRITICAL); } } diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/FightData.java b/src/fr/neatmonster/nocheatplus/checks/fight/FightData.java index da3a9bb2..2f795b0b 100644 --- a/src/fr/neatmonster/nocheatplus/checks/fight/FightData.java +++ b/src/fr/neatmonster/nocheatplus/checks/fight/FightData.java @@ -40,6 +40,7 @@ public class FightData { // Violation levels. public double angleVL; + public double criticalVL; // Data of the angle check. public TreeMap angleHits = new TreeMap(); diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/FightListener.java b/src/fr/neatmonster/nocheatplus/checks/fight/FightListener.java index d3f26994..1b05ad8b 100644 --- a/src/fr/neatmonster/nocheatplus/checks/fight/FightListener.java +++ b/src/fr/neatmonster/nocheatplus/checks/fight/FightListener.java @@ -1,5 +1,7 @@ package fr.neatmonster.nocheatplus.checks.fight; +import org.bukkit.event.Listener; + /* * MM""""""""`M oo dP dP M""MMMMMMMM oo dP * MM mmmmmmmM 88 88 M MMMMMMMM 88 @@ -13,6 +15,6 @@ package fr.neatmonster.nocheatplus.checks.fight; /** * Central location to listen to events that are relevant for the fight checks. */ -public class FightListener { +public class FightListener implements Listener { } diff --git a/src/fr/neatmonster/nocheatplus/config/ConfPaths.java b/src/fr/neatmonster/nocheatplus/config/ConfPaths.java index 6cc4f7b3..baf6c693 100644 --- a/src/fr/neatmonster/nocheatplus/config/ConfPaths.java +++ b/src/fr/neatmonster/nocheatplus/config/ConfPaths.java @@ -202,6 +202,12 @@ public abstract class ConfPaths { public static final String FIGHT_ANGLE_THRESHOLD = FIGHT_ANGLE + "threshold"; public static final String FIGHT_ANGLE_ACTIONS = FIGHT_ANGLE + "actions"; + private static final String FIGHT_CRITICAL = FIGHT + "critical."; + public static final String FIGHT_CRITICAL_CHECK = FIGHT_CRITICAL + "active"; + public static final String FIGHT_CRITICAL_FALLDISTANCE = FIGHT_CRITICAL + "falldistance"; + public static final String FIGHT_CRITICAL_VELOCITY = FIGHT_CRITICAL + "velocity"; + public static final String FIGHT_CRITICAL_ACTIONS = FIGHT_CRITICAL + "actions"; + /* * e e ,e, * d8b d8b e88 88e Y8b Y888P " 888 8e e88 888 diff --git a/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java b/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java index 083483f3..836fcf7a 100644 --- a/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java +++ b/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java @@ -181,6 +181,11 @@ public class DefaultConfig extends ConfigFile { set(ConfPaths.FIGHT_ANGLE_THRESHOLD, 50); set(ConfPaths.FIGHT_ANGLE_ACTIONS, "cancel vl>100 log:angle:3:5:f cancel vl>250 log:angle:0:5:cif cancel"); + set(ConfPaths.FIGHT_CRITICAL_CHECK, true); + set(ConfPaths.FIGHT_CRITICAL_FALLDISTANCE, 0.01D); + set(ConfPaths.FIGHT_CRITICAL_VELOCITY, 0.1D); + set(ConfPaths.FIGHT_CRITICAL_ACTIONS, "cancel vl>50 log:critical:0:5:cif cancel"); + /* * e e ,e, * d8b d8b e88 88e Y8b Y888P " 888 8e e88 888 @@ -243,6 +248,7 @@ public class DefaultConfig extends ConfigFile { set(ConfPaths.STRINGS + ".bpspeed", start + "tried to throw projectiles too quickly" + end); set(ConfPaths.STRINGS + ".breach", start + "tried to interact with a block over distance [reachdistance] block(s)" + end); + set(ConfPaths.STRINGS + ".critical", start + "tried to do a critical hit but wasn't technically jumping" + end); set(ConfPaths.STRINGS + ".fastbreak", start + "tried to break too much blocks" + end); set(ConfPaths.STRINGS + ".fastplace", start + "tried to place too much blocks" + end); set(ConfPaths.STRINGS + ".flyshort", start + "tried to move unexpectedly" + end); diff --git a/src/fr/neatmonster/nocheatplus/players/Permissions.java b/src/fr/neatmonster/nocheatplus/players/Permissions.java index 3e906872..414dfd3c 100644 --- a/src/fr/neatmonster/nocheatplus/players/Permissions.java +++ b/src/fr/neatmonster/nocheatplus/players/Permissions.java @@ -114,6 +114,7 @@ public class Permissions { */ private static final String FIGHT = CHECKS + ".fight"; public static final String FIGHT_ANGLE = FIGHT + ".angle"; + public static final String FIGHT_CRITICAL = FIGHT + ".critical"; /* * e e ,e,