[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.TraceEntry;
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.compat.BridgeEnchant;
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){
final MovingData mData = MovingData.getData(player);
// Check if fly checks is an issue at all, re-check "real sprinting".
if (mData.fromX != Double.MAX_VALUE && mData.liftOffEnvelope == LiftOffEnvelope.NORMAL) {
final double hDist = TrigUtil.distance(loc.getX(), loc.getZ(), mData.fromX, mData.fromZ);
final MoveData lastMove = mData.moveData.getFirst();
if (lastMove.valid && mData.liftOffEnvelope == LiftOffEnvelope.NORMAL) {
final double hDist = TrigUtil.distance(loc.getX(), loc.getZ(), lastMove.fromX, lastMove.fromZ);
if (hDist >= 0.23) {
// TODO: Might need to check hDist relative to speed / modifiers.
final MovingConfig mc = MovingConfig.getConfig(player);

View File

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

View File

@ -10,7 +10,6 @@ import org.bukkit.World;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.access.ACheckData;
import fr.neatmonster.nocheatplus.checks.access.CheckDataFactory;
import fr.neatmonster.nocheatplus.checks.access.ICheckData;
@ -127,16 +126,6 @@ public class MovingData extends ACheckData {
/** Last time the player was actually sprinting. */
public long timeSprinting = 0;
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. */
public SimpleEntry verVelUsed = null;
/** 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();
// 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." */
private LocationTrace trace = null;
@ -306,11 +289,7 @@ public class MovingData extends ACheckData {
sfJumpPhase = 0;
jumpAmplifier = 0;
setBack = null;
lastYDist = lastHDist = Double.MAX_VALUE;
lastFlyCheck = CheckType.UNKNOWN;
sfZeroVdist = 0;
fromX = toX = Double.MAX_VALUE;
toYaw = Float.MAX_VALUE;
clearAccounting();
clearNoFallData();
removeAllVelocity();
@ -370,8 +349,6 @@ public class MovingData extends ACheckData {
invalidateMoveData();
clearAccounting();
sfJumpPhase = 0;
lastYDist = lastHDist = Double.MAX_VALUE;
lastFlyCheck = CheckType.UNKNOWN;
sfZeroVdist = 0;
toWasReset = 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 y
* @param z
*/
public void resetPositions(final double x, final double y, final double z, final float yaw, final float pitch) {
invalidateMoveData();
moveData.get(0).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.
resetPositions();
moveData.getFirst().set(x, y, z, yaw, pitch);
}
/**
* Just reset the "last locations" references.
* Invalidate all past moves data and set last position if not null.
*
* @param 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
*/
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() {
resetPositions(Double.MAX_VALUE, 0.0, 0.0, Float.MAX_VALUE, 0f);
}
public void resetLastDistances() {
// TODO: Will change with moveData in use.
lastHDist = lastYDist = Double.MAX_VALUE;
}
/**
* Set positions according to a move (just to and from).
* @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();
invalidateMoveData();
sfZeroVdist = 0;
sfDirty = false;
sfLowJump = false;
liftOffEnvelope = defaultLiftOffEnvelope;
insideMediumCount = 0;
lastFrictionHorizontal = lastFrictionVertical = 0.0;
verticalBounce = null;
// TODO: other buffers ?
// No reset of vehicleConsistency.
}
/**
@ -702,18 +654,6 @@ public class MovingData extends ACheckData {
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.
* @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.model.LiftOffEnvelope;
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.velocity.AccountEntry;
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 MoveInfo moveInfo = useMoveInfo();
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)
|| 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.
//&& 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.
data.thisMove.set(pFrom, pTo);
final MoveData lastMove = data.moveData.getFirst();
// Potion effect "Jump".
final double jumpAmplifier = survivalFly.getJumpAmplifier(player);
@ -611,7 +615,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
// Fake use velocity here.
data.prependVerticalVelocity(new SimpleEntry(tick, 0.0, 1));
data.getOrUseVerticalVelocity(0.0);
if (data.lastYDist < 0.0) {
if (lastMove.toIsValid && lastMove.yDistance < 0.0) {
// Renew the bounce effect.
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.
if (data.lastFlyCheck == CheckType.MOVING_CREATIVEFLY && data.lastHDist != Double.MAX_VALUE) {
if (lastMove.toIsValid && lastMove.flyCheck == CheckType.MOVING_CREATIVEFLY) {
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) {
// CreativeFly
@ -714,7 +718,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
data.sfHoverTicks = -1;
data.sfLowJump = false;
data.lastFlyCheck = CheckType.MOVING_CREATIVEFLY;
data.thisMove.flyCheck = CheckType.MOVING_CREATIVEFLY;
}
else {
// No fly checking :(.
@ -740,14 +744,12 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
if (newTo == null) {
// Allowed move.
// Bounce effects.
if (verticalBounce) {
processBounce(player, pFrom.getY(), pTo.getY(), data, cc);
}
// Set positions.
data.setPositions(from, to);
data.lastHDist = data.thisMove.hDistance;
data.lastYDist = data.thisMove.yDistance;
// Finished move processing.
data.finishThisMove();
return false;
}
@ -766,9 +768,10 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
* @param 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.addVerticalVelocity(new SimpleEntry(data.lastYDist, 2));
data.addVerticalVelocity(new SimpleEntry(lastMove.yDistance, 2));
data.addVerticalVelocity(new SimpleEntry(0.0, 2));
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 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.
if (effect > 0.42) {
final MoveData lastMove = data.moveData.getFirst();
if (effect > 0.42 && lastMove.toIsValid) {
// 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) {
effect = max_gain;
if (data.debug) {
@ -976,7 +980,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
* @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) {
data.lastMoveTime = now; // TODO: Evaluate moving this to MovingData !?
data.lastMoveTime = now; // TODO: Move to MovingData ?
final String toWorldName = to.getWorld().getName();
Combined.feedYawRate(player, to.getYaw(), now, toWorldName, data);
// 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?
}
else if (!from.getWorld().getName().equals(toWorldName)) {
// A teleport event should follow.
mData.resetPositions(to);
mData.resetTrace(player, to, tick);
}
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);
}
}
@ -1091,7 +1103,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
if (TrigUtil.distance(from, to) < margin) {
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);
if (TrigUtil.distance(to.getX(), to.getY(), to.getZ(), setBack.getX(), setBack.getY(), setBack.getZ()) < margin) {
smallRange = true;
@ -1140,9 +1153,10 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
ref = data.getSetBack(to);
event.setTo(ref);
adjustLiftOffEnvelope(player, ref, data, cc);
data.resetPositions(ref);
}
else {
ref = from; // Player.getLocation ?
ref = from;
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 {
// "real" teleport
@ -1169,7 +1190,6 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
final LiftOffEnvelope oldEnv = data.liftOffEnvelope; // Remember for workarounds.
data.clearMorePacketsData();
data.clearFlyData();
data.resetPositions(to);
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).
// Keep old lift-off envelope.
@ -1190,6 +1210,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
data.noFallSkipAirCheck = true;
}
data.sfHoverTicks = -1; // Important against concurrent modification exception.
data.resetPositions(ref);
}
if (data.debug && BuildParameters.debugLevel > 0) {
@ -1208,9 +1229,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
// Reset stuff.
Combined.resetYawRate(player, ref.getYaw(), System.currentTimeMillis(), true);
Combined.resetYawRate(player, ref.getYaw(), System.currentTimeMillis(), true); // TODO: Not sure.
data.resetTeleported();
data.resetLastDistances();
// Prevent further moving processing for nested events.
processingEvents.remove(player.getName());
}
@ -1489,7 +1509,6 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
// (Note: resetPositions resets lastFlyCheck and other.)
data.resetLastDistances();
data.clearMorePacketsData();
data.removeAllVelocity();
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.
// TODO: Consider to catch all, at least (debug-) logging-wise.
if (!BlockProperties.isPassable(loc)) {
if (data.toX != Double.MAX_VALUE) {
final Location refLoc = new Location(loc.getWorld(), data.toX, data.toY, data.toZ);
final MoveData lastMove = data.moveData.getFirst();
if (lastMove.toIsValid) {
final Location refLoc = new Location(loc.getWorld(), lastMove.toX, lastMove.toY, lastMove.toZ);
final double d = refLoc.distanceSquared(loc);
if (d > 0.0) {
// TODO: Consider to always set back here. Might skip on big distances.
@ -1675,9 +1695,12 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
// TODO: What with the case of vehicle moved to another world !?
loc = vLoc; //
if (data.vehicleConsistency != MoveConsistency.INCONSISTENT) {
final Location oldLoc = new Location(pLoc.getWorld(), data.toX, data.toY, data.toZ);
if (data.toX != Double.MAX_VALUE && MoveConsistency.getConsistency(oldLoc, null, pLoc) != MoveConsistency.INCONSISTENT) {
loc = oldLoc;
final MoveData lastMove = data.moveData.getFirst();
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;
}
}
}
@ -1817,7 +1840,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
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.
// TODO: Add history / alert?
//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).
return data.getSetBack(loc);
} 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 {
return null;

View File

@ -1,16 +1,21 @@
package fr.neatmonster.nocheatplus.checks.moving.model;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.utilities.PlayerLocation;
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
*
*/
public class MoveData {
// TODO: Use objects for from and to (could lead to redesign, think of PlayerLocation)?
//////////////////////////////////////////
// Guaranteed to be initialized with set.
@ -21,25 +26,61 @@ public class MoveData {
*/
public boolean valid = false;
/** Double.MAX_VALUE if not available, e.g. after a teleport. */
public double yDistance = Double.MAX_VALUE;
/** Double.MAX_VALUE if not available, e.g. after a teleport. */
public double hDistance = Double.MAX_VALUE;
/**
* Start position coordinates.
*/
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, ...
//////////////////////////////////////////////////////////
// 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>
* 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;
/**
* 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/...
/**
@ -59,6 +100,17 @@ public class MoveData {
final double toX, final double toY, final double toZ, final float toYaw, final float toPitch) {
yDistance = toY - fromY;
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
*/
private void setPositions(final double x, final double y, final double z, final float yaw, final float pitch) {
yDistance = Double.MAX_VALUE;
hDistance = Double.MAX_VALUE;
this.fromX = x;
this.fromY = y;
this.fromZ = z;
this.fromYaw = yaw;
this.fromPitch = pitch;
toIsValid = false;
}
private void resetBase() {
headObstructed = false;
flyCheck = CheckType.UNKNOWN;
valid = true;
}
@ -109,6 +166,7 @@ public class MoveData {
*/
public void invalidate() {
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.moving.MovingConfig;
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.hooks.NCPExemptionManager;
import fr.neatmonster.nocheatplus.logging.StaticLog;
@ -149,12 +150,13 @@ public class MovingUtil {
if (TrigUtil.isSamePos(loc, refLoc) && (entity instanceof Player)) {
final Player other = (Player) entity;
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.
// TODO: Consider counting as tracked?
continue;
}
else if (TrigUtil.isSamePos(refLoc, otherData.toX, otherData.toY, otherData.toZ)) {
else if (TrigUtil.isSamePos(refLoc, otherLastMove.toX, otherLastMove.toY, otherLastMove.toZ)) {
// Tracked.
return null;
}
@ -163,7 +165,7 @@ public class MovingUtil {
// TODO: Discard locations in the same block, if passable.
// TODO: Sanity check distance?
// 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;
}
untrackedData = otherData;
@ -176,7 +178,8 @@ public class MovingUtil {
}
else {
// 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.CheckType;
import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.checks.net.model.DataPacketFlying;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
/**
* 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;
}
}