From 9850a0e3bbe40520b8a7e0799d2c05aee5ff4490 Mon Sep 17 00:00:00 2001 From: asofold Date: Mon, 14 Jan 2013 18:49:49 +0100 Subject: [PATCH] [BLEEDING] Add simple hover check. --- .../checks/moving/MovingConfig.java | 10 ++ .../nocheatplus/checks/moving/MovingData.java | 4 + .../checks/moving/MovingListener.java | 124 +++++++++++++++++- .../checks/moving/SurvivalFly.java | 34 +++++ .../nocheatplus/config/ConfPaths.java | 6 + .../nocheatplus/config/DefaultConfig.java | 10 +- 6 files changed, 183 insertions(+), 5 deletions(-) diff --git a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingConfig.java b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingConfig.java index a500a305..0c45ac86 100644 --- a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingConfig.java +++ b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingConfig.java @@ -99,6 +99,11 @@ public class MovingConfig extends ACheckConfig { public final long survivalFlyVLFreeze; public final ActionList survivalFlyActions; + public final boolean sfHoverCheck; + public final int sfHoverTicks; + public final boolean sfHoverFallDamage; + public final double sfHoverViolation; + // Special tolerance values: public final double noFallyOnGround; public final double yOnGround; @@ -151,6 +156,11 @@ public class MovingConfig extends ACheckConfig { survivalFlyVLFreeze = data.getLong(ConfPaths.MOVING_SURVIVALFLY_VLFREEZE, 2000L); survivalFlyActions = data.getOptimizedActionList(ConfPaths.MOVING_SURVIVALFLY_ACTIONS, Permissions.MOVING_SURVIVALFLY); + sfHoverCheck = data.getBoolean(ConfPaths.MOVING_SURVIVALFLY_HOVER_CHECK); + sfHoverTicks = data.getInt(ConfPaths.MOVING_SURVIVALFLY_HOVER_TICKS); + sfHoverFallDamage = data.getBoolean(ConfPaths.MOVING_SURVIVALFLY_HOVER_FALLDAMAGE); + sfHoverViolation = data.getDouble(ConfPaths.MOVING_SURVIVALFLY_HOVER_SFVIOLATION); + yOnGround = data.getDouble(ConfPaths.MOVING_YONGROUND, 0.001, 2.0, 0.0626); // sqrt(1/256), see: NetServerHandler. noFallyOnGround = data.getDouble(ConfPaths.MOVING_NOFALL_YONGROUND, 0.001, 2.0, 0.3); // ystep is set to 0.45 by default, for stairs / steps. diff --git a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingData.java b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingData.java index 5072457e..738b67fd 100644 --- a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingData.java +++ b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingData.java @@ -127,6 +127,8 @@ public class MovingData extends ACheckData { * Last valid y distance covered by a move. Integer.MAX_VALUE indicates "not set". */ public double sfLastYDist = Double.MAX_VALUE; + /** A value <0 means not hovering at all. */ + public int sfHoverTicks = -1; public int sfFlyOnIce; public long sfCobwebTime; public double sfCobwebVL; @@ -157,6 +159,7 @@ public class MovingData extends ACheckData { clearNoFallData(); sfHorizontalBuffer = 0; toWasReset = fromWasReset = false; // TODO: true maybe + sfHoverTicks = -1; } /** @@ -182,6 +185,7 @@ public class MovingData extends ACheckData { // keep jump phase. sfHorizontalBuffer = Math.min(0, sfHorizontalBuffer); toWasReset = fromWasReset = false; // TODO: true maybe + sfHoverTicks = -1; } /** diff --git a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java index 52073268..0008770e 100644 --- a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java +++ b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java @@ -2,13 +2,16 @@ package fr.neatmonster.nocheatplus.checks.moving; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.Server; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.entity.Vehicle; @@ -42,6 +45,10 @@ import fr.neatmonster.nocheatplus.checks.combined.BedLeave; import fr.neatmonster.nocheatplus.checks.combined.Combined; import fr.neatmonster.nocheatplus.checks.combined.CombinedData; import fr.neatmonster.nocheatplus.compat.MCAccess; +import fr.neatmonster.nocheatplus.components.IData; +import fr.neatmonster.nocheatplus.components.IHaveCheckType; +import fr.neatmonster.nocheatplus.components.IRemoveData; +import fr.neatmonster.nocheatplus.components.TickListener; import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager; import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.utilities.BlockCache; @@ -73,7 +80,7 @@ import fr.neatmonster.nocheatplus.utilities.PlayerLocation; * * @see MovingEvent */ -public class MovingListener extends CheckListener{ +public class MovingListener extends CheckListener implements TickListener, IRemoveData, IHaveCheckType{ private static final class MoveInfo{ public final BlockCache cache; @@ -144,6 +151,8 @@ public class MovingListener extends CheckListener{ */ private final Map processingEvents = new HashMap(); + private final Set hoverTicks = new LinkedHashSet(30); + public MovingListener() { super(CheckType.MOVING); } @@ -351,7 +360,8 @@ public class MovingListener extends CheckListener{ final Player player = event.getPlayer(); // Store the event for monitor level checks. - processingEvents.put(player.getName(), event); + final String playerName = player.getName(); + processingEvents.put(playerName, event); // Ignore players in vehicles. if (player.isInsideVehicle()) return; @@ -445,6 +455,16 @@ public class MovingListener extends CheckListener{ && cc.survivalFlyCheck && !NCPExemptionManager.isExempted(player, CheckType.MOVING_SURVIVALFLY) && !player.hasPermission(Permissions.MOVING_SURVIVALFLY)){ // If he is handled by the survival fly check, execute it. newTo = survivalFly.check(player, pFrom, pTo, data, cc); + if (newTo == null){ + if (cc.sfHoverCheck && !data.toWasReset && !pTo.isOnGround()){ + // Start counting ticks. + hoverTicks.add(playerName); + data.sfHoverTicks = 0; + } + else{ + data.sfHoverTicks = -1; + } + } // Check NoFall if no reset is done. if (cc.noFallCheck && !NCPExemptionManager.isExempted(player, CheckType.MOVING_NOFALL) && !player.hasPermission(Permissions.MOVING_NOFALL)) { if (passableTo != null){ @@ -466,10 +486,15 @@ public class MovingListener extends CheckListener{ else if (cc.creativeFlyCheck && !NCPExemptionManager.isExempted(player, CheckType.MOVING_CREATIVEFLY)){ // If the player is handled by the creative fly check, execute it. newTo = creativeFly.check(player, pFrom, pTo, data, cc); + data.sfHoverTicks = -1; + } + else{ + data.clearFlyData(); } - else data.clearFlyData(); } - else data.clearFlyData(); + else{ + data.clearFlyData(); + } if (newTo == null && cc.morePacketsCheck && !NCPExemptionManager.isExempted(player, CheckType.MOVING_MOREPACKETS) && !player.hasPermission(Permissions.MOVING_MOREPACKETS)) { // If he hasn't been stopped by any other check and is handled by the more packets check, execute it. @@ -751,6 +776,7 @@ public class MovingListener extends CheckListener{ Combined.resetYawRate(player, ref.getYaw(), System.currentTimeMillis(), true); data.resetTeleported(); processingEvents.remove(player.getName()); + hoverTicks.remove(player.getName()); } /** @@ -924,6 +950,15 @@ public class MovingListener extends CheckListener{ // TODO: re-think: more fine grained reset? data.resetPositions(loc); } + // Reset hover ticks until a better method is used. + if (MovingConfig.getConfig(player).sfHoverCheck){ + // Start as if hovering already. + data.sfHoverTicks = 0; + hoverTicks.add(player.getName()); + } + else{ + data.sfHoverTicks = -1; + } } @EventHandler(priority = EventPriority.MONITOR) @@ -975,4 +1010,85 @@ public class MovingListener extends CheckListener{ public void onPlayerToggleSneak(final PlayerToggleSneakEvent event){ survivalFly.setReallySneaking(event.getPlayer(), event.isSneaking()); } + + @Override + public final void onTick(final int tick, final long timeLast) { + // Hover checks ! + if (hoverTicks.isEmpty()) return; // Seldom or not ? + final Server server = Bukkit.getServer(); + final MoveInfo info; + if (parkedInfo.isEmpty()) info = new MoveInfo(mcAccess); + else info = parkedInfo.remove(parkedInfo.size() - 1); + final List rem = new ArrayList(hoverTicks.size()); // Pessimistic. + for (final String playerName : hoverTicks){ + final Player player = server.getPlayerExact(playerName); + if (player == null || !player.isOnline()){ + rem.add(playerName); + continue; + } + final MovingData data = MovingData.getData(player); + if (data.sfHoverTicks < 0){ + rem.add(playerName); + continue; + } + if (checkHover(player, data, info)){ + rem.add(playerName); + } + } + parkedInfo.add(info); + hoverTicks.removeAll(rem); + rem.clear(); + } + + private final boolean checkHover(final Player player, final MovingData data, final MoveInfo info) { + final MovingConfig cc = MovingConfig.getConfig(player); + // Check if enabled at all. + if (!cc.sfHoverCheck) return true; + // Check if player is on ground. + final Location loc = player.getLocation(); + info.set(player, loc, null, cc.yOnGround); + final boolean res; + if (info.from.isOnGround() || info.from.isResetCond() || info.from.isAboveLadder() || info.from.isAboveStairs()){ + res = true; + } + else{ + data.sfHoverTicks ++; + if (data.sfHoverTicks > cc.sfHoverTicks){ + handleHoverViolation(player, loc, cc, data); + // Assume the player might still be hovering. + res = false; + data.sfHoverTicks = 0; + } + else res = false; + } + info.cleanup(); + return res; + } + + private final void handleHoverViolation(final Player player, final Location loc, final MovingConfig cc, final MovingData data) { + // Check nofall damage (!). + if (cc.sfHoverFallDamage && noFall.isEnabled(player)){ + // Consider adding 3/3.5 to fall distance if fall distance > 0? + noFall.checkDamage(player, data, loc.getY()); + } + // Delegate violation handling. + survivalFly.handleHoverViolation(player, loc, cc, data); + } + + @Override + public CheckType getCheckType() { + // TODO: this is for the hover check only... + return CheckType.MOVING_SURVIVALFLY; + } + + @Override + public IData removeData(String playerName) { + hoverTicks.remove(playerName); + return null; + } + + @Override + public void removeAllData() { + hoverTicks.clear(); + } } diff --git a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java index 58833e0b..7496c644 100644 --- a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java +++ b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java @@ -489,6 +489,40 @@ public class SurvivalFly extends Check { return null; } } + + protected final void handleHoverViolation(final Player player, final Location loc, final MovingConfig cc, final MovingData data) { + data.survivalFlyVL += cc.sfHoverViolation; + + // TODO: Extra options for set-back / kick, like vl? + data.sfVLTime = System.currentTimeMillis(); + final ViolationData vd = new ViolationData(this, player, data.survivalFlyVL, cc.sfHoverViolation, cc.survivalFlyActions); + if (vd.needsParameters()) { + vd.setParameter(ParameterName.LOCATION_FROM, String.format(Locale.US, "%.2f, %.2f, %.2f", loc.getX(), loc.getY(), loc.getZ())); + vd.setParameter(ParameterName.LOCATION_TO, "(HOVER)"); + vd.setParameter(ParameterName.DISTANCE, "0.0(HOVER)"); + vd.setParameter(ParameterName.TAGS, "hover"); + } + if (executeActions(vd)) { + // Set-back or kick. + if (data.hasSetBack()){ + data.clearAccounting(); + data.sfJumpPhase = 0; + data.sfLastYDist = Double.MAX_VALUE; + data.toWasReset = false; + data.fromWasReset = false; + player.teleport(data.getSetBack(loc)); + } + else{ + // Solve by extra actions ? Special case (probably never happens)? + player.kickPlayer("Hovering?"); + } + } + else{ + // Ignore. + } + } + + /** * First split-off. Not strictly accounting only, actually.
diff --git a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/config/ConfPaths.java b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/config/ConfPaths.java index ee5a91a2..58bd91ee 100644 --- a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/config/ConfPaths.java +++ b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/config/ConfPaths.java @@ -496,6 +496,12 @@ public abstract class ConfPaths { public static final String MOVING_SURVIVALFLY_EXTENDED_VACC = MOVING_SURVIVALFLY_EXTENDED + "vertical-accounting"; public static final String MOVING_SURVIVALFLY_VLFREEZE = MOVING_SURVIVALFLY + "vlfreeze"; public static final String MOVING_SURVIVALFLY_ACTIONS = MOVING_SURVIVALFLY + "actions"; + + private static final String MOVING_SURVIVALFLY_HOVER = MOVING_SURVIVALFLY + "hover."; + public static final String MOVING_SURVIVALFLY_HOVER_CHECK = MOVING_SURVIVALFLY_HOVER + "active"; + public static final String MOVING_SURVIVALFLY_HOVER_TICKS = MOVING_SURVIVALFLY_HOVER + "ticks"; + public static final String MOVING_SURVIVALFLY_HOVER_FALLDAMAGE = MOVING_SURVIVALFLY_HOVER + "falldamage"; + public static final String MOVING_SURVIVALFLY_HOVER_SFVIOLATION = MOVING_SURVIVALFLY_HOVER + "sfviolation"; // Special (to be sorted in or factored out). public static final String MOVING_NOFALL_YONGROUND = MOVING_NOFALL + "yonground"; diff --git a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/config/DefaultConfig.java b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/config/DefaultConfig.java index c73d8c3c..600e5493 100644 --- a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/config/DefaultConfig.java +++ b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/config/DefaultConfig.java @@ -25,7 +25,9 @@ public class DefaultConfig extends ConfigFile { * NCP build needed for this config. * (Should only increment with changing or removing paths.) */ - public static final int buildNumber = 314; + public static final int buildNumber = 315; // TODO: Check jenkins... + + // TODO: auto input full version or null to an extra variable or several [fail safe for other syntax checking]? /** * Instantiates a new default configuration. @@ -387,6 +389,12 @@ public class DefaultConfig extends ConfigFile { set(ConfPaths.MOVING_SURVIVALFLY_ACTIONS, "log:flyshort:3:5:f cancel vl>100 log:flyshort:0:5:if cancel vl>400 log:flylong:0:5:cif cancel vl>1000 log:flylong:0:5:cif cancel cmd:kickfly"); + // sf / hover check. + set(ConfPaths.MOVING_SURVIVALFLY_HOVER_CHECK, true); + set(ConfPaths.MOVING_SURVIVALFLY_HOVER_TICKS, 80); + set(ConfPaths.MOVING_SURVIVALFLY_HOVER_FALLDAMAGE, true); + set(ConfPaths.MOVING_SURVIVALFLY_HOVER_SFVIOLATION, 500); + /* * dP"8 d8 ,e, * C8b Y d88 888,8, " 888 8e e88 888 dP"Y