diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/FightConfig.java b/src/fr/neatmonster/nocheatplus/checks/fight/FightConfig.java index 4bd14e48..63741791 100644 --- a/src/fr/neatmonster/nocheatplus/checks/fight/FightConfig.java +++ b/src/fr/neatmonster/nocheatplus/checks/fight/FightConfig.java @@ -67,6 +67,9 @@ public class FightConfig { public final boolean godModeCheck; public final ActionList godModeActions; + public final boolean instantHealCheck; + public final ActionList instantHealActions; + /** * Instantiates a new fight configuration. * @@ -89,5 +92,8 @@ public class FightConfig { godModeCheck = data.getBoolean(ConfPaths.FIGHT_GODMODE_CHECK); godModeActions = data.getActionList(ConfPaths.FIGHT_GODMODE_ACTIONS, Permissions.FIGHT_GODMODE); + + instantHealCheck = data.getBoolean(ConfPaths.FIGHT_INSTANTHEAL_CHECK); + instantHealActions = data.getActionList(ConfPaths.FIGHT_INSTANTHEAL_ACTIONS, Permissions.FIGHT_INSTANTHEAL); } } diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/FightData.java b/src/fr/neatmonster/nocheatplus/checks/fight/FightData.java index 5c31825b..2de0169f 100644 --- a/src/fr/neatmonster/nocheatplus/checks/fight/FightData.java +++ b/src/fr/neatmonster/nocheatplus/checks/fight/FightData.java @@ -43,6 +43,7 @@ public class FightData { public double criticalVL; public double directionVL; public double godModeVL; + public double instantHealVL; // Data of the angle check. public TreeMap angleHits = new TreeMap(); @@ -55,4 +56,8 @@ public class FightData { public int godModeLastAge; public long godModeLastTime; + // Data of the instant heal check. + public int instantHealBuffer; + public long instantHealLastTime; + } diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/InstantHeal.java b/src/fr/neatmonster/nocheatplus/checks/fight/InstantHeal.java new file mode 100644 index 00000000..f2da0ee3 --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/fight/InstantHeal.java @@ -0,0 +1,110 @@ +package fr.neatmonster.nocheatplus.checks.fight; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; + +/* + * M""M dP dP M""MMMMM""MM dP + * M M 88 88 M MMMMM MM 88 + * M M 88d888b. .d8888b. d8888P .d8888b. 88d888b. d8888P M `M .d8888b. .d8888b. 88 + * M M 88' `88 Y8ooooo. 88 88' `88 88' `88 88 M MMMMM MM 88ooood8 88' `88 88 + * M M 88 88 88 88 88. .88 88 88 88 M MMMMM MM 88. ... 88. .88 88 + * M M dP dP `88888P' dP `88888P8 dP dP dP M MMMMM MM `88888P' `88888P8 dP + * MMMM MMMMMMMMMMMM + */ +/** + * The InstantHeal check should find out if a player tried to artificially accelerate the health regeneration by food. + */ +public class InstantHeal extends Check { + + /** + * The event triggered by this check. + */ + public class InstantHealEvent extends CheckEvent { + + /** + * Instantiates a new instant heal event. + * + * @param player + * the player + */ + public InstantHealEvent(final Player player) { + super(player); + } + } + + /** + * Check a player. + * + * @param player + * the player + * @return true, if successful + */ + public boolean check(final Player player) { + final FightConfig cc = FightConfig.getConfig(player); + final FightData data = FightData.getData(player); + + boolean cancel = false; + + // Security check if system time ran backwards. + if (data.instantHealLastTime > System.currentTimeMillis()) { + data.instantHealLastTime = 0L; + return false; + } + + final long delta = System.currentTimeMillis() - (data.instantHealLastTime + 3500L); + data.instantHealBuffer += delta; + + if (data.instantHealBuffer < 0) { + // Buffer has been fully consumed, increase the player's violation level; + data.instantHealVL -= data.instantHealBuffer / 1000D; + + // Reset the buffer. + data.instantHealBuffer = 0; + + // Dispatch an instant heal event (API). + final InstantHealEvent e = new InstantHealEvent(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.instantHealActions, data.instantHealVL); + } else + // Decrease the violation level. + data.instantHealVL *= 0.9D; + + // Buffer can't be bigger than 2 seconds. + if (data.instantHealBuffer > 2000) + data.instantHealBuffer = 2000; + + if (!cancel) + // New reference time. + data.instantHealLastTime = System.currentTimeMillis(); + + return cancel; + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player) + */ + @Override + public String getParameter(final ParameterName wildcard, final Player player) { + if (wildcard == ParameterName.VIOLATIONS) + return String.valueOf(Math.round(FightData.getData(player).instantHealVL)); + else + return super.getParameter(wildcard, player); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player) + */ + @Override + protected boolean isEnabled(final Player player) { + return !player.hasPermission(Permissions.FIGHT_INSTANTHEAL) && FightConfig.getConfig(player).instantHealCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/config/ConfPaths.java b/src/fr/neatmonster/nocheatplus/config/ConfPaths.java index 339a3692..575fc107 100644 --- a/src/fr/neatmonster/nocheatplus/config/ConfPaths.java +++ b/src/fr/neatmonster/nocheatplus/config/ConfPaths.java @@ -217,6 +217,10 @@ public abstract class ConfPaths { public static final String FIGHT_GODMODE_CHECK = FIGHT_GODMODE + "active"; public static final String FIGHT_GODMODE_ACTIONS = FIGHT_GODMODE + "actions"; + private static final String FIGHT_INSTANTHEAL = FIGHT + "instantheal."; + public static final String FIGHT_INSTANTHEAL_CHECK = FIGHT_INSTANTHEAL + "active"; + public static final String FIGHT_INSTANTHEAL_ACTIONS = FIGHT_INSTANTHEAL + "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 e6792d96..529494f1 100644 --- a/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java +++ b/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java @@ -194,6 +194,9 @@ public class DefaultConfig extends ConfigFile { set(ConfPaths.FIGHT_GODMODE_CHECK, true); set(ConfPaths.FIGHT_GODMODE_ACTIONS, "log:godmode:2:5:if cancel"); + set(ConfPaths.FIGHT_INSTANTHEAL_CHECK, true); + set(ConfPaths.FIGHT_INSTANTHEAL_ACTIONS, "log:instantheal:1:1:if cancel"); + /* * e e ,e, * d8b d8b e88 88e Y8b Y888P " 888 8e e88 888 @@ -264,6 +267,7 @@ public class DefaultConfig extends ConfigFile { set(ConfPaths.STRINGS + ".flylong", start + "tried to move from [locationfrom] to [locationto] over a distance of [distance] block(s)" + end); set(ConfPaths.STRINGS + ".godmode", start + "avoided taking damage or lagging" + end); + set(ConfPaths.STRINGS + ".instantheal", start + "tried to regenerate health faster than normal" + end); set(ConfPaths.STRINGS + ".kick", "kick [player]"); set(ConfPaths.STRINGS + ".morepackets", start + "sent [packets] more packet(s) than expected" + end); set(ConfPaths.STRINGS + ".nofall", start + "tried to avoid fall damage for ~[falldistance] block(s)" + end); diff --git a/src/fr/neatmonster/nocheatplus/players/Permissions.java b/src/fr/neatmonster/nocheatplus/players/Permissions.java index 8cdbc549..5bacbfe7 100644 --- a/src/fr/neatmonster/nocheatplus/players/Permissions.java +++ b/src/fr/neatmonster/nocheatplus/players/Permissions.java @@ -117,6 +117,7 @@ public class Permissions { public static final String FIGHT_CRITICAL = FIGHT + ".critical"; public static final String FIGHT_DIRECTION = FIGHT + ".direction"; public static final String FIGHT_GODMODE = FIGHT + ".godmode"; + public static final String FIGHT_INSTANTHEAL = FIGHT + "instantheal"; /* * e e ,e,