[BREAKING] Use MoveData for more 'last123'-type properties.

Does break use of MovingData for last coordinates and distances (not
officially exposed API).

Other changes:
* Position resetting on teleport events has been altered.
* Some blocks/methods are guarded by checking for lastMove.toIsValid.
* Possibly other.
This commit is contained in:
asofold 2015-12-16 13:22:02 +01:00
parent 2145a6a0d3
commit 16a1e08f57
8 changed files with 412 additions and 433 deletions

View File

@ -31,6 +31,7 @@ import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.checks.moving.locations.LocationTrace; import fr.neatmonster.nocheatplus.checks.moving.locations.LocationTrace;
import fr.neatmonster.nocheatplus.checks.moving.locations.LocationTrace.TraceEntry; import fr.neatmonster.nocheatplus.checks.moving.locations.LocationTrace.TraceEntry;
import fr.neatmonster.nocheatplus.checks.moving.model.LiftOffEnvelope; import fr.neatmonster.nocheatplus.checks.moving.model.LiftOffEnvelope;
import fr.neatmonster.nocheatplus.checks.moving.model.MoveData;
import fr.neatmonster.nocheatplus.checks.moving.util.MovingUtil; import fr.neatmonster.nocheatplus.checks.moving.util.MovingUtil;
import fr.neatmonster.nocheatplus.compat.BridgeEnchant; import fr.neatmonster.nocheatplus.compat.BridgeEnchant;
import fr.neatmonster.nocheatplus.compat.BridgeHealth; import fr.neatmonster.nocheatplus.compat.BridgeHealth;
@ -283,8 +284,9 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
if (!cancelled && TrigUtil.distance(loc.getX(), loc.getZ(), damagedLoc.getX(), damagedLoc.getZ()) < 4.5){ if (!cancelled && TrigUtil.distance(loc.getX(), loc.getZ(), damagedLoc.getX(), damagedLoc.getZ()) < 4.5){
final MovingData mData = MovingData.getData(player); final MovingData mData = MovingData.getData(player);
// Check if fly checks is an issue at all, re-check "real sprinting". // Check if fly checks is an issue at all, re-check "real sprinting".
if (mData.fromX != Double.MAX_VALUE && mData.liftOffEnvelope == LiftOffEnvelope.NORMAL) { final MoveData lastMove = mData.moveData.getFirst();
final double hDist = TrigUtil.distance(loc.getX(), loc.getZ(), mData.fromX, mData.fromZ); if (lastMove.valid && mData.liftOffEnvelope == LiftOffEnvelope.NORMAL) {
final double hDist = TrigUtil.distance(loc.getX(), loc.getZ(), lastMove.fromX, lastMove.fromZ);
if (hDist >= 0.23) { if (hDist >= 0.23) {
// TODO: Might need to check hDist relative to speed / modifiers. // TODO: Might need to check hDist relative to speed / modifiers.
final MovingConfig mc = MovingConfig.getConfig(player); final MovingConfig mc = MovingConfig.getConfig(player);

View File

@ -45,6 +45,7 @@ public class CreativeFly extends Check {
// Edge data for this move. // Edge data for this move.
final MoveData thisMove = data.thisMove; final MoveData thisMove = data.thisMove;
final MoveData lastMove = data.moveData.getFirst();
// Ensure we have a set-back location. // Ensure we have a set-back location.
if (!data.hasSetBack()) { if (!data.hasSetBack()) {
@ -139,9 +140,9 @@ public class CreativeFly extends Check {
limitV *= data.flySpeed / 0.1; limitV *= data.flySpeed / 0.1;
} }
if (data.lastYDist != Double.MAX_VALUE) { if (lastMove.toIsValid) {
// (Disregard gravity.) // (Disregard gravity.)
double frictionDist = data.lastYDist * SurvivalFly.FRICTION_MEDIUM_AIR; double frictionDist = lastMove.yDistance * SurvivalFly.FRICTION_MEDIUM_AIR;
if (!flying) { if (!flying) {
frictionDist -= SurvivalFly.GRAVITY_MIN; frictionDist -= SurvivalFly.GRAVITY_MIN;
} }

View File

@ -10,7 +10,6 @@ import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.NCPAPIProvider; import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.access.ACheckData; import fr.neatmonster.nocheatplus.checks.access.ACheckData;
import fr.neatmonster.nocheatplus.checks.access.CheckDataFactory; import fr.neatmonster.nocheatplus.checks.access.CheckDataFactory;
import fr.neatmonster.nocheatplus.checks.access.ICheckData; import fr.neatmonster.nocheatplus.checks.access.ICheckData;
@ -127,16 +126,6 @@ public class MovingData extends ACheckData {
/** Last time the player was actually sprinting. */ /** Last time the player was actually sprinting. */
public long timeSprinting = 0; public long timeSprinting = 0;
public double multSprinting = 1.30000002; // Multiplier at the last time sprinting. public double multSprinting = 1.30000002; // Multiplier at the last time sprinting.
/**
* Last valid y distance covered by a move. Integer.MAX_VALUE indicates "not set".
*/
public double lastYDist = Double.MAX_VALUE;
/**
* Last valid horizontal distance covered by a move. Integer.MAX_VALUE indicates "not set".
*/
public double lastHDist = Double.MAX_VALUE;
/** Last flying check used (creativefly, survivalfly, unknown), used for hacks. */
public CheckType lastFlyCheck = CheckType.UNKNOWN;
/** Just used velocity, during processing of moving checks. */ /** Just used velocity, during processing of moving checks. */
public SimpleEntry verVelUsed = null; public SimpleEntry verVelUsed = null;
/** Compatibility entry for bouncing of slime blocks and the like. */ /** Compatibility entry for bouncing of slime blocks and the like. */
@ -169,12 +158,6 @@ public class MovingData extends ACheckData {
private final FrictionAxisVelocity horVel = new FrictionAxisVelocity(); private final FrictionAxisVelocity horVel = new FrictionAxisVelocity();
// Coordinates. // Coordinates.
/** Last from coordinates. X is at Double.MAX_VALUE, if not set. */
public double fromX = Double.MAX_VALUE, fromY, fromZ;
/** Last to coordinates. X is at Double.MAX_VALUE, if not set. */
public double toX = Double.MAX_VALUE, toY, toZ;
/** Last to looking direction. Yaw is at Float.MAX_VALUE if not set. */
public float toYaw = Float.MAX_VALUE, toPitch ;
/** Moving trace (to-positions, use tick as time). This is initialized on "playerJoins, i.e. MONITOR, and set to null on playerLeaves." */ /** Moving trace (to-positions, use tick as time). This is initialized on "playerJoins, i.e. MONITOR, and set to null on playerLeaves." */
private LocationTrace trace = null; private LocationTrace trace = null;
@ -306,11 +289,7 @@ public class MovingData extends ACheckData {
sfJumpPhase = 0; sfJumpPhase = 0;
jumpAmplifier = 0; jumpAmplifier = 0;
setBack = null; setBack = null;
lastYDist = lastHDist = Double.MAX_VALUE;
lastFlyCheck = CheckType.UNKNOWN;
sfZeroVdist = 0; sfZeroVdist = 0;
fromX = toX = Double.MAX_VALUE;
toYaw = Float.MAX_VALUE;
clearAccounting(); clearAccounting();
clearNoFallData(); clearNoFallData();
removeAllVelocity(); removeAllVelocity();
@ -370,8 +349,6 @@ public class MovingData extends ACheckData {
invalidateMoveData(); invalidateMoveData();
clearAccounting(); clearAccounting();
sfJumpPhase = 0; sfJumpPhase = 0;
lastYDist = lastHDist = Double.MAX_VALUE;
lastFlyCheck = CheckType.UNKNOWN;
sfZeroVdist = 0; sfZeroVdist = 0;
toWasReset = false; toWasReset = false;
fromWasReset = false; fromWasReset = false;
@ -441,34 +418,21 @@ public class MovingData extends ACheckData {
} }
/** /**
* Reset edge data for last moves. * Invalidate all past moves data and set the last position to the given
* coordinates.
*
* @param x * @param x
* @param y * @param y
* @param z * @param z
*/ */
public void resetPositions(final double x, final double y, final double z, final float yaw, final float pitch) { public void resetPositions(final double x, final double y, final double z, final float yaw, final float pitch) {
invalidateMoveData(); resetPositions();
moveData.get(0).set(x, y, z, yaw, pitch); moveData.getFirst().set(x, y, z, yaw, pitch);
fromX = toX = x;
fromY = toY = y;
fromZ = toZ = z;
toYaw = yaw;
toPitch = pitch;
lastYDist = lastHDist = Double.MAX_VALUE;
lastFlyCheck = CheckType.UNKNOWN;
sfZeroVdist = 0;
sfDirty = false;
sfLowJump = false;
liftOffEnvelope = defaultLiftOffEnvelope;
insideMediumCount = 0;
lastFrictionHorizontal = lastFrictionVertical = 0.0;
verticalBounce = null;
// TODO: other buffers ?
// No reset of vehicleConsistency.
} }
/** /**
* Just reset the "last locations" references. * Invalidate all past moves data and set last position if not null.
*
* @param loc * @param loc
*/ */
public void resetPositions(PlayerLocation loc) { public void resetPositions(PlayerLocation loc) {
@ -481,7 +445,8 @@ public class MovingData extends ACheckData {
} }
/** /**
* Just reset the "last locations" references. * Invalidate all past moves data and set last position if not null.
*
* @param loc * @param loc
*/ */
public void resetPositions(final Location loc) { public void resetPositions(final Location loc) {
@ -494,32 +459,19 @@ public class MovingData extends ACheckData {
} }
/** /**
* Reset the "last locations" to "not set". * Invalidate all past moves data.
*/ */
public void resetPositions() { public void resetPositions() {
resetPositions(Double.MAX_VALUE, 0.0, 0.0, Float.MAX_VALUE, 0f); invalidateMoveData();
} sfZeroVdist = 0;
sfDirty = false;
public void resetLastDistances() { sfLowJump = false;
// TODO: Will change with moveData in use. liftOffEnvelope = defaultLiftOffEnvelope;
lastHDist = lastYDist = Double.MAX_VALUE; insideMediumCount = 0;
} lastFrictionHorizontal = lastFrictionVertical = 0.0;
verticalBounce = null;
/** // TODO: other buffers ?
* Set positions according to a move (just to and from). // No reset of vehicleConsistency.
* @param from
* @param to
*/
public void setPositions(final Location from, final Location to) {
// TODO: Will change with moveData in use..
fromX = from.getX();
fromY = from.getY();
fromZ = from.getZ();
toX = to.getX();
toY = to.getY();
toZ = to.getZ();
toYaw = to.getYaw();
toPitch = to.getPitch();
} }
/** /**
@ -702,18 +654,6 @@ public class MovingData extends ACheckData {
setBack = null; setBack = null;
} }
/**
* Just set the last "to-coordinates", no world check.
* @param to
*/
public final void setTo(final Location to) {
toX = to.getX();
toY = to.getY();
toZ = to.getZ();
toYaw = to.getYaw();
toPitch = to.getPitch();
}
/** /**
* Add velocity to internal book-keeping. * Add velocity to internal book-keeping.
* @param player * @param player

View File

@ -56,6 +56,7 @@ import fr.neatmonster.nocheatplus.checks.moving.locations.MoveInfo;
import fr.neatmonster.nocheatplus.checks.moving.locations.VehicleSetBack; import fr.neatmonster.nocheatplus.checks.moving.locations.VehicleSetBack;
import fr.neatmonster.nocheatplus.checks.moving.model.LiftOffEnvelope; import fr.neatmonster.nocheatplus.checks.moving.model.LiftOffEnvelope;
import fr.neatmonster.nocheatplus.checks.moving.model.MoveConsistency; import fr.neatmonster.nocheatplus.checks.moving.model.MoveConsistency;
import fr.neatmonster.nocheatplus.checks.moving.model.MoveData;
import fr.neatmonster.nocheatplus.checks.moving.util.MovingUtil; import fr.neatmonster.nocheatplus.checks.moving.util.MovingUtil;
import fr.neatmonster.nocheatplus.checks.moving.velocity.AccountEntry; import fr.neatmonster.nocheatplus.checks.moving.velocity.AccountEntry;
import fr.neatmonster.nocheatplus.checks.moving.velocity.SimpleEntry; import fr.neatmonster.nocheatplus.checks.moving.velocity.SimpleEntry;
@ -403,8 +404,10 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
final MovingConfig cc = MovingConfig.getConfig(player); final MovingConfig cc = MovingConfig.getConfig(player);
final MoveInfo moveInfo = useMoveInfo(); final MoveInfo moveInfo = useMoveInfo();
final Location loc = player.getLocation(moveInfo.useLoc); final Location loc = player.getLocation(moveInfo.useLoc);
final MoveData lastMove = data.moveData.getFirst();
// TODO: On pistons pulling the player back: -1.15 yDistance for split move 1 (untracked position > 0.5 yDistance!).
if (TrigUtil.isSamePos(from, loc) if (TrigUtil.isSamePos(from, loc)
|| TrigUtil.isSamePos(loc, data.fromX, data.fromY, data.fromZ) || lastMove.valid && TrigUtil.isSamePos(loc, lastMove.fromX, lastMove.fromY, lastMove.fromZ)
// Could also be other envelopes (0.9 velocity upwards), too tedious to research. // Could also be other envelopes (0.9 velocity upwards), too tedious to research.
//&& data.lastYDist < -SurvivalFly.GRAVITY_MIN && data.lastYDist > -SurvivalFly.GRAVITY_MAX - SurvivalFly.GRAVITY_MIN //&& data.lastYDist < -SurvivalFly.GRAVITY_MIN && data.lastYDist > -SurvivalFly.GRAVITY_MAX - SurvivalFly.GRAVITY_MIN
) { ) {
@ -545,6 +548,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
// Set some data for this move. // Set some data for this move.
data.thisMove.set(pFrom, pTo); data.thisMove.set(pFrom, pTo);
final MoveData lastMove = data.moveData.getFirst();
// Potion effect "Jump". // Potion effect "Jump".
final double jumpAmplifier = survivalFly.getJumpAmplifier(player); final double jumpAmplifier = survivalFly.getJumpAmplifier(player);
@ -611,7 +615,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
// Fake use velocity here. // Fake use velocity here.
data.prependVerticalVelocity(new SimpleEntry(tick, 0.0, 1)); data.prependVerticalVelocity(new SimpleEntry(tick, 0.0, 1));
data.getOrUseVerticalVelocity(0.0); data.getOrUseVerticalVelocity(0.0);
if (data.lastYDist < 0.0) { if (lastMove.toIsValid && lastMove.yDistance < 0.0) {
// Renew the bounce effect. // Renew the bounce effect.
data.verticalBounce = new SimpleEntry(tick, data.verticalBounce.value, 1); data.verticalBounce = new SimpleEntry(tick, data.verticalBounce.value, 1);
} }
@ -658,7 +662,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
} }
// Hack: Add velocity for transitions between creativefly and survivalfly. // Hack: Add velocity for transitions between creativefly and survivalfly.
if (data.lastFlyCheck == CheckType.MOVING_CREATIVEFLY && data.lastHDist != Double.MAX_VALUE) { if (lastMove.toIsValid && lastMove.flyCheck == CheckType.MOVING_CREATIVEFLY) {
workaroundFlyNoFlyTransition(tick, data); workaroundFlyNoFlyTransition(tick, data);
} }
@ -705,7 +709,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
} }
} }
} }
data.lastFlyCheck = CheckType.MOVING_SURVIVALFLY; data.thisMove.flyCheck = CheckType.MOVING_SURVIVALFLY;
} }
else if (checkCf) { else if (checkCf) {
// CreativeFly // CreativeFly
@ -714,7 +718,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
} }
data.sfHoverTicks = -1; data.sfHoverTicks = -1;
data.sfLowJump = false; data.sfLowJump = false;
data.lastFlyCheck = CheckType.MOVING_CREATIVEFLY; data.thisMove.flyCheck = CheckType.MOVING_CREATIVEFLY;
} }
else { else {
// No fly checking :(. // No fly checking :(.
@ -740,14 +744,12 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
if (newTo == null) { if (newTo == null) {
// Allowed move.
// Bounce effects. // Bounce effects.
if (verticalBounce) { if (verticalBounce) {
processBounce(player, pFrom.getY(), pTo.getY(), data, cc); processBounce(player, pFrom.getY(), pTo.getY(), data, cc);
} }
// Set positions. // Finished move processing.
data.setPositions(from, to);
data.lastHDist = data.thisMove.hDistance;
data.lastYDist = data.thisMove.yDistance;
data.finishThisMove(); data.finishThisMove();
return false; return false;
} }
@ -766,9 +768,10 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
* @param data * @param data
*/ */
private static void workaroundFlyNoFlyTransition(final int tick, final MovingData data) { private static void workaroundFlyNoFlyTransition(final int tick, final MovingData data) {
final double amount = data.lastHDist * SurvivalFly.FRICTION_MEDIUM_AIR; final MoveData lastMove = data.moveData.getFirst();
final double amount = lastMove.hDistance * SurvivalFly.FRICTION_MEDIUM_AIR;
data.addHorizontalVelocity(new AccountEntry(tick, amount, 1, MovingData.getHorVelValCount(amount))); data.addHorizontalVelocity(new AccountEntry(tick, amount, 1, MovingData.getHorVelValCount(amount)));
data.addVerticalVelocity(new SimpleEntry(data.lastYDist, 2)); data.addVerticalVelocity(new SimpleEntry(lastMove.yDistance, 2));
data.addVerticalVelocity(new SimpleEntry(0.0, 2)); data.addVerticalVelocity(new SimpleEntry(0.0, 2));
data.setFrictionJumpPhase(); data.setFrictionJumpPhase();
} }
@ -789,9 +792,10 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
final double fallDistance = MovingUtil.getRealisticFallDistance(player, fromY, toY, data); final double fallDistance = MovingUtil.getRealisticFallDistance(player, fromY, toY, data);
final double base = Math.sqrt(fallDistance) / 3.3; final double base = Math.sqrt(fallDistance) / 3.3;
double effect = Math.min(3.5, base + Math.min(base / 10.0, SurvivalFly.GRAVITY_MAX)); // Ancient Greek technology with gravity added. double effect = Math.min(3.5, base + Math.min(base / 10.0, SurvivalFly.GRAVITY_MAX)); // Ancient Greek technology with gravity added.
if (effect > 0.42) { final MoveData lastMove = data.moveData.getFirst();
if (effect > 0.42 && lastMove.toIsValid) {
// Extra cap by last y distance(s). // Extra cap by last y distance(s).
final double max_gain = Math.abs(data.lastYDist < 0.0 ? Math.min(data.lastYDist, toY - fromY) : (toY - fromY)) - SurvivalFly.GRAVITY_SPAN; final double max_gain = Math.abs(lastMove.yDistance < 0.0 ? Math.min(lastMove.yDistance, toY - fromY) : (toY - fromY)) - SurvivalFly.GRAVITY_SPAN;
if (max_gain < effect) { if (max_gain < effect) {
effect = max_gain; effect = max_gain;
if (data.debug) { if (data.debug) {
@ -976,7 +980,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
* @param mData * @param mData
*/ */
private void onMoveMonitorNotCancelled(final Player player, final Location from, final Location to, final long now, final long tick, final CombinedData data, final MovingData mData) { private void onMoveMonitorNotCancelled(final Player player, final Location from, final Location to, final long now, final long tick, final CombinedData data, final MovingData mData) {
data.lastMoveTime = now; // TODO: Evaluate moving this to MovingData !? data.lastMoveTime = now; // TODO: Move to MovingData ?
final String toWorldName = to.getWorld().getName(); final String toWorldName = to.getWorld().getName();
Combined.feedYawRate(player, to.getYaw(), now, toWorldName, data); Combined.feedYawRate(player, to.getYaw(), now, toWorldName, data);
// TODO: maybe even not count vehicles at all ? // TODO: maybe even not count vehicles at all ?
@ -988,11 +992,19 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
mData.updateTrace(player, to, tick); // TODO: Can you become invincible by sending special moves? mData.updateTrace(player, to, tick); // TODO: Can you become invincible by sending special moves?
} }
else if (!from.getWorld().getName().equals(toWorldName)) { else if (!from.getWorld().getName().equals(toWorldName)) {
// A teleport event should follow.
mData.resetPositions(to); mData.resetPositions(to);
mData.resetTrace(player, to, tick); mData.resetTrace(player, to, tick);
} }
else { else {
mData.setTo(to); // Called on lowest too. // TODO: Detect differing location (a teleport event would follow).
final MoveData lastMove = mData.moveData.getFirst();
if (!lastMove.toIsValid || !TrigUtil.isSamePos(to, lastMove.toX, lastMove.toY, lastMove.toZ)) {
// Something odd happened.
mData.resetPositions(to);
} else {
// Normal move, nothing to do.
}
mData.updateTrace(player, to, tick); mData.updateTrace(player, to, tick);
} }
} }
@ -1091,7 +1103,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
if (TrigUtil.distance(from, to) < margin) { if (TrigUtil.distance(from, to) < margin) {
smallRange = true; smallRange = true;
} }
else if (data.toX != Double.MAX_VALUE && data.hasSetBack()) { else if (data.hasSetBack()) {
// (Removed demand for a past move to be present - remember on issues.)
final Location setBack = data.getSetBack(to); final Location setBack = data.getSetBack(to);
if (TrigUtil.distance(to.getX(), to.getY(), to.getZ(), setBack.getX(), setBack.getY(), setBack.getZ()) < margin) { if (TrigUtil.distance(to.getX(), to.getY(), to.getZ(), setBack.getX(), setBack.getY(), setBack.getZ()) < margin) {
smallRange = true; smallRange = true;
@ -1140,9 +1153,10 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
ref = data.getSetBack(to); ref = data.getSetBack(to);
event.setTo(ref); event.setTo(ref);
adjustLiftOffEnvelope(player, ref, data, cc); adjustLiftOffEnvelope(player, ref, data, cc);
data.resetPositions(ref);
} }
else { else {
ref = from; // Player.getLocation ? ref = from;
event.setCancelled(true); event.setCancelled(true);
} }
} }
@ -1161,6 +1175,13 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
// } // }
// }); // });
// } // }
final MoveData lastMove = data.moveData.getFirst();
if (lastMove.toIsValid) {
// TODO: Could keep on ground
lastMove.set(lastMove.toX, lastMove.toY, lastMove.toZ, ref.getYaw(), ref.getPitch());
} else {
data.resetPositions(ref);
}
} }
else { else {
// "real" teleport // "real" teleport
@ -1169,7 +1190,6 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
final LiftOffEnvelope oldEnv = data.liftOffEnvelope; // Remember for workarounds. final LiftOffEnvelope oldEnv = data.liftOffEnvelope; // Remember for workarounds.
data.clearMorePacketsData(); data.clearMorePacketsData();
data.clearFlyData(); data.clearFlyData();
data.resetPositions(to);
if (TrigUtil.maxDistance(from.getX(), from.getY(), from.getZ(), to.getX(), to.getY(), to.getZ()) <= 12.0) { if (TrigUtil.maxDistance(from.getX(), from.getY(), from.getZ(), to.getX(), to.getY(), to.getZ()) <= 12.0) {
// TODO: Might happen with bigger distances (mainly ender pearl thrown at others). // TODO: Might happen with bigger distances (mainly ender pearl thrown at others).
// Keep old lift-off envelope. // Keep old lift-off envelope.
@ -1190,6 +1210,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
data.noFallSkipAirCheck = true; data.noFallSkipAirCheck = true;
} }
data.sfHoverTicks = -1; // Important against concurrent modification exception. data.sfHoverTicks = -1; // Important against concurrent modification exception.
data.resetPositions(ref);
} }
if (data.debug && BuildParameters.debugLevel > 0) { if (data.debug && BuildParameters.debugLevel > 0) {
@ -1208,9 +1229,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
} }
// Reset stuff. // Reset stuff.
Combined.resetYawRate(player, ref.getYaw(), System.currentTimeMillis(), true); Combined.resetYawRate(player, ref.getYaw(), System.currentTimeMillis(), true); // TODO: Not sure.
data.resetTeleported(); data.resetTeleported();
data.resetLastDistances();
// Prevent further moving processing for nested events. // Prevent further moving processing for nested events.
processingEvents.remove(player.getName()); processingEvents.remove(player.getName());
} }
@ -1489,7 +1509,6 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
} }
// (Note: resetPositions resets lastFlyCheck and other.) // (Note: resetPositions resets lastFlyCheck and other.)
data.resetLastDistances();
data.clearMorePacketsData(); data.clearMorePacketsData();
data.removeAllVelocity(); data.removeAllVelocity();
data.resetTrace(loc, tick, cc.traceSize, cc.traceMergeDist); // Might reset to loc instead of set-back ? data.resetTrace(loc, tick, cc.traceSize, cc.traceMergeDist); // Might reset to loc instead of set-back ?
@ -1555,8 +1574,9 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
// Check for missed moves. // Check for missed moves.
// TODO: Consider to catch all, at least (debug-) logging-wise. // TODO: Consider to catch all, at least (debug-) logging-wise.
if (!BlockProperties.isPassable(loc)) { if (!BlockProperties.isPassable(loc)) {
if (data.toX != Double.MAX_VALUE) { final MoveData lastMove = data.moveData.getFirst();
final Location refLoc = new Location(loc.getWorld(), data.toX, data.toY, data.toZ); if (lastMove.toIsValid) {
final Location refLoc = new Location(loc.getWorld(), lastMove.toX, lastMove.toY, lastMove.toZ);
final double d = refLoc.distanceSquared(loc); final double d = refLoc.distanceSquared(loc);
if (d > 0.0) { if (d > 0.0) {
// TODO: Consider to always set back here. Might skip on big distances. // TODO: Consider to always set back here. Might skip on big distances.
@ -1675,11 +1695,14 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
// TODO: What with the case of vehicle moved to another world !? // TODO: What with the case of vehicle moved to another world !?
loc = vLoc; // loc = vLoc; //
if (data.vehicleConsistency != MoveConsistency.INCONSISTENT) { if (data.vehicleConsistency != MoveConsistency.INCONSISTENT) {
final Location oldLoc = new Location(pLoc.getWorld(), data.toX, data.toY, data.toZ); final MoveData lastMove = data.moveData.getFirst();
if (data.toX != Double.MAX_VALUE && MoveConsistency.getConsistency(oldLoc, null, pLoc) != MoveConsistency.INCONSISTENT) { if (lastMove.toIsValid) {
final Location oldLoc = new Location(pLoc.getWorld(), lastMove.toX, lastMove.toY, lastMove.toZ);
if (MoveConsistency.getConsistency(oldLoc, null, pLoc) != MoveConsistency.INCONSISTENT) {
loc = oldLoc; loc = oldLoc;
} }
} }
}
} }
if (data.debug) { if (data.debug) {
@ -1817,7 +1840,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
} }
private Location enforceLocation(final Player player, final Location loc, final MovingData data) { private Location enforceLocation(final Player player, final Location loc, final MovingData data) {
if (data.toX != Double.MAX_VALUE && TrigUtil.distanceSquared(data.toX, data.toY, data.toZ, loc.getX(), loc.getY(), loc.getZ()) > 1.0 / 256.0) { final MoveData lastMove = data.moveData.getFirst();
if (lastMove.toIsValid && TrigUtil.distanceSquared(lastMove.toX, lastMove.toY, lastMove.toZ, loc.getX(), loc.getY(), loc.getZ()) > 1.0 / 256.0) {
// Teleport back. // Teleport back.
// TODO: Add history / alert? // TODO: Add history / alert?
//player.sendMessage(ChatColor.RED + "NCP: enforce location !"); // TODO: DEBUG - REMOVE. //player.sendMessage(ChatColor.RED + "NCP: enforce location !"); // TODO: DEBUG - REMOVE.
@ -1826,7 +1850,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
// Could use a flexible set-back policy (switch to in-air on login). // Could use a flexible set-back policy (switch to in-air on login).
return data.getSetBack(loc); return data.getSetBack(loc);
} else { } else {
return new Location(player.getWorld(), data.toX, data.toY, data.toZ, loc.getYaw(), loc.getPitch()); return new Location(player.getWorld(), lastMove.toX, lastMove.toY, lastMove.toZ, loc.getYaw(), loc.getPitch());
} }
} else { } else {
return null; return null;

View File

@ -1,16 +1,21 @@
package fr.neatmonster.nocheatplus.checks.moving.model; package fr.neatmonster.nocheatplus.checks.moving.model;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.utilities.PlayerLocation; import fr.neatmonster.nocheatplus.utilities.PlayerLocation;
import fr.neatmonster.nocheatplus.utilities.TrigUtil; import fr.neatmonster.nocheatplus.utilities.TrigUtil;
/** /**
* Carry data of a move, involving from- and to- locations. * Carry data of a move, involving from- and to- locations. This is for
* temporary storage and often resetting, also to encapsulate some data during
* checking.
* *
* @author asofold * @author asofold
* *
*/ */
public class MoveData { public class MoveData {
// TODO: Use objects for from and to (could lead to redesign, think of PlayerLocation)?
////////////////////////////////////////// //////////////////////////////////////////
// Guaranteed to be initialized with set. // Guaranteed to be initialized with set.
@ -21,25 +26,61 @@ public class MoveData {
*/ */
public boolean valid = false; public boolean valid = false;
/** Double.MAX_VALUE if not available, e.g. after a teleport. */ /**
public double yDistance = Double.MAX_VALUE; * Start position coordinates.
/** Double.MAX_VALUE if not available, e.g. after a teleport. */ */
public double hDistance = Double.MAX_VALUE; public double fromX, fromY, fromZ;
/** Looking direction of the start position. */
public float fromYaw, fromPitch;
/**
* Indicate if coordinates for a move end-point and distances are present.
* Always set on setPositions call.
*/
public boolean toIsValid = false;
/////////////////////////////////////////////////////////////////////
// Only set if a move end-point is set, i.e. toIsValid set to true.
/////////////////////////////////////////////////////////////////////
/** End-point of a move. Only valid if toIsValid is set to true. */
public double toX, toY, toZ;
/** Looking direction of a move end-point. Only valid if toIsValid is set to true. */
public float toYaw, toPitch;
/**
* The vertical distance covered by a move. Note the sign for moving up or
* down. Only valid if toIsValid is set to true.
*/
public double yDistance;
/**
* The horizontal distance covered by a move. Note the sign for moving up or
* down. Only valid if toIsValid is set to true.
*/
public double hDistance;
// TODO: Last coords,
// TODO: Velocity used, fly check, ... // TODO: Velocity used, fly check, ...
////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////
// Reset with set, could be lazily initialized. // Reset with set, could be lazily set during checking.
////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////
/** /**
* Head is obstructed. Should expect descending next move, if in air. <br> * Head is obstructed. Should expect descending next move, if in air. <br>
* Set at the beginning of SurvivalFly.check, if either end point is not on ground. * Set at the beginning of SurvivalFly.check, if either end-point is not on
* ground.
*/ */
public boolean headObstructed = false; public boolean headObstructed = false;
/**
* The fly check that was using the current data. One of MOVING_SURVIVALFLY,
* MOVING_CREATIVEFLY, UNKNOWN.
*/
public CheckType flyCheck = CheckType.UNKNOWN;
// TODO: ground/reset/web/... // TODO: ground/reset/web/...
/** /**
@ -59,6 +100,17 @@ public class MoveData {
final double toX, final double toY, final double toZ, final float toYaw, final float toPitch) { final double toX, final double toY, final double toZ, final float toYaw, final float toPitch) {
yDistance = toY - fromY; yDistance = toY - fromY;
hDistance = TrigUtil.distance(fromX, fromZ, toX, toZ); hDistance = TrigUtil.distance(fromX, fromZ, toX, toZ);
this.fromX = fromX;
this.fromY = fromY;
this.fromZ = fromZ;
this.fromYaw = fromYaw;
this.fromPitch = fromPitch;
this.toX = toX;
this.toY = toY;
this.toZ = toZ;
this.toYaw = toYaw;
this.toPitch = toPitch;
toIsValid = true;
} }
/** /**
@ -70,12 +122,17 @@ public class MoveData {
* @param pitch * @param pitch
*/ */
private void setPositions(final double x, final double y, final double z, final float yaw, final float pitch) { private void setPositions(final double x, final double y, final double z, final float yaw, final float pitch) {
yDistance = Double.MAX_VALUE; this.fromX = x;
hDistance = Double.MAX_VALUE; this.fromY = y;
this.fromZ = z;
this.fromYaw = yaw;
this.fromPitch = pitch;
toIsValid = false;
} }
private void resetBase() { private void resetBase() {
headObstructed = false; headObstructed = false;
flyCheck = CheckType.UNKNOWN;
valid = true; valid = true;
} }
@ -109,6 +166,7 @@ public class MoveData {
*/ */
public void invalidate() { public void invalidate() {
valid = false; valid = false;
toIsValid = false;
} }
} }

View File

@ -13,6 +13,7 @@ import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.moving.MovingConfig; import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
import fr.neatmonster.nocheatplus.checks.moving.MovingData; import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.checks.moving.model.MoveData;
import fr.neatmonster.nocheatplus.compat.BridgeMisc; import fr.neatmonster.nocheatplus.compat.BridgeMisc;
import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager; import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager;
import fr.neatmonster.nocheatplus.logging.StaticLog; import fr.neatmonster.nocheatplus.logging.StaticLog;
@ -149,12 +150,13 @@ public class MovingUtil {
if (TrigUtil.isSamePos(loc, refLoc) && (entity instanceof Player)) { if (TrigUtil.isSamePos(loc, refLoc) && (entity instanceof Player)) {
final Player other = (Player) entity; final Player other = (Player) entity;
final MovingData otherData = MovingData.getData(other); final MovingData otherData = MovingData.getData(other);
if (otherData.toX == Double.MAX_VALUE) { final MoveData otherLastMove = otherData.moveData.getFirst();
if (!otherLastMove.toIsValid) {
// Data might have been removed. // Data might have been removed.
// TODO: Consider counting as tracked? // TODO: Consider counting as tracked?
continue; continue;
} }
else if (TrigUtil.isSamePos(refLoc, otherData.toX, otherData.toY, otherData.toZ)) { else if (TrigUtil.isSamePos(refLoc, otherLastMove.toX, otherLastMove.toY, otherLastMove.toZ)) {
// Tracked. // Tracked.
return null; return null;
} }
@ -163,7 +165,7 @@ public class MovingUtil {
// TODO: Discard locations in the same block, if passable. // TODO: Discard locations in the same block, if passable.
// TODO: Sanity check distance? // TODO: Sanity check distance?
// More leniency: allow moving inside of the same block. // More leniency: allow moving inside of the same block.
if (TrigUtil.isSameBlock(loc, otherData.toX, otherData.toY, otherData.toZ) && !BlockProperties.isPassable(refLoc.getWorld(), otherData.toX, otherData.toY, otherData.toZ)) { if (TrigUtil.isSameBlock(loc, otherLastMove.toX, otherLastMove.toY, otherLastMove.toZ) && !BlockProperties.isPassable(refLoc.getWorld(), otherLastMove.toX, otherLastMove.toY, otherLastMove.toZ)) {
continue; continue;
} }
untrackedData = otherData; untrackedData = otherData;
@ -176,7 +178,8 @@ public class MovingUtil {
} }
else { else {
// TODO: Count and log to TRACE_FILE, if multiple locations would match (!). // TODO: Count and log to TRACE_FILE, if multiple locations would match (!).
return new Location(loc.getWorld(), untrackedData.toX, untrackedData.toY, untrackedData.toZ, loc.getYaw(), loc.getPitch()); final MoveData lastMove = untrackedData.moveData.getFirst();
return new Location(loc.getWorld(), lastMove.toX, lastMove.toY, lastMove.toZ, loc.getYaw(), loc.getPitch());
} }
} }

View File

@ -4,10 +4,8 @@ import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.Check; import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.checks.net.model.DataPacketFlying; import fr.neatmonster.nocheatplus.checks.net.model.DataPacketFlying;
import fr.neatmonster.nocheatplus.utilities.CheckUtils; import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
/** /**
* Frequency of (pos/look/) flying packets checking. * Frequency of (pos/look/) flying packets checking.
@ -44,76 +42,4 @@ public class FlyingFrequency extends Check {
} }
} }
/**
* <b>Currently not used (too many potential and actual issues).</b><br>
* Skip packets that are not going to cause a moving event to fire, in case
* the frequency of packets is high.
*
* @param player
* @param packetData
* @param allScore
* @param time
* @param data
* @param cc
* @return
*/
@SuppressWarnings("unused")
private boolean checkRedundantPackets(final Player player, final DataPacketFlying packetData, final float allScore, final long time, final NetData data, final NetConfig cc) {
// TODO: Debug logging (better with integration into DataManager).
// TODO: Consider to compare to moving data directly, skip keeping track extra.
final MovingData mData = MovingData.getData(player);
if (mData.toX == Double.MAX_VALUE && mData.toYaw == Float.MAX_VALUE) {
// Can not check.
return false;
}
boolean onGroundSkip = false;
// Allow at least one on-ground change per state and second.
// TODO: Consider to verify on ground somehow (could tell MovingData the state).
if (packetData.onGround != data.flyingFrequencyOnGround) {
// Regard as not redundant only if sending the same state happened at least a second ago.
final long lastTime;
if (packetData.onGround) {
lastTime = data.flyingFrequencyTimeOnGround;
data.flyingFrequencyTimeOnGround = time;
} else {
lastTime = data.flyingFrequencyTimeNotOnGround;
data.flyingFrequencyTimeNotOnGround = time;
}
if (time < lastTime || time - lastTime > 1000) {
// Override
onGroundSkip = true;
}
}
data.flyingFrequencyOnGround = packetData.onGround;
if (packetData.hasPos) {
if (TrigUtil.distanceSquared(packetData.x, packetData.y, packetData.z, mData.toX, mData.toY, mData.toZ) > minMoveDistSq) {
return false;
}
}
if (packetData.hasLook) {
if (Math.abs(TrigUtil.yawDiff(packetData.yaw, mData.toYaw)) > minLookChange || Math.abs(TrigUtil.yawDiff(packetData.pitch, mData.toPitch)) > minLookChange) {
return false;
}
}
if (onGroundSkip) {
return false;
}
// Packet is redundant, if more than 20 packets per second arrive.
if (allScore / cc.flyingFrequencySeconds > 20f && !hasBypass(player)) {
// (Must re-check bypass here.)
data.flyingFrequencyRedundantFreq.add(time, 1f);
if (executeActions(player, data.flyingFrequencyRedundantFreq.score(1f) / cc.flyingFrequencyRedundantSeconds, 1.0 / cc.flyingFrequencyRedundantSeconds, cc.flyingFrequencyRedundantActions)) {
return true;
}
}
return false;
}
} }