diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/CreativeFly.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/CreativeFly.java index 0a417f79..2f4388e6 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/CreativeFly.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/CreativeFly.java @@ -41,7 +41,10 @@ public class CreativeFly extends Check { * @param time Millis. * @return */ - public Location check(final Player player, final PlayerLocation from, final PlayerLocation to, final MoveData moveData, final MovingData data, final MovingConfig cc, final long time) { + public Location check(final Player player, final PlayerLocation from, final PlayerLocation to, final MovingData data, final MovingConfig cc, final long time) { + + // Edge data for this move. + final MoveData thisMove = data.thisMove; // Ensure we have a set-back location. if (!data.hasSetBack()) { @@ -59,8 +62,8 @@ public class CreativeFly extends Check { } // Calculate some distances. - final double yDistance = moveData.yDistance; - final double hDistance = moveData.hDistance; + final double yDistance = thisMove.yDistance; + final double hDistance = thisMove.hDistance; // Sprinting. final boolean sprinting = time <= data.timeSprinting + cc.sprintingGrace; diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingData.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingData.java index 932195ee..242f57ae 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingData.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingData.java @@ -1,6 +1,8 @@ package fr.neatmonster.nocheatplus.checks.moving; import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; import java.util.Map; import org.bukkit.Location; @@ -16,6 +18,7 @@ import fr.neatmonster.nocheatplus.checks.moving.locations.LocUtil; import fr.neatmonster.nocheatplus.checks.moving.locations.LocationTrace; 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.velocity.AccountEntry; import fr.neatmonster.nocheatplus.checks.moving.velocity.FrictionAxisVelocity; import fr.neatmonster.nocheatplus.checks.moving.velocity.SimpleAxisVelocity; @@ -146,6 +149,18 @@ public class MovingData extends ACheckData { public float walkSpeed = 0.0f; public float flySpeed = 0.0f; + /** + * Keep track of past moves edge data. First entry always is the last fully + * processed move, or invalid, even during processing. The currently + * processed move always is thisMove. The list length always stays the same. + */ + public final LinkedList moveData = new LinkedList(); + /** + * The move currently being processed. Will be inserted to first position + * when done, and exchanged for the invalidated last element of moveData. + */ + public MoveData thisMove = new MoveData(); + // Velocity handling. /** Vertical velocity modeled as an axis (positive and negative possible) */ private final SimpleAxisVelocity verVel = new SimpleAxisVelocity(); @@ -254,12 +269,39 @@ public class MovingData extends ACheckData { super(config); morePacketsFreq = new ActionFrequency(config.morePacketsEPSBuckets, 500); morePacketsBurstFreq = new ActionFrequency(12, 5000); + + // Past moves data: initialize with dummies. + for (int i = 0; i < 2; i++) { // Two past moves allow better workarounds than 1. + moveData.add(new MoveData()); + } + } + + /** + * Invalidate thisMove and all elements in moveData. + */ + private void invalidateMoveData() { + final Iterator it = moveData.iterator(); + while (it.hasNext()) { + it.next().invalidate(); + } + thisMove.invalidate(); + } + + /** + * Call after processing with a valid thisMove field. Insert thisMove as + * first in moveData, set thisMove to invalidated last element of moveData. + */ + public void finishThisMove() { + moveData.addFirst(thisMove); + thisMove = moveData.removeLast(); + thisMove.invalidate(); } /** * Clear the data of the fly checks (not more-packets). */ public void clearFlyData() { + invalidateMoveData(); bunnyhopDelay = 0; sfJumpPhase = 0; jumpAmplifier = 0; @@ -325,6 +367,7 @@ public class MovingData extends ACheckData { * Move event: Mildly reset some data, prepare setting a new to-Location. */ public void prepareSetBack(final Location loc) { + invalidateMoveData(); clearAccounting(); sfJumpPhase = 0; lastYDist = lastHDist = Double.MAX_VALUE; @@ -398,12 +441,14 @@ public class MovingData extends ACheckData { } /** - * Just reset the "last locations" references. + * Reset edge data for last moves. * @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; @@ -456,6 +501,7 @@ public class MovingData extends ACheckData { } public void resetLastDistances() { + // TODO: Will change with moveData in use. lastHDist = lastYDist = Double.MAX_VALUE; } @@ -465,6 +511,7 @@ public class MovingData extends ACheckData { * @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(); diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java index 1bcdfa45..d8c0b00a 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java @@ -544,7 +544,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo } // Set some data for this move. - moveInfo.data.set(pFrom, pTo); + data.thisMove.set(pFrom, pTo); // Potion effect "Jump". final double jumpAmplifier = survivalFly.getJumpAmplifier(player); @@ -665,7 +665,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo // Actual check. if (newTo == null) { // Only check if passable has not already set back. - newTo = survivalFly.check(player, pFrom, pTo, isSamePos, mightBeMultipleMoves, moveInfo.data, data, cc, time); + newTo = survivalFly.check(player, pFrom, pTo, isSamePos, mightBeMultipleMoves, data, cc, time); } // Only check NoFall, if not already vetoed. if (checkNf) { @@ -710,7 +710,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo else if (checkCf) { // CreativeFly if (newTo == null) { - newTo = creativeFly.check(player, pFrom, pTo, moveInfo.data, data, cc, time); + newTo = creativeFly.check(player, pFrom, pTo, data, cc, time); } data.sfHoverTicks = -1; data.sfLowJump = false; @@ -745,10 +745,10 @@ public class MovingListener extends CheckListener implements TickListener, IRemo processBounce(player, pFrom.getY(), pTo.getY(), data, cc); } // Set positions. - // TODO: Consider setting in Monitor (concept missing for changing coordinates, could double-check). data.setPositions(from, to); - data.lastHDist = moveInfo.data.hDistance; - data.lastYDist = moveInfo.data.yDistance; + data.lastHDist = data.thisMove.hDistance; + data.lastYDist = data.thisMove.yDistance; + data.finishThisMove(); return false; } else { @@ -905,7 +905,9 @@ public class MovingListener extends CheckListener implements TickListener, IRemo */ @EventHandler(priority=EventPriority.MONITOR, ignoreCancelled = false) public void onPlayerMoveMonitor(final PlayerMoveEvent event) { - // TODO: revise: cancelled events. + + // TODO: Use stored move data to verify if from/to have changed (thus a teleport will result, possibly a minor issue due to the teleport). + final long now = System.currentTimeMillis(); final Player player = event.getPlayer(); @@ -952,6 +954,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo * @param data */ private void onCancelledMove(final Player player, final Location from, final int tick, final long now, final MovingData mData, final CombinedData data) { + // TODO: Revise handling of cancelled events. data.lastMoveTime = now; // TODO: Move to MovingData? // TODO: teleported + other resetting ? Combined.feedYawRate(player, from.getYaw(), now, from.getWorld().getName(), data); diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java index 6c04e0c3..1b7895a5 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java @@ -121,8 +121,9 @@ public class SurvivalFly extends Check { * @param isSamePos * @return the location */ - public Location check(final Player player, final PlayerLocation from, final PlayerLocation to, final boolean isSamePos, final boolean mightBeMultipleMoves, final MoveData moveData, final MovingData data, final MovingConfig cc, final long now) { + public Location check(final Player player, final PlayerLocation from, final PlayerLocation to, final boolean isSamePos, final boolean mightBeMultipleMoves, final MovingData data, final MovingConfig cc, final long now) { tags.clear(); + final MoveData thisMove = data.thisMove; // Calculate some distances. final double xDistance, yDistance, zDistance, hDistance; @@ -133,14 +134,14 @@ public class SurvivalFly extends Check { hasHdist = false; } else { xDistance = to.getX() - from.getX(); - yDistance = moveData.yDistance; + yDistance = thisMove.yDistance; zDistance = to.getZ() - from.getZ(); if (xDistance == 0.0 && zDistance == 0.0) { hDistance = 0.0; hasHdist = false; } else { hasHdist = true; - hDistance = moveData.hDistance; + hDistance = thisMove.hDistance; } } diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/locations/MoveInfo.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/locations/MoveInfo.java index 2eca4478..b4db515e 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/locations/MoveInfo.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/locations/MoveInfo.java @@ -3,7 +3,6 @@ package fr.neatmonster.nocheatplus.checks.moving.locations; import org.bukkit.Location; import org.bukkit.entity.Player; -import fr.neatmonster.nocheatplus.checks.moving.model.MoveData; import fr.neatmonster.nocheatplus.compat.MCAccess; import fr.neatmonster.nocheatplus.utilities.BlockCache; import fr.neatmonster.nocheatplus.utilities.PlayerLocation; @@ -25,8 +24,6 @@ public class MoveInfo { public final BlockCache cache; public final PlayerLocation from; public final PlayerLocation to; - /** Not initialized in set. */ - public final MoveData data = new MoveData(); public MoveInfo(final MCAccess mcAccess){ cache = mcAccess.getBlockCache(null); @@ -65,7 +62,6 @@ public class MoveInfo { from.cleanup(); to.cleanup(); cache.cleanup(); - data.reset(); } } diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/model/MoveData.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/model/MoveData.java index fe0879d0..89a94df8 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/model/MoveData.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/model/MoveData.java @@ -4,26 +4,97 @@ import fr.neatmonster.nocheatplus.utilities.PlayerLocation; import fr.neatmonster.nocheatplus.utilities.TrigUtil; /** - * Carry data of a move, involving from- and to- location. + * Carry data of a move, involving from- and to- locations. * * @author asofold * */ public class MoveData { - // TODO: Invalidation flag? + + ///////////////////////////// + // Guaranteed to be set. + ///////////////////////////// + /** + * Indicate if data has been set. Likely there will be sets of properties + * with a flag for each such set. + */ + public boolean valid = false; public double yDistance = Double.MAX_VALUE; public double hDistance = Double.MAX_VALUE; - public void set(PlayerLocation from, PlayerLocation to) { - yDistance = to.getY()- from.getY(); - hDistance = TrigUtil.xzDistance(from, to); + // TODO: Last coords, + // TODO: Velocity used, fly check, ... + + + ///////////////////////////// + // Not guaranteed to be set. + ///////////////////////////// + + public boolean headObstructed = false; + + // TODO: ground/reset/web/... + + + /** + * Set the minimal properties, likely to be used. + * + * @param from + * @param to + */ + public void set(final PlayerLocation from, final PlayerLocation to) { + set(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch(), + to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch()); } - public void reset() { - yDistance = Double.MAX_VALUE; - hDistance = Double.MAX_VALUE; + /** + * Set some basic move edge data and reset all other properties properly. + * @param fromX + * @param fromY + * @param fromZ + * @param toX + * @param toY + * @param toZ + */ + public void set(final double fromX, final double fromY, final double fromZ, final float fromYaw, final float fromPitch, + 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); + headObstructed = false; + // Set Valid last. + valid = true; } + /** + * Set with teleport / set-back. + * @param x + * @param y + * @param z + * @param yaw + * @param pitch + */ + public void set(final double x, final double y, final double z, final float yaw, final float pitch) { + yDistance = Double.MAX_VALUE; // TODO: 0 ? + hDistance = Double.MAX_VALUE; // TODO: 0 ? + headObstructed = false; + valid = true; + } + + /** + * Fast invalidation: just set the flags. + */ + public void invalidate() { + valid = false; + } + + // public void reset() { + // // TODO: Might not need this method: it's always set(...) or set invalid to true. + // valid = false; + // // Reset properties after resetting valid. + // yDistance = Double.MAX_VALUE; + // hDistance = Double.MAX_VALUE; + // headObstructed = false; + // } + }