diff --git a/src/fr/neatmonster/nocheatplus/NoCheatPlus.java b/src/fr/neatmonster/nocheatplus/NoCheatPlus.java index 0af5b233..e2594ecb 100644 --- a/src/fr/neatmonster/nocheatplus/NoCheatPlus.java +++ b/src/fr/neatmonster/nocheatplus/NoCheatPlus.java @@ -239,6 +239,7 @@ public class NoCheatPlus extends JavaPlugin implements Listener { new BlockPlaceListener(), new ChatListener(), new CombinedListener(), + // Do ming registration order: Combined must come before Fight. new FightListener(), new InventoryListener(), new MovingListener(), diff --git a/src/fr/neatmonster/nocheatplus/checks/combined/CombinedConfig.java b/src/fr/neatmonster/nocheatplus/checks/combined/CombinedConfig.java index 17614251..38193f0c 100644 --- a/src/fr/neatmonster/nocheatplus/checks/combined/CombinedConfig.java +++ b/src/fr/neatmonster/nocheatplus/checks/combined/CombinedConfig.java @@ -1,9 +1,14 @@ package fr.neatmonster.nocheatplus.checks.combined; +import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; +import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import fr.neatmonster.nocheatplus.actions.ActionList; import fr.neatmonster.nocheatplus.checks.CheckType; @@ -14,6 +19,7 @@ import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfigFile; import fr.neatmonster.nocheatplus.config.ConfigManager; import fr.neatmonster.nocheatplus.players.Permissions; +import fr.neatmonster.nocheatplus.utilities.CheckUtils; public class CombinedConfig extends ACheckConfig { @@ -37,20 +43,61 @@ public class CombinedConfig extends ACheckConfig { return cc; } - /** Do mind that this flag is not used by all compinents. */ - public final boolean improbableCheck; - public final float improbableLevel; - public final ActionList improbableActions; + /** Do mind that this flag is not used by all components. */ + public final boolean improbableCheck; + public final float improbableLevel; + public final ActionList improbableActions; + + // Invulnerable management. + public final boolean invulnerableCheck; + public final int invulnerableInitialTicksJoin; + public final Set invulnerableIgnore = new HashSet(); + public final Map invulnerableModifiers = new HashMap(); + public final int invulnerableModifierDefault; // Last yaw tracking - public final float yawRate; - public final boolean yawRateImprobable; + public final float yawRate; + public final boolean yawRateImprobable; public CombinedConfig(final ConfigFile config) { improbableCheck = config.getBoolean(ConfPaths.COMBINED_IMPROBABLE_CHECK, false); improbableLevel = (float) config.getDouble(ConfPaths.COMBINED_IMPROBABLE_LEVEL, 300); improbableActions = config.getActionList(ConfPaths.COMBINED_IMPROBABLE_ACTIONS, Permissions.COMBINED_IMPROBABLE); + invulnerableCheck = config.getBoolean(ConfPaths.COMBINED_INVULNERABLE_CHECK); + invulnerableInitialTicksJoin = config.getInt(ConfPaths.COMBINED_INVULNERABLE_INITIALTICKS_JOIN); + boolean error = false; + // Read ignored causes. + for (final String input : config.getStringList(ConfPaths.COMBINED_INVULNERABLE_IGNORE)){ + final String normInput = input.trim().toUpperCase(); + try{ + invulnerableIgnore.add(DamageCause.valueOf(normInput.replace(' ', '_').replace('-', '_'))); + } + catch (final Exception e){ + error = true; + CheckUtils.logWarning("[NoCheatPlus] Bad damage cause (combined.invulnerable.ignore): " + input); + } + } + // Read modifiers for causes. + Integer defaultMod = 0; + final ConfigurationSection sec = config.getConfigurationSection(ConfPaths.COMBINED_INVULNERABLE_MODIFIERS); + for (final String input : sec.getKeys(false)){ + final int modifier = sec.getInt(input, 0); + final String normInput = input.trim().toUpperCase(); + if (normInput.equals("ALL")){ + defaultMod = modifier; + continue; + } + try{ + invulnerableModifiers.put(DamageCause.valueOf(normInput.replace(' ', '_').replace('-', '_')), modifier); + } + catch (final Exception e){ + error = true; + CheckUtils.logWarning("[NoCheatPlus] Bad damage cause (combined.invulnerable.modifiers): " + input); + } + } + invulnerableModifierDefault = defaultMod; + if (error) CheckUtils.logInfo("[NoCheatPlus] Damage causes can be: " + CheckUtils.join(Arrays.asList(DamageCause.values()), ", ")); yawRate = config.getInt(ConfPaths.COMBINED_YAWRATE_RATE); yawRateImprobable = config.getBoolean(ConfPaths.COMBINED_YAWRATE_IMPROBABLE); } diff --git a/src/fr/neatmonster/nocheatplus/checks/combined/CombinedData.java b/src/fr/neatmonster/nocheatplus/checks/combined/CombinedData.java index e360a76b..89a7174e 100644 --- a/src/fr/neatmonster/nocheatplus/checks/combined/CombinedData.java +++ b/src/fr/neatmonster/nocheatplus/checks/combined/CombinedData.java @@ -50,22 +50,28 @@ public class CombinedData extends ACheckData { playersMap.clear(); } + // VLs public double improbableVL = 0; + // Invulnerable management: + /** This is the tick from which on the player is vulnerable again. */ + public int invulnerableTick = Integer.MIN_VALUE; + + // Yawrate check. public float lastYaw; public long lastYawTime; public final ActionFrequency yawFreq = new ActionFrequency(3, 333); - + + // General penalty time (used for fighting mainly, set by yawrate check). public long timeFreeze = 0; + // Improbable check public final ActionFrequency improbableCount = new ActionFrequency(20, 3000); + // General data public String lastWorld = ""; - public long lastJoinTime; - public long lastLogoutTime; - public long lastMoveTime; public CombinedData(final Player player){ diff --git a/src/fr/neatmonster/nocheatplus/checks/combined/CombinedListener.java b/src/fr/neatmonster/nocheatplus/checks/combined/CombinedListener.java index 50416ef1..12470510 100644 --- a/src/fr/neatmonster/nocheatplus/checks/combined/CombinedListener.java +++ b/src/fr/neatmonster/nocheatplus/checks/combined/CombinedListener.java @@ -1,16 +1,25 @@ package fr.neatmonster.nocheatplus.checks.combined; +import net.minecraft.server.EntityPlayer; + import org.bukkit.Location; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerToggleSneakEvent; import org.bukkit.event.player.PlayerToggleSprintEvent; +import fr.neatmonster.nocheatplus.utilities.TickTask; + /** - * + * GarbageCollectior class to combine some things, make available for other checks, or just because they don't fit into another section. * @author mc_dev * */ @@ -47,5 +56,48 @@ public class CombinedListener implements Listener { Combined.feedYawRate(player, loc.getYaw(), now, worldName, data); } - // (possibly other types of events, but these combine with fighting). + /** + * We listen to this event to prevent players from leaving while falling, so from avoiding fall damages. + * + * @param event + * the event + */ + @EventHandler( + priority = EventPriority.LOWEST) + public void onPlayerJoin(final PlayerJoinEvent event) { + + // TODO: EventPriority + + final Player player = event.getPlayer(); + final CombinedData data = CombinedData.getData(player); + final CombinedConfig cc = CombinedConfig.getConfig(player); + + if (cc.invulnerableCheck){ + // TODO: maybe allow to set a different number of ticks ! + final EntityPlayer mcPlayer= ((CraftPlayer) player).getHandle(); + final int ticks = cc.invulnerableInitialTicksJoin >= 0 ? cc.invulnerableInitialTicksJoin : mcPlayer.invulnerableTicks; + data.invulnerableTick = TickTask.getTick() + ticks; + mcPlayer.invulnerableTicks = 0; + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = false) + public void onEntityDamage(final EntityDamageEvent event){ + final Entity entity = event.getEntity(); + if (!(entity instanceof Player)) return; + final Player player = (Player) entity; + final CombinedConfig cc = CombinedConfig.getConfig(player); + if (!cc.invulnerableCheck) return; + final DamageCause cause = event.getCause(); + // Ignored causes. + if (cc.invulnerableIgnore.contains(cause)) return; + // Modified invulnerable ticks. + Integer modifier = cc.invulnerableModifiers.get(cause); + if (modifier == null) modifier = cc.invulnerableModifierDefault; + final CombinedData data = CombinedData.getData(player); + if (TickTask.getTick() >= data.invulnerableTick + modifier.intValue()) return; + // Still invulnerable. + event.setCancelled(true); + } + } diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java b/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java index 94328d34..288e75f7 100644 --- a/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java +++ b/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java @@ -17,7 +17,6 @@ import org.bukkit.event.player.PlayerBedLeaveEvent; import org.bukkit.event.player.PlayerChangedWorldEvent; import org.bukkit.event.player.PlayerGameModeChangeEvent; import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerPortalEvent; import org.bukkit.event.player.PlayerRespawnEvent; @@ -274,32 +273,6 @@ public class MovingListener implements Listener { event.setCancelled(true); } - /** - * We listen to this event to prevent players from leaving while falling, so from avoiding fall damages. - * - * @param event - * the event - */ - @EventHandler( - priority = EventPriority.MONITOR) - public void onPlayerJoin(final PlayerJoinEvent event) { - /* - * ____ _ _ _ - * | _ \| | __ _ _ _ ___ _ __ | | ___ (_)_ __ - * | |_) | |/ _` | | | |/ _ \ '__| _ | |/ _ \| | '_ \ - * | __/| | (_| | |_| | __/ | | |_| | (_) | | | | | - * |_| |_|\__,_|\__, |\___|_| \___/ \___/|_|_| |_| - * |___/ - */ - final Player player = event.getPlayer(); - final MovingData data = MovingData.getData(player); - - // If the player has joined in the air and a previous location is defined... - if (player.getLocation().add(0D, -1D, 0D).getBlock().getType() == Material.AIR && data.ground != null) - // ...teleport him there. - player.teleport(data.ground); - } - /** * When a player moves, he will be checked for various suspicious behaviors. * diff --git a/src/fr/neatmonster/nocheatplus/config/ConfPaths.java b/src/fr/neatmonster/nocheatplus/config/ConfPaths.java index 5cf182fd..d2a7af93 100644 --- a/src/fr/neatmonster/nocheatplus/config/ConfPaths.java +++ b/src/fr/neatmonster/nocheatplus/config/ConfPaths.java @@ -304,6 +304,14 @@ public abstract class ConfPaths { public static final String COMBINED_IMPROBABLE_ACTIONS = COMBINED_IMPROBABLE + "actions"; + private static final String COMBINED_INVULNERABLE = COMBINED + "invulnerable."; + public static final String COMBINED_INVULNERABLE_CHECK = COMBINED_INVULNERABLE + "active"; + private static final String COMBINED_INVULNERABLE_INITIALTICKS = COMBINED_INVULNERABLE + "initialticks."; + public static final String COMBINED_INVULNERABLE_INITIALTICKS_JOIN = COMBINED_INVULNERABLE_INITIALTICKS + "join"; + public static final String COMBINED_INVULNERABLE_IGNORE = COMBINED_INVULNERABLE + "ignore"; + public static final String COMBINED_INVULNERABLE_MODIFIERS = COMBINED_INVULNERABLE + "modifiers"; + + private static final String COMBINED_YAWRATE = COMBINED + "yawrate."; public static final String COMBINED_YAWRATE_RATE = COMBINED_YAWRATE + "rate"; public static final String COMBINED_YAWRATE_IMPROBABLE = COMBINED_YAWRATE + "improbable"; @@ -470,5 +478,4 @@ public abstract class ConfPaths { * "8",P" */ public static final String STRINGS = "strings"; - } diff --git a/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java b/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java index f638ebdc..bd322b68 100644 --- a/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java +++ b/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java @@ -233,6 +233,12 @@ public class DefaultConfig extends ConfigFile { // set(ConfPaths.COMBINED_IMPROBABLE_FASTBREAK_CHECK, false); set(ConfPaths.COMBINED_IMPROBABLE_ACTIONS, "cancel log:improbable:2:8:if"); + + set(ConfPaths.COMBINED_INVULNERABLE_CHECK, true); + set(ConfPaths.COMBINED_INVULNERABLE_INITIALTICKS_JOIN, -1); + set(ConfPaths.COMBINED_INVULNERABLE_IGNORE, new LinkedList(Arrays.asList(new String[]{"FALL"}))); + set(ConfPaths.COMBINED_INVULNERABLE_MODIFIERS + ".all", 0); + set(ConfPaths.COMBINED_YAWRATE_RATE , 380); set(ConfPaths.COMBINED_YAWRATE_IMPROBABLE, true); diff --git a/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java b/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java index 68d0f868..71482270 100644 --- a/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java +++ b/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java @@ -237,7 +237,9 @@ public class PlayerLocation { // // TODO: maybe make an auxiliary method in BlockProperties (can stand on ? id, boundY) // if (y < 0) y += 1D; // final int id = getTypeId(); +// final int idBelow = getTypeIdBelow(); // if (y >= 0.5 && BlockProperties.isStairs(id)) onGround = true; +// else if (y <= 0.002 && BlockProperties.isStairs(idBelow)) onGround = true; // } return onGround; }