[BLEEDING] Ignore Minecraft fall distance if it's greater than tracked.

Fall damage is adjusted or cancelled, if the Minecraft fall distance is
greater than the distance(s) tracked by NCP (per move diffs, maximum y).
Intention is to prevent (speeding by) self damage by abusing Minecraft
dealing fall for untracked moves.
Issue: https://github.com/NoCheatPlus/Issues/issues/338
This commit is contained in:
asofold 2016-12-29 00:19:55 +01:00
parent d85ee35d99
commit b6ae8049b7
2 changed files with 61 additions and 12 deletions

View File

@ -1742,7 +1742,10 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
if (!(entity instanceof Player)) {
return;
}
final Player player = (Player) entity;
checkFallDamageEvent((Player) entity, event);
}
private void checkFallDamageEvent(final Player player, final EntityDamageEvent event) {
final MovingData data = MovingData.getData(player);
if (player.isInsideVehicle()) {
// Ignore vehicles (noFallFallDistance will be inaccurate anyway).
@ -1763,12 +1766,48 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
return;
}
boolean allowReset = true;
float fallDistance = player.getFallDistance();
final float yDiff = (float) (data.noFallMaxY - loc.getY());
final double damage = BridgeHealth.getDamage(event);
// NoFall bypass checks.
if (!data.noFallSkipAirCheck) {
// Cheat: let Minecraft gather and deal fall damage.
/*
* TODO: data.noFallSkipAirCheck is used to skip checking in
* general, thus move into that block or not?
*/
// TODO: Could consider skipping accumulated fall distance for NoFall in general as well.
final float dataDist = Math.max(yDiff, data.noFallFallDistance);
final double dataDamage = NoFall.getDamage(dataDist);
if (damage > dataDamage + 0.5 || dataDamage <= 0.0) {
data.noFallVL += 1.0;
if (noFall.executeActions(player, data.noFallVL, 1.0, cc.noFallActions).willCancel()) {
// NOTE: Double violations are possible with the in-air check below.
// TODO: Differing sub checks, once cancel action...
player.setFallDistance(dataDist);
if (dataDamage <= 0.0) {
// Cancel the event.
event.setCancelled(true);
useLoc.setWorld(null);
aux.returnPlayerMoveInfo(moveInfo);
return;
}
else {
// Adjust and continue.
if (data.debug) {
debug(player, "NoFall/Damage: override player fall distance and damage (" + fallDistance + " -> " + dataDist + ").");
}
fallDistance = dataDist;
BridgeHealth.setDamage(event, dataDamage);
}
}
}
// Cheat: set ground to true in-air.
// Be sure not to lose that block.
data.noFallFallDistance += 1.0;
// TODO: Accound for liquid too?
data.noFallFallDistance += 1.0; // TODO: What is this and why is it right here?
// TODO: Account for liquid too?
if (!pLoc.isOnGround(1.0, 0.3, 0.1) && !pLoc.isResetCond() && !pLoc.isAboveLadder() && !pLoc.isAboveStairs()) {
// Likely a new style no-fall bypass (damage in mid-air).
// Likely: force damage in mid-air by setting on-ground to true.
data.noFallVL += 1.0;
if (noFall.executeActions(player, data.noFallVL, 1.0, cc.noFallActions).willCancel() && data.hasSetBack()) {
// Cancel the event and restore fall distance.
@ -1779,14 +1818,12 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
else {
// Legitimate damage: clear accounting data.
data.vDistAcc.clear();
// TODO: Why only reset in case of !data.noFallSkipAirCheck?
// TODO: Also reset other properties.
// TODO: Also reset in other cases (moved too quickly)?
}
}
aux.returnPlayerMoveInfo(moveInfo);
final float fallDistance = player.getFallDistance();
final double damage = BridgeHealth.getDamage(event);
final float yDiff = (float) (data.noFallMaxY - loc.getY());
if (data.debug) {
debug(player, "Damage(FALL): " + damage + " / dist=" + player.getFallDistance() + " nf=" + data.noFallFallDistance + " yDiff=" + yDiff);
}

View File

@ -99,14 +99,25 @@ public class NoFall extends Check {
* @return
*/
public double estimateDamage(final Player player, final double y, final MovingData data) {
return getDamage(Math.max((float) (data.noFallMaxY - y), Math.max(data.noFallFallDistance, player.getFallDistance())));
//return getDamage(Math.max((float) (data.noFallMaxY - y), Math.max(data.noFallFallDistance, player.getFallDistance())));
return getDamage(Math.max((float) (data.noFallMaxY - y), data.noFallFallDistance));
}
/**
*
* @param player
* @param minY
* @param reallyOnGround
* @param data
* @param cc
*/
private void adjustFallDistance(final Player player, final double minY, final boolean reallyOnGround, final MovingData data, final MovingConfig cc) {
final float noFallFallDistance = Math.max(data.noFallFallDistance, (float) (data.noFallMaxY - minY));
if (noFallFallDistance >= 3.0) {
final float fallDistance = player.getFallDistance();
if (noFallFallDistance - fallDistance >= 0.5f || noFallFallDistance >= 3.5f && noFallFallDistance < 3.5f) {
if (noFallFallDistance - fallDistance >= 0.5f // TODO: Why not always adjust, if greater?
|| noFallFallDistance >= 3.5f && fallDistance < 3.5f // Ensure damage.
) {
player.setFallDistance(noFallFallDistance);
}
}
@ -230,7 +241,7 @@ public class NoFall extends Check {
// TODO: fall distance might be behind (!)
// TODO: should be the data.noFallMaxY be counted in ?
final float mcFallDistance = player.getFallDistance(); // Note: it has to be fetched here.
data.noFallFallDistance = Math.max(mcFallDistance, data.noFallFallDistance);
// SKIP: data.noFallFallDistance = Math.max(mcFallDistance, data.noFallFallDistance);
// Add y distance.
if (!toReset && !toOnGround && yDiff < 0) {
@ -279,7 +290,8 @@ public class NoFall extends Check {
public void onLeave(final Player player) {
final MovingData data = MovingData.getData(player);
final float fallDistance = player.getFallDistance();
if (data.noFallFallDistance - fallDistance > 0.0) {
// TODO: Might also detect too high mc fall dist.
if (data.noFallFallDistance > fallDistance) {
final double playerY = player.getLocation(useLoc).getY();
useLoc.setWorld(null);
if (player.isFlying() || player.getGameMode() == GameMode.CREATIVE
@ -292,7 +304,7 @@ public class NoFall extends Check {
// Might use tolerance, might log, might use method (compare: MovingListener.onEntityDamage).
// Might consider triggering violations here as well.
final float yDiff = (float) (data.noFallMaxY - playerY);
final float maxDist = Math.max(yDiff, Math.max(data.noFallFallDistance, fallDistance));
final float maxDist = Math.max(yDiff, data.noFallFallDistance);
player.setFallDistance(maxDist);
}
}