Improved NoFall and SurvivalFly checks, again I know...

This commit is contained in:
NeatMonster 2012-08-15 14:18:38 +02:00
parent 6bcd26b6dc
commit 0f0e22a993
5 changed files with 72 additions and 73 deletions

View File

@ -92,7 +92,7 @@ public class MovingData implements CheckData {
// Data of the survival fly check. // Data of the survival fly check.
public int survivalFlyJumpPhase; public int survivalFlyJumpPhase;
public double[] survivalFlyLastDistances = new double[] {0D, 0D}; public double survivalFlyLastFromY;
public int survivalFlyOnIce; public int survivalFlyOnIce;
public boolean survivalFlyWasInBed; public boolean survivalFlyWasInBed;
@ -120,4 +120,8 @@ public class MovingData implements CheckData {
morePacketsSetback = null; morePacketsSetback = null;
morePacketsVehicleSetback = null; morePacketsVehicleSetback = null;
} }
public void resetNoFallDistances() {
noFallFallDistance = noFallNewFallDistance = 0D;
}
} }

View File

@ -51,10 +51,9 @@ public class NoFall extends Check {
final MovingConfig cc = MovingConfig.getConfig(player); final MovingConfig cc = MovingConfig.getConfig(player);
final MovingData data = MovingData.getData(player); final MovingData data = MovingData.getData(player);
// If the player has just started falling, is falling into a liquid, in web or is on a ladder. // If the player is on the ground, is falling into a liquid, in web or is on a ladder.
if (to.isInLiquid() || to.isInWeb() || to.isOnLadder()) if (from.isOnGround() && to.isOnGround() || to.isInLiquid() || to.isInWeb() || to.isOnLadder())
// Reset his fall distance. data.resetNoFallDistances();
data.noFallFallDistance = data.noFallNewFallDistance = 0D;
// If the player just touched the ground for the server, but no for the client. // If the player just touched the ground for the server, but no for the client.
if (!data.noFallWasOnGroundServer && data.noFallOnGroundServer if (!data.noFallWasOnGroundServer && data.noFallOnGroundServer
@ -76,22 +75,26 @@ public class NoFall extends Check {
else if (!data.noFallWasOnGroundServer && data.noFallOnGroundServer) { else if (!data.noFallWasOnGroundServer && data.noFallOnGroundServer) {
// If the difference between the fall distance recorded by Bukkit and NoCheatPlus is too big and the fall // If the difference between the fall distance recorded by Bukkit and NoCheatPlus is too big and the fall
// distance bigger than 2. // distance bigger than 2.
if (data.noFallFallDistance - player.getFallDistance() > 1D && (int) data.noFallFallDistance > 2) { if (data.noFallFallDistance - player.getFallDistance() > Math.pow(1D, -3D)
&& (int) data.noFallFallDistance > 2) {
// Add the difference to the violation level. // Add the difference to the violation level.
data.noFallVL += data.noFallFallDistance - player.getFallDistance(); data.noFallVL += data.noFallFallDistance - player.getFallDistance();
// Execute the actions to find out if we need to cancel the event or not. // Execute the actions to find out if we need to cancel the event or not.
if (executeActions(player, data.noFallVL, cc.noFallActions)) if (executeActions(player, data.noFallVL, cc.noFallActions))
// player.sendMessage("");
// Set the fall distance to its right value. // Set the fall distance to its right value.
player.setFallDistance((float) data.noFallFallDistance); player.setFallDistance((float) data.noFallFallDistance);
} else
// Reward the player by lowering his violation level.
data.noFallVL *= 0.95D;
} else
// Reward the player by lowering his violation level.
data.noFallVL *= 0.95D;
} else // The player has touched the ground somewhere, reset his fall distance.
// Reward the player by lowering his violation level. if (!data.noFallWasOnGroundServer && data.noFallOnGroundServer || data.noFallWasOnGroundServer
data.noFallVL *= 0.95D; && !data.noFallOnGroundServer)
} else data.resetNoFallDistances();
// Reward the player by lowering his violation level.
data.noFallVL *= 0.95D;
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -122,9 +125,7 @@ public class NoFall extends Check {
final AxisAlignedBB boundingBoxGround = player.boundingBox.clone().d(packet.x - player.locX, final AxisAlignedBB boundingBoxGround = player.boundingBox.clone().d(packet.x - player.locX,
packet.y - player.locY - 0.001D, packet.z - player.locZ); packet.y - player.locY - 0.001D, packet.z - player.locZ);
data.noFallOnGroundServer = player.world.getCubes(player, boundingBoxGround).size() > 0; data.noFallOnGroundServer = player.world.getCubes(player, boundingBoxGround).size() > 0;
if (packet.hasPos && packet.y > 0 && data.noFallWasOnGroundServer && !data.noFallOnGroundServer) if (packet.hasPos && packet.y > 0 && player.locY - packet.y > 0D) {
data.noFallFallDistance = data.noFallNewFallDistance = 0D;
else if (packet.hasPos && packet.y > 0 && player.locY - packet.y > 0D) {
data.noFallFallDistance = data.noFallNewFallDistance; data.noFallFallDistance = data.noFallNewFallDistance;
data.noFallNewFallDistance += player.locY - packet.y; data.noFallNewFallDistance += player.locY - packet.y;
} }

View File

@ -116,23 +116,23 @@ public class SurvivalFly extends Check {
// Calculate some distances. // Calculate some distances.
final double xDistance = to.getX() - from.getX(); final double xDistance = to.getX() - from.getX();
final double yDistance = to.getY() - from.getY();
final double zDistance = to.getZ() - from.getZ(); final double zDistance = to.getZ() - from.getZ();
final double hDistance = Math.sqrt(xDistance * xDistance + zDistance * zDistance); final double hDistance = Math.sqrt(xDistance * xDistance + zDistance * zDistance);
double hDistanceAboveLimit = hDistance - hAllowedDistance - data.horizontalFreedom; double hDistanceAboveLimit = hDistance - hAllowedDistance - data.horizontalFreedom;
// Prevent players from walking on a liquid. // Prevent players from walking on a liquid.
if (hDistanceAboveLimit <= 0D && hDistance > 0.1D && from.getY() == to.getY() if (hDistanceAboveLimit <= 0D && hDistance > 0.1D && yDistance == 0D
&& MovingListener.isLiquid(to.getLocation().getBlock().getType()) && !to.isOnGround() && MovingListener.isLiquid(to.getLocation().getBlock().getType()) && !to.isOnGround()
&& to.getY() % 1D < 0.8D) && to.getY() % 1D < 0.8D)
hDistanceAboveLimit = hDistance; hDistanceAboveLimit = hDistance;
// Prevent players from sprinting if they're moving backwards. // Prevent players from sprinting if they're moving backwards.
if (hDistanceAboveLimit <= 0D && sprinting && !player.hasPermission(Permissions.MOVING_SURVIVALFLY_SPRINTING)) { if (hDistanceAboveLimit <= 0D && sprinting && !player.hasPermission(Permissions.MOVING_SURVIVALFLY_SPRINTING)) {
final double dX = to.getX() - from.getX();
final double dZ = to.getZ() - from.getZ();
final float yaw = from.getYaw(); final float yaw = from.getYaw();
if (dX < 0D && dZ > 0D && yaw > 180F && yaw < 270F || dX < 0D && dZ < 0D && yaw > 270F && yaw < 360F if (xDistance < 0D && zDistance > 0D && yaw > 180F && yaw < 270F || xDistance < 0D && zDistance < 0D
|| dX > 0D && dZ < 0D && yaw > 0F && yaw < 90F || dX > 0D && dZ > 0D && yaw > 90F && yaw < 180F) && yaw > 270F && yaw < 360F || xDistance > 0D && zDistance < 0D && yaw > 0F && yaw < 90F
|| xDistance > 0D && zDistance > 0D && yaw > 90F && yaw < 180F)
hDistanceAboveLimit = hDistance; hDistanceAboveLimit = hDistance;
} }
@ -169,12 +169,19 @@ public class SurvivalFly extends Check {
if (jumpAmplifier > data.jumpAmplifier) if (jumpAmplifier > data.jumpAmplifier)
data.jumpAmplifier = jumpAmplifier; data.jumpAmplifier = jumpAmplifier;
// If the player has made a "double-jump" which hasn't been noticed by the plugin, the issue is fixed here. // If the player has touched the ground but it hasn't been noticed by the plugin, the workaround is here.
if (!from.isOnGround() && to.isOnGround() && to.getY() - from.getY() > 0D && to.getY() - from.getY() <= 0.5D final double setBackYDistance = to.getY() - data.setBack.getY();
&& to.getY() - data.setBack.getY() > 0D && to.getY() - data.setBack.getY() <= 1.5D) { if (!from.isOnGround()
data.setBack = to.getLocation(); && (from.getY() < data.survivalFlyLastFromY && yDistance > 0D && yDistance < 0.5D
&& setBackYDistance > 0D && setBackYDistance <= 1.5D || !to.isOnGround() && to.isAboveStairs())) {
// Set the new setBack and reset the jumpPhase.
data.setBack = from.getLocation();
data.setBack.setY(Math.floor(data.setBack.getY()));
data.survivalFlyJumpPhase = 0; data.survivalFlyJumpPhase = 0;
// Reset the no fall data.
data.resetNoFallDistances();
} }
data.survivalFlyLastFromY = from.getY();
// Calculate the vertical speed limit based on the current jump phase. // Calculate the vertical speed limit based on the current jump phase.
double vAllowedDistance = (!from.isOnGround() && !to.isOnGround() ? 1.45D : 1.35D) + data.verticalFreedom; double vAllowedDistance = (!from.isOnGround() && !to.isOnGround() ? 1.45D : 1.35D) + data.verticalFreedom;
@ -182,25 +189,7 @@ public class SurvivalFly extends Check {
if (data.survivalFlyJumpPhase > 6 + data.jumpAmplifier) if (data.survivalFlyJumpPhase > 6 + data.jumpAmplifier)
vAllowedDistance -= (data.survivalFlyJumpPhase - 6) * 0.15D; vAllowedDistance -= (data.survivalFlyJumpPhase - 6) * 0.15D;
// If the player has touched the ground and this actions hasn't been noticed by the plugin, the issue is fixed final double vDistanceAboveLimit = to.getY() - data.setBack.getY() - vAllowedDistance;
// here.
final double vDistance = to.getY() - data.setBack.getY();
if (data.survivalFlyLastDistances[0] < data.survivalFlyLastDistances[1]
&& vDistance > data.survivalFlyLastDistances[0] && vDistance > 0 && vDistance < 0.5D)
data.survivalFlyJumpPhase = 0;
else if (vDistance <= 0D)
data.survivalFlyJumpPhase = 0;
data.survivalFlyLastDistances[1] = data.survivalFlyLastDistances[0];
data.survivalFlyLastDistances[0] = vDistance;
double vDistanceAboveLimit = vDistance - vAllowedDistance;
// Fix for the issue with stairs.
if (from.isOnStairs() || to.isOnStairs() && vDistanceAboveLimit < 0.15D) {
data.jumpAmplifier = 0D;
data.noFallOnGroundClient = data.noFallOnGroundServer = true;
vDistanceAboveLimit = 0D;
}
if (from.isOnGround() || to.isOnGround()) if (from.isOnGround() || to.isOnGround())
data.jumpAmplifier = 0D; data.jumpAmplifier = 0D;

View File

@ -22,7 +22,9 @@ public class DefaultConfig extends ConfigFile {
public DefaultConfig() { public DefaultConfig() {
super(); super();
options().header("Main configuration file for NoCheatPlus. Read \"Instructions.txt\"."); options().header(
"Main configuration file for NoCheatPlus. "
+ "For more information, visit http://dev.bukkit.org/server-mods/nocheatplus/.");
/* /*
* 888 ,e, * 888 ,e,

View File

@ -1,12 +1,14 @@
package fr.neatmonster.nocheatplus.utilities; package fr.neatmonster.nocheatplus.utilities;
import java.util.Arrays;
import net.minecraft.server.AxisAlignedBB; import net.minecraft.server.AxisAlignedBB;
import net.minecraft.server.Block; import net.minecraft.server.Block;
import net.minecraft.server.EntityPlayer; import net.minecraft.server.EntityPlayer;
import net.minecraft.server.Material;
import net.minecraft.server.WorldServer; import net.minecraft.server.WorldServer;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -75,9 +77,16 @@ public class PlayerLocation {
} }
} }
private static final Material[] STAIRS = new Material[] {Material.WOOD_STAIRS, Material.COBBLESTONE_STAIRS,
Material.BRICK_STAIRS, Material.SMOOTH_STAIRS, Material.NETHER_BRICK_STAIRS, Material.SANDSTONE_STAIRS,
Material.SPRUCE_WOOD_STAIRS, Material.BIRCH_WOOD_STAIRS, Material.JUNGLE_WOOD_STAIRS};
/** The original location. */ /** The original location. */
private final Location location; private final Location location;
/** Is the player above stairs? */
private final CustomBoolean aboveStairs = new CustomBoolean();
/** Is the player in lava? */ /** Is the player in lava? */
private final CustomBoolean inLava = new CustomBoolean(); private final CustomBoolean inLava = new CustomBoolean();
@ -102,9 +111,6 @@ public class PlayerLocation {
/** Is the player on soul sand? */ /** Is the player on soul sand? */
private final CustomBoolean onSoulSand = new CustomBoolean(); private final CustomBoolean onSoulSand = new CustomBoolean();
/** Is the player on stairs? */
private final CustomBoolean onStairs = new CustomBoolean();
/** The bounding box of the player. */ /** The bounding box of the player. */
private final AxisAlignedBB boundingBox; private final AxisAlignedBB boundingBox;
@ -191,6 +197,17 @@ public class PlayerLocation {
return location.getZ(); return location.getZ();
} }
/**
* Checks if the player is above stairs.
*
* @return true, if the player above on stairs
*/
public boolean isAboveStairs() {
if (!aboveStairs.isSet())
aboveStairs.set(Arrays.asList(STAIRS).contains(Material.getMaterial(world.getTypeId(x, y - 1, z))));
return aboveStairs.get();
}
/** /**
* Checks if the player is in lava. * Checks if the player is in lava.
* *
@ -200,7 +217,7 @@ public class PlayerLocation {
if (!inLava.isSet()) { if (!inLava.isSet()) {
AxisAlignedBB boundingBoxLava = boundingBox.clone(); AxisAlignedBB boundingBoxLava = boundingBox.clone();
boundingBoxLava = boundingBoxLava.grow(-0.10000000149011612D, -0.40000000596046448D, -0.10000000149011612D); boundingBoxLava = boundingBoxLava.grow(-0.10000000149011612D, -0.40000000596046448D, -0.10000000149011612D);
inLava.set(world.a(boundingBoxLava, Material.LAVA)); inLava.set(world.a(boundingBoxLava, net.minecraft.server.Material.LAVA));
} }
return inLava.get(); return inLava.get();
} }
@ -224,7 +241,7 @@ public class PlayerLocation {
AxisAlignedBB boundingBoxWater = boundingBox.clone(); AxisAlignedBB boundingBoxWater = boundingBox.clone();
boundingBoxWater = boundingBoxWater.grow(0.0D, -0.40000000596046448D, 0.0D); boundingBoxWater = boundingBoxWater.grow(0.0D, -0.40000000596046448D, 0.0D);
boundingBoxWater = boundingBoxWater.shrink(0.001D, 0.001D, 0.001D); boundingBoxWater = boundingBoxWater.shrink(0.001D, 0.001D, 0.001D);
inWater.set(world.a(boundingBoxWater, Material.WATER, entity)); inWater.set(world.a(boundingBoxWater, net.minecraft.server.Material.WATER, entity));
} }
return inWater.get(); return inWater.get();
} }
@ -351,18 +368,4 @@ public class PlayerLocation {
} }
return onSoulSand.get(); return onSoulSand.get();
} }
/**
* Checks if the player is on stairs.
*
* @return true, if the player is on stairs
*/
public boolean isOnStairs() {
if (!onStairs.isSet()) {
final int id = world.getTypeId(x, y - 1, z);
onStairs.set(id == 53 || id == 67 || id == 108 || id == 109 || id == 114 || id == 128 || id == 134
|| id == 135 || id == 136);
}
return onStairs.get();
}
} }