diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java index dd9fe9da..7efb1158 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java @@ -428,7 +428,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo // Fire move from -> to // (Special case: Location has not been updated last moving event.) moveInfo.set(player, from, to, cc.yOnGround); - checkPlayerMove(player, from, to, false, moveInfo, data, cc, event); + checkPlayerMove(player, from, to, 0, moveInfo, data, cc, event); } else { // Split into two moves. @@ -437,7 +437,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo debug(player, "Split move 1 (from -> loc):"); } moveInfo.set(player, from, loc, cc.yOnGround); - if (!checkPlayerMove(player, from, loc, true, moveInfo, data, cc, event) && processingEvents.containsKey(player.getName())) { + if (!checkPlayerMove(player, from, loc, 1, moveInfo, data, cc, event) && processingEvents.containsKey(player.getName())) { // Between -> set data accordingly (compare: onPlayerMoveMonitor). onMoveMonitorNotCancelled(player, from, loc, System.currentTimeMillis(), TickTask.getTick(), CombinedData.getData(player), data, cc); data.joinOrRespawn = false; @@ -446,7 +446,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo debug(player, "Split move 2 (loc -> to):"); } moveInfo.set(player, loc, to, cc.yOnGround); - checkPlayerMove(player, loc, to, false, moveInfo, data, cc, event); + checkPlayerMove(player, loc, to, 2, moveInfo, data, cc, event); } } // Cleanup. @@ -502,7 +502,9 @@ public class MovingListener extends CheckListener implements TickListener, IRemo * @param player * @param from * @param to - * @param mightBeMultipleMoves + * @param multiMoveCount + * 0: An ordinary move, not split. 1/2: first/second of a split + * move. * @param moveInfo * @param data * @param cc @@ -510,7 +512,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo * @return If cancelled/done, i.e. not to process further split moves. */ private boolean checkPlayerMove(final Player player, final Location from, final Location to, - final boolean mightBeMultipleMoves, final PlayerMoveInfo moveInfo, final MovingData data, final MovingConfig cc, + final int multiMoveCount, final PlayerMoveInfo moveInfo, final MovingData data, final MovingConfig cc, final PlayerMoveEvent event) { Location newTo = null; @@ -606,8 +608,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo // Set some data for this move. final PlayerMoveData thisMove = data.playerMoves.getCurrentMove(); thisMove.set(pFrom, pTo); - if (mightBeMultipleMoves) { - thisMove.mightBeMultipleMoves = true; + if (multiMoveCount > 0) { + thisMove.multiMoveCount = multiMoveCount; } final PlayerMoveData lastMove = data.playerMoves.getFirstPastMove(); @@ -766,7 +768,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo // Actual check. if (newTo == null) { // Only check if passable has not already set back. - newTo = survivalFly.check(player, pFrom, pTo, mightBeMultipleMoves, data, cc, tick, time, useBlockChangeTracker); + newTo = survivalFly.check(player, pFrom, pTo, multiMoveCount, data, cc, tick, time, useBlockChangeTracker); } // Only check NoFall, if not already vetoed. if (checkNf) { diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/magic/Magic.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/magic/Magic.java index 6feb0782..47d6fb2a 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/magic/Magic.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/magic/Magic.java @@ -280,7 +280,7 @@ public class Magic { public static boolean skipPaper(final PlayerMoveData thisMove, final PlayerMoveData lastMove, final MovingData data) { // TODO: Confine to from at block level (offset 0)? final double setBackYDistance = thisMove.to.getY() - data.getSetBackY(); - return !lastMove.toIsValid && data.sfJumpPhase == 0 && thisMove.mightBeMultipleMoves + return !lastMove.toIsValid && data.sfJumpPhase == 0 && thisMove.multiMoveCount > 0 && setBackYDistance > 0.0 && setBackYDistance < PAPER_DIST && thisMove.yDistance > 0.0 && thisMove.yDistance < PAPER_DIST && inAir(thisMove); } diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/model/PlayerMoveData.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/model/PlayerMoveData.java index fae75184..edc70d3e 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/model/PlayerMoveData.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/model/PlayerMoveData.java @@ -74,9 +74,10 @@ public class PlayerMoveData extends MoveData { /** * Due to the thresholds for moving events, there could have been other - * (micro-) moves by the player which could not be checked. + * (micro-) moves by the player which could not be checked. One moving event + * is split into two moves 1: from -> loc, 2: loc -> to. */ - public boolean mightBeMultipleMoves; + public int multiMoveCount; /** * Just the used vertical velocity. Could be overridden multiple times @@ -96,7 +97,7 @@ public class PlayerMoveData extends MoveData { // Meta stuff. flyCheck = CheckType.UNKNOWN; modelFlying = null; - mightBeMultipleMoves = false; + multiMoveCount = 0; verVelUsed = null; // Super class last, because it'll set valid to true in the end. super.resetBase(); diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/player/SurvivalFly.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/player/SurvivalFly.java index 20b0783e..83f9b353 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/player/SurvivalFly.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/player/SurvivalFly.java @@ -103,19 +103,21 @@ public class SurvivalFly extends Check { } /** - * Checks a player. * * @param player - * the player * @param from - * the from * @param to - * the to - * @param isSamePos - * @return the location + * @param multiMoveCount + * =: Ordinary, 1/2: first/second of a split move. + * @param data + * @param cc + * @param tick + * @param now + * @param useBlockChangeTracker + * @return */ public Location check(final Player player, final PlayerLocation from, final PlayerLocation to, - final boolean mightBeMultipleMoves, final MovingData data, final MovingConfig cc, + final int multiMoveCount, final MovingData data, final MovingConfig cc, final int tick, final long now, final boolean useBlockChangeTracker) { tags.clear(); if (data.debug) { @@ -247,7 +249,7 @@ public class SurvivalFly extends Check { // TODO: Always/never reset with any ground touched? data.resetVelocityJumpPhase(); } - else if (!mightBeMultipleMoves && thisMove.from.onGround && !lastMove.touchedGround + else if (multiMoveCount == 0 && thisMove.from.onGround && !lastMove.touchedGround && TrigUtil.isSamePosAndLook(thisMove.from, lastMove.to)) { // Ground somehow appeared out of thin air (block place). data.setSetBack(from); @@ -348,7 +350,10 @@ public class SurvivalFly extends Check { else { limitFCMH = 1.0; } - if (fcmh > limitFCMH && !data.isVelocityJumpPhase()) { // TODO: Configurable / adjust by medium type. + // TODO: Configurable / adjust by medium type. + // TODO: Instead of velocityJumpPhase account for friction directly? + // TODO: Fly-NoFly + bunny-water transitions pose issues. + if (fcmh > limitFCMH && !data.isVelocityJumpPhase()) { hDistanceAboveLimit = hDistance * (fcmh - limitFCMH); tags.add("hacc"); // Reset for now. @@ -444,7 +449,7 @@ public class SurvivalFly extends Check { } } else { - final double[] res = vDistAir(now, player, from, fromOnGround, resetFrom, to, toOnGround, resetTo, hDistanceAboveLimit, yDistance, mightBeMultipleMoves, lastMove, data, cc); + final double[] res = vDistAir(now, player, from, fromOnGround, resetFrom, to, toOnGround, resetTo, hDistanceAboveLimit, yDistance, multiMoveCount, lastMove, data, cc); vAllowedDistance = res[0]; vDistanceAboveLimit = res[1]; } @@ -978,7 +983,10 @@ public class SurvivalFly extends Check { * Core y-distance checks for in-air movement (may include air -> other). * @return */ - private double[] vDistAir(final long now, final Player player, final PlayerLocation from, final boolean fromOnGround, final boolean resetFrom, final PlayerLocation to, final boolean toOnGround, final boolean resetTo, final double hDistance, final double yDistance, final boolean mightBeMultipleMoves, final PlayerMoveData lastMove, final MovingData data, final MovingConfig cc) { + private double[] vDistAir(final long now, final Player player, final PlayerLocation from, + final boolean fromOnGround, final boolean resetFrom, final PlayerLocation to, + final boolean toOnGround, final boolean resetTo, final double hDistance, final double yDistance, + final int multiMoveCount, final PlayerMoveData lastMove, final MovingData data, final MovingConfig cc) { final PlayerMoveData thisMove = data.playerMoves.getCurrentMove(); // Y-distance for normal jumping, like in air. double vAllowedDistance = 0.0;