From d9038010d8adc9622308191469802df2fe6627fe Mon Sep 17 00:00:00 2001 From: asofold Date: Sun, 7 Oct 2012 21:47:54 +0200 Subject: [PATCH] Fix survivalfly alerts for moving downstream in water. --- .../checks/moving/SurvivalFly.java | 49 +++++++++----- .../nocheatplus/utilities/PlayerLocation.java | 67 ++++++++++++++++++- 2 files changed, 96 insertions(+), 20 deletions(-) diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java b/src/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java index ef420e21..b0e01ba6 100644 --- a/src/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java +++ b/src/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java @@ -45,6 +45,9 @@ public class SurvivalFly extends Check { public static final double webSpeed = 0.105D; // TODO: walkingSpeed * 0.15D; <- does not work public static final double modIce = 2.5D; + + /** Faster moving down stream (water mainly). */ + public static final double modDownStream = 0.19 / swimmingSpeed; /** * Instantiates a new survival fly check. @@ -112,20 +115,25 @@ 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 && (from.getY() < data.survivalFlyLastFromY && yDistance > 0D && yDistance < 0.5D - && setBackYDistance > 0D && setBackYDistance <= 1.5D && !BlockProperties.isPassable(from.getTypeIdBelow()) - || !toOnGround && to.isAboveStairs())) { - // Set the new setBack and reset the jumpPhase. - - // Maybe don't adapt the setback (unless null)! - data.setBack = from.getLocation(); - data.setBack.setY(Math.floor(data.setBack.getY())); - // data.ground ? - 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 (!fromOnGround){ + // TODO: more precise + final boolean inconsistent = from.getY() < data.survivalFlyLastFromY && yDistance > 0D && yDistance < 0.5D + && setBackYDistance > 0D && setBackYDistance <= 1.5D + && !BlockProperties.isPassable(from.getTypeIdBelow()); + // TODO: fromAboveStairs ? + if (inconsistent || from.isAboveStairs()){ // !toOnGround && to.isAboveStairs()) { + // Set the new setBack and reset the jumpPhase. + + // Maybe don't adapt the setback (unless null)! + data.setBack = from.getLocation(); + data.setBack.setY(Math.floor(data.setBack.getY())); + // data.ground ? + 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"); + } } data.survivalFlyLastFromY = from.getY(); @@ -158,7 +166,7 @@ public class SurvivalFly extends Check { // Speeding bypass permission (can be combined with other bypasses). // TODO: How exactly to bring it on finally. if (player.hasPermission(Permissions.MOVING_SURVIVALFLY_SPEEDING)) - hAllowedDistance = hAllowedDistance * cc.survivalFlySpeedingSpeed/ 100D; + hAllowedDistance *= cc.survivalFlySpeedingSpeed/ 100D; } // TODO: Optimize: maybe only do the permission checks and modifiers if the distance is too big. @@ -172,6 +180,11 @@ public class SurvivalFly extends Check { final EntityPlayer entity = ((CraftPlayer) player).getHandle(); if (entity.hasEffect(MobEffectList.FASTER_MOVEMENT)) hAllowedDistance *= 1.0D + 0.2D * (entity.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier() + 1); + + // Account for flowing liquids (only if needed). + if (hDistance > swimmingSpeed && from.isInLiquid() && from.isDownStream(xDistance, zDistance)){ + hAllowedDistance *= modDownStream; + } // Judge if horizontal speed is above limit. double hDistanceAboveLimit = hDistance - hAllowedDistance - data.horizontalFreedom; @@ -252,7 +265,7 @@ public class SurvivalFly extends Check { vAllowedDistance *= data.jumpAmplifier; if (data.survivalFlyJumpPhase > 6 + data.jumpAmplifier && data.verticalVelocityCounter <= 0){ vAllowedDistance -= (data.survivalFlyJumpPhase - 6) * 0.15D; -// System.out.println("jumpphase -> " + data.survivalFlyJumpPhase); + if (cc.debug) System.out.println("jumpphase -> " + data.survivalFlyJumpPhase); } vDistanceAboveLimit = to.getY() - data.setBack.getY() - vAllowedDistance; @@ -281,14 +294,14 @@ public class SurvivalFly extends Check { data.vDistSum.add(now, (float) (yDistance)); data.vDistCount.add(now, 1f); } - if (useH && data.hDistCount.getScore(2) > 0){ + if (useH && data.hDistCount.getScore(2) > 0 && data.hDistCount.getScore(1) > 0){ final float hsc0 = data.hDistSum.getScore(1); final float hsc1 = data.hDistSum.getScore(2); if (hsc0 < hsc1 || hDistance < 3.9 && hsc0 == hsc1){ hDistanceAboveLimit = Math.max(hDistanceAboveLimit, hsc0 - hsc1); } } - if (useV && data.vDistCount.getScore(2) > 0){ + if (useV && data.vDistCount.getScore(2) > 0 && data.vDistCount.getScore(1) > 0){ final float vsc0 = data.vDistSum.getScore(1); final float vsc1 = data.vDistSum.getScore(2); if (vsc0 < vsc1 || yDistance < 3.9 && vsc0 == vsc1){ diff --git a/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java b/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java index 71482270..6365de46 100644 --- a/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java +++ b/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java @@ -40,6 +40,8 @@ public class PlayerLocation { /** Type id of the block below. */ private Integer typeIdBelow; + + private Integer data; /** Is the player above stairs? */ private Boolean aboveStairs; @@ -259,9 +261,9 @@ public class PlayerLocation { } /** - * Checks if the player is on a ladder. + * Checks if the player is on a ladder or vine. * - * @return true, if the player is on a ladder + * @return If so. */ public boolean isOnLadder() { if (onLadder == null){ @@ -271,6 +273,17 @@ public class PlayerLocation { return onLadder; } + /** + * Checks if the player is above a ladder or vine.
+ * Does not save back value to field. + * + * @return If so. + */ + public boolean isAboveLadder() { + final int typeId = getTypeIdBelow(); + return typeId == Material.LADDER.getId() || typeId == Material.VINE.getId(); + } + /** * Sets the player location object. * @@ -332,6 +345,56 @@ public class PlayerLocation { if (typeIdBelow == null) typeIdBelow = worldServer.getTypeId(blockX, blockY - 1, blockZ); return typeIdBelow; } + + public Integer getData(){ + if (data == null) data = worldServer.getData(blockX, blockY, blockZ); + return data; + } + + public boolean isDownStream(final double xDistance, final double zDistance){ + // x > 0 -> south, z > 0 -> west + final int fromData = getData(); + + if ((fromData & 0x8) == 0){ + // not falling. + if ((xDistance > 0)){ + if (fromData < 7 && BlockProperties.isLiquid(worldServer.getTypeId(blockX + 1, blockY, blockZ)) && worldServer.getData(blockX + 1, blockY, blockZ) > fromData){ + return true; + } + else if (fromData > 0 && BlockProperties.isLiquid(worldServer.getTypeId(blockX - 1, blockY, blockZ)) && worldServer.getData(blockX - 1, blockY, blockZ) < fromData){ + // reverse direction. + return true; + } + } else if (xDistance < 0){ + if (fromData < 7 && BlockProperties.isLiquid(worldServer.getTypeId(blockX - 1, blockY, blockZ)) && worldServer.getData(blockX - 1, blockY, blockZ) > fromData){ + return true; + } + else if (fromData > 0 && BlockProperties.isLiquid(worldServer.getTypeId(blockX + 1, blockY, blockZ)) && worldServer.getData(blockX + 1, blockY, blockZ) < fromData){ + // reverse direction. + return true; + } + } + if (zDistance > 0){ + if (fromData < 7 && BlockProperties.isLiquid(worldServer.getTypeId(blockX, blockY, blockZ + 1)) && worldServer.getData(blockX, blockY, blockZ + 1) > fromData){ + return true; + } + else if (fromData > 0 && BlockProperties.isLiquid(worldServer.getTypeId(blockX , blockY, blockZ - 1)) && worldServer.getData(blockX, blockY, blockZ - 1) < fromData){ + // reverse direction. + return true; + } + } + else if (zDistance < 0 ){ + if (fromData < 7 && BlockProperties.isLiquid(worldServer.getTypeId(blockX, blockY, blockZ - 1)) && worldServer.getData(blockX, blockY, blockZ - 1) > fromData){ + return true; + } + else if (fromData > 0 && BlockProperties.isLiquid(worldServer.getTypeId(blockX , blockY, blockZ + 1)) && worldServer.getData(blockX, blockY, blockZ + 1) < fromData){ + // reverse direction. + return true; + } + } + } + return false; + } public final boolean isSameBlock(final PlayerLocation other) { // Maybe make block coordinate fields later.