From e82f99bf9ce9f98406d66534774590edb5d80894 Mon Sep 17 00:00:00 2001 From: NeatMonster Date: Sun, 5 Aug 2012 15:17:41 +0200 Subject: [PATCH] [Development] GodMode check (re-)added. --- .../nocheatplus/checks/fight/FightConfig.java | 6 + .../nocheatplus/checks/fight/FightData.java | 7 + .../nocheatplus/checks/fight/GodMode.java | 156 ++++++++++++++++++ .../nocheatplus/config/ConfPaths.java | 4 + .../nocheatplus/config/DefaultConfig.java | 4 + .../nocheatplus/players/Permissions.java | 1 + 6 files changed, 178 insertions(+) create mode 100644 src/fr/neatmonster/nocheatplus/checks/fight/GodMode.java diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/FightConfig.java b/src/fr/neatmonster/nocheatplus/checks/fight/FightConfig.java index e4f41f28..4bd14e48 100644 --- a/src/fr/neatmonster/nocheatplus/checks/fight/FightConfig.java +++ b/src/fr/neatmonster/nocheatplus/checks/fight/FightConfig.java @@ -64,6 +64,9 @@ public class FightConfig { public final long directionPenalty; public final ActionList directionActions; + public final boolean godModeCheck; + public final ActionList godModeActions; + /** * Instantiates a new fight configuration. * @@ -83,5 +86,8 @@ public class FightConfig { directionCheck = data.getBoolean(ConfPaths.FIGHT_DIRECTION_CHECK); directionPenalty = data.getLong(ConfPaths.FIGHT_DIRECTION_PENALTY); directionActions = data.getActionList(ConfPaths.FIGHT_DIRECTION_ACTIONS, Permissions.FIGHT_DIRECTION); + + godModeCheck = data.getBoolean(ConfPaths.FIGHT_GODMODE_CHECK); + godModeActions = data.getActionList(ConfPaths.FIGHT_GODMODE_ACTIONS, Permissions.FIGHT_GODMODE); } } diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/FightData.java b/src/fr/neatmonster/nocheatplus/checks/fight/FightData.java index abdf68e5..5c31825b 100644 --- a/src/fr/neatmonster/nocheatplus/checks/fight/FightData.java +++ b/src/fr/neatmonster/nocheatplus/checks/fight/FightData.java @@ -42,10 +42,17 @@ public class FightData { public double angleVL; public double criticalVL; public double directionVL; + public double godModeVL; // Data of the angle check. public TreeMap angleHits = new TreeMap(); // Data of the direction check. public long directionLastViolationTime; + + // Data of the god mode check. + public int godModeBuffer; + public int godModeLastAge; + public long godModeLastTime; + } diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/GodMode.java b/src/fr/neatmonster/nocheatplus/checks/fight/GodMode.java new file mode 100644 index 00000000..bb227bb3 --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/fight/GodMode.java @@ -0,0 +1,156 @@ +package fr.neatmonster.nocheatplus.checks.fight; + +import net.minecraft.server.EntityPlayer; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.NoCheatPlus; +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; + +/* + * MM'"""""`MM dP M"""""`'"""`YM dP + * M' .mmm. `M 88 M mm. mm. M 88 + * M MMMMMMMM .d8888b. .d888b88 M MMM MMM M .d8888b. .d888b88 .d8888b. + * M MMM `M 88' `88 88' `88 M MMM MMM M 88' `88 88' `88 88ooood8 + * M. `MMM' .M 88. .88 88. .88 M MMM MMM M 88. .88 88. .88 88. ... + * MM. .MM `88888P' `88888P8 M MMM MMM M `88888P' `88888P8 `88888P' + * MMMMMMMMMMM MMMMMMMMMMMMMM + */ +/** + * The GodMode check will find out if a player tried to stay invulnerable after being hit or after dying. + */ +public class GodMode extends Check { + + /** + * The event triggered by this check. + */ + public class GodModeEvent extends CheckEvent { + + /** + * Instantiates a new god mode event. + * + * @param player + * the player + */ + public GodModeEvent(final Player player) { + super(player); + } + } + + /** + * Checks 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; + + // Check at most once a second. + if (data.godModeLastTime < System.currentTimeMillis() - 1000L) { + data.godModeLastTime = System.currentTimeMillis(); + + final int age = player.getTicksLived(); + + // How much older did he get? + final int ageDelta = Math.max(0, age - data.godModeLastAge); + + if (player.getNoDamageTicks() > 0 && ageDelta < 15) { + // He is invulnerable and didn't age fast enough, that costs some points. + data.godModeBuffer -= 15 - ageDelta; + + // Still points left? + if (data.godModeBuffer <= 0) { + // No, that means we can increase his violation level. + data.godModeVL -= data.godModeBuffer; + + // Dispatch a god mode event (API). + final GodModeEvent e = new GodModeEvent(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.godModeActions, data.godModeVL); + } + } else { + // Give some new points, once a second. + data.godModeBuffer += 15; + + // Decrease the violation level. + data.godModeVL *= 0.95; + } + + if (data.godModeBuffer < 0) + // Can't have less than 0! + data.godModeBuffer = 0; + else if (data.godModeBuffer > 30) + // And 30 is enough for simple lag situations. + data.godModeBuffer = 30; + + // Start age counting from a new time. + data.godModeLastAge = age; + } + + return cancel; + } + + /** + * If a player apparently died, make sure he really dies after some time if he didn't already, by setting up a + * Bukkit task. + * + * @param player + * the player + */ + public void death(final Player player) { + // First check if the player is really dead (e.g. another plugin could have just fired an artificial event). + if (player.getHealth() <= 0 && player.isDead()) + try { + final EntityPlayer entity = ((CraftPlayer) player).getHandle(); + + // Schedule a task to be executed in roughly 1.5 seconds. + final NoCheatPlus plugin = (NoCheatPlus) Bukkit.getPluginManager().getPlugin("NoCheatPlus"); + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { + + @Override + public void run() { + try { + // Check again if the player should be dead, and if the game didn't mark him as dead. + if (entity.getHealth() <= 0 && !entity.dead) { + // Artificially "kill" him. + entity.deathTicks = 19; + entity.g(); + } + } catch (final Exception e) {} + } + }, 30); + } catch (final Exception e) {} + } + + /* (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).godModeVL)); + 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_GODMODE) && FightConfig.getConfig(player).godModeCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/config/ConfPaths.java b/src/fr/neatmonster/nocheatplus/config/ConfPaths.java index 6371b440..339a3692 100644 --- a/src/fr/neatmonster/nocheatplus/config/ConfPaths.java +++ b/src/fr/neatmonster/nocheatplus/config/ConfPaths.java @@ -213,6 +213,10 @@ public abstract class ConfPaths { public static final String FIGHT_DIRECTION_PENALTY = FIGHT_DIRECTION + "penalty"; public static final String FIGHT_DIRECTION_ACTIONS = FIGHT_DIRECTION + "actions"; + private static final String FIGHT_GODMODE = FIGHT + "godmode."; + public static final String FIGHT_GODMODE_CHECK = FIGHT_GODMODE + "active"; + public static final String FIGHT_GODMODE_ACTIONS = FIGHT_GODMODE + "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 28383564..e6792d96 100644 --- a/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java +++ b/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java @@ -191,6 +191,9 @@ public class DefaultConfig extends ConfigFile { set(ConfPaths.FIGHT_DIRECTION_ACTIONS, "cancel vl>5 log:fdirection:3:5:f cancel vl>20 log:fdirection:0:5:if cancel vl>50 log:fdirection:0:5:cif cancel"); + set(ConfPaths.FIGHT_GODMODE_CHECK, true); + set(ConfPaths.FIGHT_GODMODE_ACTIONS, "log:godmode:2:5:if cancel"); + /* * e e ,e, * d8b d8b e88 88e Y8b Y888P " 888 8e e88 888 @@ -260,6 +263,7 @@ public class DefaultConfig extends ConfigFile { set(ConfPaths.STRINGS + ".flyshort", start + "tried to move unexpectedly" + end); 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 + ".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 3ec5649d..8cdbc549 100644 --- a/src/fr/neatmonster/nocheatplus/players/Permissions.java +++ b/src/fr/neatmonster/nocheatplus/players/Permissions.java @@ -116,6 +116,7 @@ public class Permissions { public static final String FIGHT_ANGLE = FIGHT + ".angle"; public static final String FIGHT_CRITICAL = FIGHT + ".critical"; public static final String FIGHT_DIRECTION = FIGHT + ".direction"; + public static final String FIGHT_GODMODE = FIGHT + ".godmode"; /* * e e ,e,