diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/MovingConfig.java b/src/fr/neatmonster/nocheatplus/checks/moving/MovingConfig.java index f90186e2..be4538af 100644 --- a/src/fr/neatmonster/nocheatplus/checks/moving/MovingConfig.java +++ b/src/fr/neatmonster/nocheatplus/checks/moving/MovingConfig.java @@ -145,7 +145,7 @@ public class MovingConfig extends ACheckConfig { survivalFlyAccounting = data.getBoolean(ConfPaths.MOVING_SURVIVALFLY_ACCOUNTING); survivalFlyActions = data.getActionList(ConfPaths.MOVING_SURVIVALFLY_ACTIONS, Permissions.MOVING_SURVIVALFLY); - yOnGround = data.getDouble(ConfPaths.MOVING_YONGROUND, 0.001, 2.0, 0.001); + 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 = data.getDouble(ConfPaths.MOVING_SURVIVALFLY_YSTEP, 0.001, 0.49, 0.1); } diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/MovingData.java b/src/fr/neatmonster/nocheatplus/checks/moving/MovingData.java index 6938983a..3e78ac14 100644 --- a/src/fr/neatmonster/nocheatplus/checks/moving/MovingData.java +++ b/src/fr/neatmonster/nocheatplus/checks/moving/MovingData.java @@ -115,6 +115,8 @@ public class MovingData extends ACheckData { // Data of the survival fly check. public int survivalFlyJumpPhase; public double survivalFlyLastFromY; + /** Last valid y distance covered by a move. Integer.MAX_VALUE indicates "not set". */ + public double survivalFlyLastYDist = Integer.MAX_VALUE; public int survivalFlyOnIce; public boolean survivalFlyWasInBed; public long survivalFlyCobwebTime; @@ -140,6 +142,7 @@ public class MovingData extends ACheckData { bunnyhopDelay = 0; survivalFlyJumpPhase = 0; setBack = null; + survivalFlyLastYDist = Integer.MAX_VALUE; clearAccounting(); clearNoFallData(); } diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java b/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java index 33db9fc7..3998c5af 100644 --- a/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java +++ b/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java @@ -356,8 +356,10 @@ public class MovingListener implements Listener { // Counter has run out, now reduce the vertical freedom over time. data.verticalFreedom *= 0.93D; - if (pFrom.isOnGround()) + if (pFrom.isOnGround()){ data.ground = from; // pFrom.getLocation(); + data.survivalFlyLastFromY = Integer.MAX_VALUE; + } Location newTo = null; diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java b/src/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java index 8adee862..10942255 100644 --- a/src/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java +++ b/src/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java @@ -112,11 +112,17 @@ public class SurvivalFly extends Check { final double setBackYDistance = to.getY() - data.setBack.getY(); // If the player has touched the ground but it hasn't been noticed by the plugin, the workaround is here. - if (!fromOnGround){ + if (!fromOnGround && !from.isInWeb()){ // TODO: more precise - final boolean inconsistent = from.getY() < data.survivalFlyLastFromY && yDistance > 0D && yDistance < 0.5D + // TODO: account for all near ground positions, use as fallback some counter if player.getLocation.getY is < from.getY +// final boolean inconsistent = from.getY() < data.survivalFlyLastFromY && yDistance > 0D && yDistance < 0.5D +// && setBackYDistance > 0D && setBackYDistance <= 1.5D +// && !BlockProperties.isPassable(from.getTypeIdBelow()); + + final boolean inconsistent = yDistance > 0 && yDistance < 0.5 && data.survivalFlyLastYDist < 0 && setBackYDistance > 0D && setBackYDistance <= 1.5D && !BlockProperties.isPassable(from.getTypeIdBelow()); + // TODO: Use bounding box ? // TODO: fromAboveStairs ? if (inconsistent || from.isAboveStairs()){ // !toOnGround && to.isAboveStairs()) { // Set the new setBack and reset the jumpPhase. @@ -125,14 +131,14 @@ public class SurvivalFly extends Check { data.setBack = from.getLocation(); data.setBack.setY(Location.locToBlock(data.setBack.getY())); // data.ground ? + // ? set jumpphase to height / 0.15 ? data.survivalFlyJumpPhase = 0; data.clearAccounting(); // Tell NoFall that we assume the player to have been on ground somehow. data.noFallAssumeGround = true; - if (cc.debug) System.out.println(player.getName() + " Y INCONSISTENCY WORKAROUND USED"); + if (cc.debug) System.out.println(player.getName() + " Y-INCONSISTENCY WORKAROUND USED"); } } - data.survivalFlyLastFromY = from.getY(); // Player on ice? Give him higher max speed. if (from.isOnIce() || to.isOnIce()) @@ -250,9 +256,15 @@ public class SurvivalFly extends Check { data.survivalFlyCobwebVL = vDistanceAboveLimit * 100D; } else data.survivalFlyCobwebVL += vDistanceAboveLimit * 100D; - if (data.survivalFlyCobwebVL < 325) { // Totally random ! + if (data.survivalFlyCobwebVL < 550) { // Totally random ! + if (cc.debug) System.out.println(player.getName()+ " (Cobweb: silent set-back-)"); + // Silently set back. if (data.setBack == null) data.setBack = player.getLocation(); data.survivalFlyJumpPhase = 0; + data.setBack.setYaw(to.getYaw()); + data.setBack.setPitch(to.getPitch()); + data.survivalFlyLastYDist = Integer.MAX_VALUE; + data.survivalFlyLastFromY = data.setBack.getY(); return data.setBack; } } @@ -277,7 +289,7 @@ public class SurvivalFly extends Check { if (data.noFallAssumeGround || fromOnGround || toOnGround) data.jumpAmplifier = 0D; - final boolean resetFrom = data.noFallAssumeGround || fromOnGround || from.isInLiquid() || from.isOnLadder() || from.isInWeb(); + final boolean resetFrom = data.noFallAssumeGround || fromOnGround || from.isInLiquid() || from.isOnLadder() || from.isInWeb(); if (cc.survivalFlyAccounting && !resetFrom){ final boolean useH = data.horizontalFreedom <= 0.001D; @@ -316,7 +328,7 @@ public class SurvivalFly extends Check { if (cc.debug){ System.out.println(player.getName() + " vertical freedom: " + data.verticalFreedom + " ("+data.verticalVelocity+"/"+data.verticalVelocityCounter+"), jumpphase: " + data.survivalFlyJumpPhase); System.out.println(player.getName() + " hDist: " + hDistance + " / " + hAllowedDistance + " , vDist: " + (yDistance) + " ("+player.getVelocity().getY()+")" + " / " + vAllowedDistance); - System.out.println(player.getName() + " y: " + from.getY() +"(" + player.getLocation().getY() + ") -> " + to.getY()) ; + System.out.println(player.getName() + " y" + (fromOnGround?"(onground)":"") + (data.noFallAssumeGround?"(assumeonground)":"") + ": " + from.getY() +"(" + player.getLocation().getY() + ") -> " + to.getY()+ (toOnGround?"(onground)":"")); if (cc.survivalFlyAccounting) System.out.println(player.getName() + " h=" + data.hDistSum.getScore(1f)+"/" + data.hDistSum.getScore(1) + " , v=" + data.vDistSum.getScore(1f)+"/"+data.vDistSum.getScore(1) ); } @@ -334,52 +346,32 @@ public class SurvivalFly extends Check { vd.setParameter(ParameterName.LOCATION_FROM, String.format(Locale.US, "%.2f, %.2f, %.2f", from.getX(), from.getY(), from.getZ())); vd.setParameter(ParameterName.LOCATION_TO, String.format(Locale.US, "%.2f, %.2f, %.2f", to.getX(), to.getY(), to.getZ())); vd.setParameter(ParameterName.DISTANCE, String.format(Locale.US, "%.2f", to.getLocation().distance(from.getLocation()))); - } + } if (executeActions(vd)){ + data.survivalFlyLastYDist = Integer.MAX_VALUE; + data.survivalFlyLastFromY = data.setBack.getY(); // Compose a new location based on coordinates of "newTo" and viewing direction of "event.getTo()" to // allow the player to look somewhere else despite getting pulled back by NoCheatPlus. return new Location(player.getWorld(), data.setBack.getX(), data.setBack.getY(), data.setBack.getZ(), to.getYaw(), to.getPitch()); } - else if (to.isInLiquid() || to.isInWeb() || toOnGround || to.isOnLadder()) { - // In case it only gets logged, not stopped by NoCheatPlus, update the setback location at least a bit. - data.setBack = to.getLocation(); - } } - else{ - final boolean resetTo = toOnGround || to.isInLiquid() || to.isOnLadder()|| to.isInWeb(); -// if (to.isInLiquid()) { -// // If the player moved into liquid. -// data.setBack = to.getLocation(); -// data.setBack.setY(Math.ceil(data.setBack.getY())); -// data.survivalFlyJumpPhase = 0; -// data.clearAccounting(); -// } else if (resetTo && (from.getY() >= to.getY() || data.setBack.getY() <= Location.locToBlock(to.getY()))) { -// // Set set back and jump phase, if: -// // 1. Moving onto ladder/vine. -// /* -// * 2. If the player moved down "onto" the ground or in web and ... -// * the new setback point is higher up than the old or at -// * least at the same height. -// */ -// data.setBack = to.getLocation(); -// data.survivalFlyJumpPhase = 0; -// data.clearAccounting(); -// } else - if (resetTo){ - // The player has moved onto ground. - data.setBack = to.getLocation(); - data.survivalFlyJumpPhase = 0; - data.clearAccounting(); - } - else if (resetFrom){ - // The player moved from ground. - data.setBack = from.getLocation(); - data.clearAccounting(); - } + // Violation or not, apply reset conditions (cancel would have returned above). + final boolean resetTo = toOnGround || to.isInLiquid() || to.isOnLadder()|| to.isInWeb(); + if (resetTo){ + // The player has moved onto ground. + data.setBack = to.getLocation(); + data.survivalFlyJumpPhase = 0; + data.clearAccounting(); } - // Decide if we should create a new setBack point. These are the result of a lot of bug reports, experience and - // trial and error. + else if (resetFrom){ + // The player moved from ground. + data.setBack = from.getLocation(); + data.survivalFlyJumpPhase = 1; // TODO: ? + data.clearAccounting(); + } + data.survivalFlyLastYDist = yDistance; + data.survivalFlyLastFromY = from.getY(); return null; } diff --git a/src/fr/neatmonster/nocheatplus/utilities/BlockProperties.java b/src/fr/neatmonster/nocheatplus/utilities/BlockProperties.java index 8fa33f27..770c846c 100644 --- a/src/fr/neatmonster/nocheatplus/utilities/BlockProperties.java +++ b/src/fr/neatmonster/nocheatplus/utilities/BlockProperties.java @@ -329,7 +329,11 @@ public class BlockProperties { blockFlags[mat.getId()] |= F_LIQUID | F_LAVA; } // Workarounds. - blockFlags[Material.WATER_LILY.getId()] |= F_SOLID; + for (final Material mat : new Material[]{ + Material.WATER_LILY, Material.LADDER, + }){ + blockFlags[mat.getId()] |= F_SOLID; + } // Ignore for passable. for (final Material mat : new Material[]{ Material.WOOD_PLATE, Material.STONE_PLATE, diff --git a/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java b/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java index 5790e78e..61f55eea 100644 --- a/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java +++ b/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java @@ -228,7 +228,7 @@ public class PlayerLocation { for (int blockZ = Location.locToBlock(boundingBox.c + 0.001D); blockZ <= Location.locToBlock(boundingBox.f - 0.001D); blockZ++){ if (getTypeId(blockX, blockY, blockZ) == webId){ inWeb = true; - break; + return true; } } } @@ -245,9 +245,9 @@ public class PlayerLocation { */ public boolean isOnGround() { if (onGround == null) { - AxisAlignedBB boundingBoxGround = boundingBox.clone(); - boundingBoxGround = boundingBoxGround.d(0D, -getyOnGround(), 0D); - onGround = idCache.collides(boundingBoxGround, BlockProperties.F_SOLID); +// AxisAlignedBB boundingBoxGround = boundingBox.clone(); +// boundingBoxGround = boundingBoxGround.d(0D, -getyOnGround(), 0D); + onGround = idCache.collides(boundingBox.a, boundingBox.b - yOnGround, boundingBox.c, boundingBox.d, boundingBox.e, boundingBox.f, BlockProperties.F_SOLID); // onGround = worldServer.getCubes(entity, boundingBoxGround).size() > 0; // if (onGround.booleanValue() != idCache.collides(boundingBoxGround, BlockProperties.F_SOLID)){ // System.out.println("INCONSISTENCY ON GROUND (" + onGround + ")."); // TODO: remove