[BLEEDING] Model (noob) tower with lost-ground only.

* lostGroundAscend: new condition.
* lostGroundStill: some precondition checks moved inside, new condition.
* vdistrel: Extra case with decreased lift-off gain, but second move as
if normal lift off.
* With from being on ground, and last move not having touched ground,
setSetBack(from).
This commit is contained in:
asofold 2017-04-18 16:56:24 +02:00
parent 6a4c75460a
commit ca2d2398e4
4 changed files with 107 additions and 80 deletions

View File

@ -25,12 +25,10 @@ import java.util.UUID;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.entity.PlayerDeathEvent;
@ -212,65 +210,6 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
blockChangeTracker = NCPAPIProvider.getNoCheatPlusAPI().getBlockChangeTracker();
}
/**
* A workaround for players placing blocks below them getting pushed off the block by NoCheatPlus.
*
* It essentially moves the "setbackpoint" to the top of the newly placed block, therefore tricking NoCheatPlus into
* thinking the player was already on top of that block and should be allowed to stay there.
*
* It also prevent players from placing a block on a liquid (which is impossible without a modified version of
* Minecraft).
*
* @param event
* the event
*/
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onBlockPlace(final BlockPlaceEvent event) {
final Player player = event.getPlayer();
// Ignore players inside a vehicle.
if (player.isInsideVehicle())
return;
final org.bukkit.block.Block block = event.getBlock();
if (block == null) {
return;
}
final int blockY = block.getY();
final Material mat = block.getType();
final MovingData data = MovingData.getData(player);
final MovingConfig cc = MovingConfig.getConfig(player);
final PlayerMoveInfo moveInfo = aux.usePlayerMoveInfo();
final Location loc = player.getLocation(useLoc);
moveInfo.set(player, loc, null, cc.yOnGround);
if (!MovingUtil.shouldCheckSurvivalFly(player, moveInfo.from, data, cc)) {
aux.returnPlayerMoveInfo(moveInfo);
useLoc.setWorld(null);
return;
}
aux.returnPlayerMoveInfo(moveInfo);
if (!data.hasSetBack() || blockY + 1D < data.getSetBackY()) {
useLoc.setWorld(null);
return;
}
if (Math.abs(loc.getX() - 0.5 - block.getX()) <= 1D
&& Math.abs(loc.getZ() - 0.5 - block.getZ()) <= 1D
&& loc.getY() - blockY > 0D && loc.getY() - blockY < 2D
&& (MovingUtil.canJumpOffTop(mat) || BlockProperties.isLiquid(mat))) {
// The creative fly and/or survival fly check is enabled, the
// block was placed below the player and is
// solid, so do what we have to do.
data.setSetBackY(blockY + 1D);
data.sfJumpPhase = 0;
}
useLoc.setWorld(null);
}
/**
* We listen to this event to prevent player from flying by sending bed leaving packets.
*

View File

@ -63,14 +63,14 @@ public class LostGround {
// TODO: yDistance limit does not seem to be appropriate.
if (yDistance >= -0.7 && yDistance <= Math.max(cc.sfStepHeight, LiftOffEnvelope.NORMAL.getMaxJumpGain(data.jumpAmplifier) + 0.174)) { // MovingUtil.estimateJumpLiftOff(player, data, 0.174))) {
// "Mild" Ascending / descending.
//Ascending
if (yDistance >= 0) {
// Ascending
if (yDistance >= 0.0) {
if (lastMove.toIsValid && lostGroundAscend(player, from, to, hDistance, yDistance, sprinting, lastMove, data, cc, tags)) {
return true;
}
}
// Descending.
if (yDistance <= 0) {
if (yDistance <= 0.0) {
if (lostGroundDescend(player, from, to, hDistance, yDistance, sprinting, lastMove, data, cc, tags)) {
return true;
}
@ -121,26 +121,44 @@ public class LostGround {
*/
private static boolean lostGroundAscend(final Player player, final PlayerLocation from, final PlayerLocation to, final double hDistance, final double yDistance, final boolean sprinting, final PlayerMoveData lastMove, final MovingData data, final MovingConfig cc, final Collection<String> tags) {
final PlayerMoveData thisMove = data.playerMoves.getCurrentMove();
final double setBackYDistance = to.getY() - data.getSetBackY();
final double setBackYDistance = from.getY() - data.getSetBackY();
// Step height related.
// TODO: Combine / refine preconditions for step height related.
// TODO: || yDistance <= jump estimate?
if (yDistance <= cc.sfStepHeight && hDistance <= 1.5) { // hDistance is arbitrary, just to confine.
if (setBackYDistance <= Math.max(0.0, 1.3 + 0.2 * data.jumpAmplifier)) {
final double setBackYMargin = data.liftOffEnvelope.getMaxJumpHeight(data.jumpAmplifier) - setBackYDistance;
if (setBackYMargin >= 0.0) {
// Half block step up (definitive).
// TODO: && hDistance < 0.5 ~ switch to about 2.2 * baseSpeed once available.
if (to.isOnGround()) {
if (to.isOnGround() && setBackYMargin >= yDistance) {
// TODO: hDistance > 0.0
if (lastMove.yDistance < 0.0 || yDistance <= cc.sfStepHeight && from.isOnGround(cc.sfStepHeight - yDistance)) {
return applyLostGround(player, from, true, thisMove, data, "step", tags);
}
}
// Noob tower (moving up placing blocks underneath). Rather since 1.9: player jumps off with 0.4 speed but ground within 0.42.
// TODO: Confine by actually having placed a block nearby, possibly rather low jumpphase (3, 4).
// TODO: Re-test with legacy.
// TODO: Confine by actually having placed a block nearby.
// TODO: Jump phase can be 6/7 - also confine by typical max jump phase (!)
final double maxJumpGain = data.liftOffEnvelope.getMaxJumpGain(data.jumpAmplifier);
if (yDistance > 0.0 && yDistance < maxJumpGain && lastMove.yDistance < 0.0 && maxJumpGain > yDistance
&& Math.abs(lastMove.yDistance) + Magic.GRAVITY_MAX > cc.yOnGround + maxJumpGain - yDistance
&& from.isOnGround(cc.yOnGround + maxJumpGain - yDistance)) {
if (
maxJumpGain > yDistance
&& (
// Typical: distance to ground + yDistance roughly covers maxJumpGain.
yDistance > 0.0
&& lastMove.yDistance < 0.0 // Rather -0.15 or so.
&& Math.abs(lastMove.yDistance) + Magic.GRAVITY_MAX + yDistance > cc.yOnGround + maxJumpGain
&& from.isOnGround(0.025)
/*
* Rather rare: Come to rest above the block.
* Multiple 0-dist moves with looking packets.
* Not sure this happens with hdist > 0 at all.
*/
|| lastMove.yDistance == 0.0
&& noobTowerStillCommon(to, yDistance)
)
) {
// TODO: Ensure set back is slightly lower, if still on ground.
return applyLostGround(player, from, true, thisMove, data, "nbtwr", tags);
}
}
@ -191,6 +209,19 @@ public class LostGround {
return false;
}
/**
* Common conditions for noob tower without y distance taken (likely also no
* hdist).
*
* @param to
* @param yDistance
* @return
*/
private static boolean noobTowerStillCommon(final PlayerLocation to, final double yDistance) {
// TODO: Block recently placed underneath (xz box with 0.025 down, Direction.NONE).
return yDistance < 0.025 && to.getY() - to.getBlockY() < 0.025 && to.isOnGround(0.025);
}
/**
* Preconditions move dist is 0, not on ground, last h dist > 0, last y dist
* < 0. Needs last move data.
@ -206,13 +237,26 @@ public class LostGround {
* @param cc
* @return
*/
public static boolean lostGroundStill(final Player player, final PlayerLocation from, final PlayerLocation to, final double hDistance, final double yDistance, final boolean sprinting, final PlayerMoveData lastMove, final MovingData data, final MovingConfig cc, final Collection<String> tags) {
if (lastMove.yDistance <= -0.23) {
public static boolean lostGroundStill(final Player player,
final PlayerLocation from, final PlayerLocation to,
final double hDistance, final double yDistance, final boolean sprinting,
final PlayerMoveData lastMove, final MovingData data, final MovingConfig cc,
final Collection<String> tags) {
if (lastMove.yDistance <= -0.23 && lastMove.hDistance > 0.0 && lastMove.yDistance < -0.3) {
// TODO: Code duplication with edgeasc5 above.
if (lostGroundEdgeAsc(player, from.getBlockCache(), to.getWorld(), to.getX(), to.getY(), to.getZ(), from.getX(), from.getY(), from.getZ(), hDistance, to.getBoxMarginHorizontal(), 0.3, data, "asc7", tags, from.getMCAccess())) {
return true;
}
}
else if ((lastMove.yDistance == 0.0 && lastMove.touchedGround // TODO: && (lastMove.)hDistance == 0.0
|| lastMove.yDistance < 0.0)
&& data.liftOffEnvelope.getMaxJumpGain(data.jumpAmplifier) > yDistance
&& noobTowerStillCommon(to, yDistance)
) {
// TODO: Ensure set back is slightly lower, if still on ground.
final PlayerMoveData thisMove = data.playerMoves.getCurrentMove();
return applyLostGround(player, from, true, thisMove, data, "nbtwr", tags);
}
return false;
}

View File

@ -132,7 +132,8 @@ public class Magic {
* @param extraGravity Extra amount to fall faster.
* @return
*/
public static boolean fallingEnvelope(final double yDistance, final double lastYDist, final double lastFrictionVertical, final double extraGravity) {
public static boolean fallingEnvelope(final double yDistance, final double lastYDist,
final double lastFrictionVertical, final double extraGravity) {
if (yDistance >= lastYDist) {
return false;
}
@ -339,4 +340,28 @@ public class Magic {
;
}
/**
* Jump off the top off a block with the ordinary jumping envelope, however
* from a slightly higher position with the initial gain being lower than
* typical, but the following move having the y distance as if jumped off
* with typical gain.
*
* @param yDistance
* @param maxJumpGain
* @param thisMove
* @param lastMove
* @param data
* @return
*/
public static boolean noobJumpsOffTower(final double yDistance, final double maxJumpGain,
final PlayerMoveData thisMove, final PlayerMoveData lastMove, final MovingData data) {
final PlayerMoveData secondPastMove = data.playerMoves.getSecondPastMove();
return (data.sfJumpPhase == 1 && lastMove.touchedGroundWorkaround // TODO: Not observed though.
|| data.sfJumpPhase == 2 && inAir(lastMove)
&& secondPastMove.valid && secondPastMove.touchedGroundWorkaround
)
&& inAir(thisMove)
&& lastMove.yDistance < maxJumpGain && lastMove.yDistance > maxJumpGain * 0.67
&& Magic.fallingEnvelope(yDistance, maxJumpGain, data.lastFrictionVertical, Magic.GRAVITY_SPAN);
}
}

View File

@ -223,7 +223,7 @@ public class SurvivalFly extends Check {
resetFrom = true;
tags.add("pastground_from");
}
else if (lastMove.toIsValid && lastMove.hDistance > 0.0 && lastMove.yDistance < -0.3) {
else if (lastMove.toIsValid) {
// Note that to is not on ground either.
resetFrom = LostGround.lostGroundStill(player, from, to, hDistance, yDistance, sprinting, lastMove, data, cc, tags);
}
@ -241,10 +241,20 @@ public class SurvivalFly extends Check {
// Note: if not setting resetFrom, other places have to check assumeGround...
}
if (thisMove.touchedGround && !thisMove.from.onGround && !thisMove.to.onGround) {
// Lost ground workaround has just been applied, check resetting of the dirty flag.
// TODO: Always/never reset with any ground touched?
data.resetVelocityJumpPhase();
if (thisMove.touchedGround ) {
if (!thisMove.from.onGround && !thisMove.to.onGround) {
// Lost ground workaround has just been applied, check resetting of the dirty flag.
// TODO: Always/never reset with any ground touched?
data.resetVelocityJumpPhase();
}
else if (!mightBeMultipleMoves && thisMove.from.onGround && !lastMove.touchedGround
&& TrigUtil.isSamePosAndLook(thisMove.from, lastMove.to)) {
// Ground somehow appeared out of thin air (block place).
data.setSetBack(from);
if (data.debug) {
debug(player, "Adjust set back on move: from is now on ground.");
}
}
}
// Renew the "dirty"-flag (in-air phase affected by velocity).
@ -600,6 +610,7 @@ public class SurvivalFly extends Check {
}
else {
data.sfJumpPhase ++;
// TODO: Void-to-void: Rather handle unified somewhere else (!).
if (to.getY() < 0.0 && cc.sfSetBackPolicyVoid) {
data.setSetBack(to);
}
@ -1096,9 +1107,17 @@ public class SurvivalFly extends Check {
&& yDistance < lastMove.yDistance - 0.001) {
// Odd decrease with water.
}
else if (lastMove.toIsValid && MagicAir.oddJunction(from, to, yDistance, yDistChange, yDistDiffEx, maxJumpGain, resetTo, thisMove, lastMove, data, cc)) {
else if (MagicAir.oddJunction(from, to, yDistance, yDistChange, yDistDiffEx, maxJumpGain, resetTo, thisMove, lastMove, data, cc)) {
// Several types of odd in-air moves, mostly with gravity near maximum, friction, medium change.
}
else if (yDistDiffEx < 0.025
&& Magic.noobJumpsOffTower(yDistance, maxJumpGain, thisMove, lastMove, data)) {
/*
* On (noob) tower up, the second move has a higher distance
* than expected, because the first had been starting
* slightly above the top.
*/
}
else {
// Violation.
vDistRelVL = true;