diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/AxisVelocity.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/AxisVelocity.java new file mode 100644 index 00000000..f74a8938 --- /dev/null +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/AxisVelocity.java @@ -0,0 +1,157 @@ +package fr.neatmonster.nocheatplus.checks.moving; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Velocity accounting for one axis (positive + negative direction). + * @author dev1mc + * + */ +public class AxisVelocity { + + private final List queued = new ArrayList(); + private final List active = new ArrayList(); + + public void add(Velocity vel) { + // TODO: Merging behavior? + queued.add(vel); + } + + public boolean hasActive() { + return !active.isEmpty(); + } + + public boolean hasQueued() { + return !queued.isEmpty(); + } + + /** + * Called for moving events, increase age of velocity, decrease amounts, check which entries are invalid. Both horizontal and vertical. + */ + public void tick() { + // Decrease counts for active. + // TODO: Actual friction. Could pass as an argument (special value for not to be used). + // TODO: Consider removing already invalidated here. + for (final Velocity vel : active) { + vel.valCount --; + vel.sum += vel.value; + vel.value *= 0.93; // vel.frictionFactor; + // (Altered entries should be kept, since they get used right away.) + } + // Decrease counts for queued. + final Iterator it = queued.iterator(); + while (it.hasNext()) { + it.next().actCount --; + } + } + + /** + * Remove all velocity entries that are invalid. Checks both active and queued. + *
(This does not catch invalidation by speed / direction changing.) + * @param tick All velocity added before this tick gets removed. + */ + public void removeInvalid(final int tick) { + // TODO: Also merge entries here, or just on adding? + Iterator it; + // Active. + it = active.iterator(); + while (it.hasNext()) { + final Velocity vel = it.next(); + // TODO: 0.001 can be stretched somewhere else, most likely... + // TODO: Somehow use tick here too (actCount, valCount)? + if (vel.valCount <= 0 || vel.value <= 0.001) { +// System.out.prsintln("Invalidate active: " + vel); + it.remove(); + } + } + // Queued. + it = queued.iterator(); + while (it.hasNext()) { + final Velocity vel = it.next(); + if (vel.actCount <= 0 || vel.tick < tick) { +// System.out.println("Invalidate queued: " + vel); + it.remove(); + } + } + } + + /** + * Get the sum of active velocity values. + * @return + */ + public double getFreedom() { + // TODO: model/calculate it as accurate as possible... + double f = 0; + for (final Velocity vel : active) { + f += vel.value; + } + return f; + } + + /** + * Use all queued velocity until at least amount is matched. + * Amount is the horizontal distance that is to be covered by velocity (active has already been checked). + *
+ * If the modeling changes (max instead of sum or similar), then this will be affected. + * @param amount The amount used. + * @return + */ + public double use(final double amount) { + final Iterator it = queued.iterator(); + double used = 0; + while (it.hasNext()) { + final Velocity vel = it.next(); + used += vel.value; + active.add(vel); + it.remove(); + if (used >= amount) { + break; + } + } + // TODO: Add to sum. + return used; + } + + public void clearActive() { + active.clear(); + } + + /** + * Clear active and queued velocity entries. + */ + public void clear() { + queued.clear(); + active.clear(); + } + + /** + * Debugging. + * @param builder + */ + public void AddQueued(StringBuilder builder) { + addVeloctiy(builder, queued); + } + + /** + * Debugging. + * @param builder + */ + public void addActive(StringBuilder builder) { + addVeloctiy(builder, active); + } + + /** + * Debugging. + * @param builder + * @param entries + */ + private void addVeloctiy(final StringBuilder builder, final List entries) { + for (final Velocity vel: entries) { + builder.append(" "); + builder.append(vel); + } + } + +} 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 a3fd97b4..3c14d25f 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 @@ -96,7 +96,7 @@ public class CreativeFly extends Check { } } else{ - data.hVelActive.clear(); // TODO: test/check ! + data.clearActiveHVel(); // TODO: test/check ! } 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 b6cc028e..3768426b 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,9 +1,6 @@ package fr.neatmonster.nocheatplus.checks.moving; import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; import java.util.Map; import org.bukkit.Location; @@ -123,10 +120,8 @@ public class MovingData extends ACheckData { public double verticalFreedom; public double verticalVelocity; public int verticalVelocityUsed = 0; - /** Active velocity entries (horizontal distance). */ - public final List hVelActive = new LinkedList(); - /** Queued velocity entries (horizontal distance). */ - public final List hVelQueued = new LinkedList(); + /** Horizontal velocity modeled as an axis (always positive) */ + private final AxisVelocity hVel = new AxisVelocity(); // Coordinates. /** Last from coordinates. */ @@ -524,16 +519,14 @@ public class MovingData extends ACheckData { * @param vel */ public void addHorizontalVelocity(final Velocity vel) { - // TODO: Might merge entries ! - hVelQueued.add(vel); + hVel.add(vel); } /** * Currently only applies to horizontal velocity. */ public void removeAllVelocity() { - hVelActive.clear(); - hVelQueued.clear(); + hVel.clear(); } /** @@ -542,28 +535,22 @@ public class MovingData extends ACheckData { * @param tick All velocity added before this tick gets removed. */ public void removeInvalidVelocity(final int tick) { - // TODO: Also merge entries here, or just on adding? - Iterator it; - // Active. - it = hVelActive.iterator(); - while (it.hasNext()) { - final Velocity vel = it.next(); - // TODO: 0.001 can be stretched somewhere else, most likely... - // TODO: Somehow use tick here too (actCount, valCount)? - if (vel.valCount <= 0 || vel.value <= 0.001) { -// System.out.prsintln("Invalidate active: " + vel); - it.remove(); - } - } - // Queued. - it = hVelQueued.iterator(); - while (it.hasNext()) { - final Velocity vel = it.next(); - if (vel.actCount <= 0 || vel.tick < tick) { -// System.out.println("Invalidate queued: " + vel); - it.remove(); - } - } + hVel.removeInvalid(tick); + } + + /** + * Clear only active horizontal velocity. + */ + public void clearActiveHVel() { + hVel.clearActive(); + } + + public boolean hasActiveHVel() { + return hVel.hasActive(); + } + + public boolean hasQueuedHVel() { + return hVel.hasQueued(); } /** @@ -571,44 +558,31 @@ public class MovingData extends ACheckData { */ public void velocityTick() { // Horizontal velocity (intermediate concept). - // Decrease counts for active. - // TODO: Actual friction. Could pass as an argument (special value for not to be used). - // TODO: Consider removing already invalidated here. - for (final Velocity vel : hVelActive) { - vel.valCount --; - vel.sum += vel.value; - vel.value *= 0.93; // vel.frictionFactor; - // (Altered entries should be kept, since they get used right away.) - } - // Decrease counts for queued. - final Iterator it = hVelQueued.iterator(); - while (it.hasNext()) { - it.next().actCount --; - } + hVel.tick(); // Vertical velocity (old concept). - if (verticalVelocity <= 0.09D) { - verticalVelocityUsed ++; - verticalVelocityCounter--; - } - else if (verticalVelocityCounter > 0) { - verticalVelocityUsed ++; - verticalFreedom += verticalVelocity; - verticalVelocity = Math.max(0.0, verticalVelocity -0.09); - // TODO: Consider using up counter ? / better use velocity entries / even better use x,y,z entries right away . - } else if (verticalFreedom > 0.001D) { - if (verticalVelocityUsed == 1 && verticalVelocity > 1.0) { - // Workarounds. - verticalVelocityUsed = 0; - verticalVelocity = 0; - verticalFreedom = 0; - } - else{ - // Counter has run out, now reduce the vertical freedom over time. - verticalVelocityUsed ++; - verticalFreedom *= 0.93D; - } - } + if (verticalVelocity <= 0.09D) { + verticalVelocityUsed ++; + verticalVelocityCounter--; + } + else if (verticalVelocityCounter > 0) { + verticalVelocityUsed ++; + verticalFreedom += verticalVelocity; + verticalVelocity = Math.max(0.0, verticalVelocity -0.09); + // TODO: Consider using up counter ? / better use velocity entries / even better use x,y,z entries right away . + } else if (verticalFreedom > 0.001D) { + if (verticalVelocityUsed == 1 && verticalVelocity > 1.0) { + // Workarounds. + verticalVelocityUsed = 0; + verticalVelocity = 0; + verticalFreedom = 0; + } + else{ + // Counter has run out, now reduce the vertical freedom over time. + verticalVelocityUsed ++; + verticalFreedom *= 0.93D; + } + } } /** @@ -616,12 +590,7 @@ public class MovingData extends ACheckData { * @return */ public double getHorizontalFreedom() { - // TODO: model/calculate it as accurate as possible... - double f = 0; - for (final Velocity vel : hVelActive) { - f += vel.value; - } - return f; + return hVel.getFreedom(); } /** @@ -633,19 +602,22 @@ public class MovingData extends ACheckData { * @return */ public double useHorizontalVelocity(final double amount) { - final Iterator it = hVelQueued.iterator(); - double used = 0; - while (it.hasNext()) { - final Velocity vel = it.next(); - used += vel.value; - hVelActive.add(vel); - it.remove(); - if (used >= amount) { - break; - } - } - // TODO: Add to sum. - return used; + return hVel.use(amount); + } + + /** + * Debugging. + * @param builder + */ + public void addHorizontalVelocity(final StringBuilder builder) { + if (hVel.hasActive()) { + builder.append("\n" + " horizontal velocity (active):"); + hVel.addActive(builder); + } + if (hVel.hasQueued()) { + builder.append("\n" + " horizontal velocity (queued):"); + hVel.AddQueued(builder); + } } /** 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 6f5e5398..45d1fd95 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 @@ -2,7 +2,6 @@ package fr.neatmonster.nocheatplus.checks.moving; import java.util.ArrayList; import java.util.HashSet; -import java.util.List; import java.util.Locale; import java.util.Set; @@ -205,7 +204,7 @@ public class SurvivalFly extends Check { hFreedom = res[2]; } else{ - data.hVelActive.clear(); + data.clearActiveHVel(); hFreedom = 0.0; if (resetFrom && data.bunnyhopDelay <= 6) { data.bunnyhopDelay = 0; @@ -224,7 +223,7 @@ public class SurvivalFly extends Check { } // Prevent players from sprinting if they're moving backwards (allow buffers to cover up !?). - if (sprinting && data.lostSprintCount == 0 && !cc.assumeSprint && hDistance > walkSpeed && data.hVelActive.isEmpty()) { + if (sprinting && data.lostSprintCount == 0 && !cc.assumeSprint && hDistance > walkSpeed && !data.hasActiveHVel()) { // (Ignore some cases, in order to prevent false positives.) // TODO: speed effects ? if (TrigUtil.isMovingBackwards(xDistance, zDistance, from.getYaw()) && !player.hasPermission(Permissions.MOVING_SURVIVALFLY_SPRINTING)) { @@ -475,7 +474,7 @@ public class SurvivalFly extends Check { // TODO: Should there be other side conditions? // Invalidate used horizontal velocity. // System.out.println("*** INVALIDATE ON SPEED"); - data.hVelActive.clear(); + data.clearActiveHVel(); // if (data.horizontalVelocityUsed > cc.velocityGraceTicks) { // data.horizontalFreedom = 0; // data.horizontalVelocityCounter = 0; @@ -1408,14 +1407,7 @@ public class SurvivalFly extends Check { // if (data.horizontalVelocityCounter > 0 || data.horizontalFreedom >= 0.001) { // builder.append("\n" + player.getName() + " horizontal freedom: " + StringUtil.fdec3.format(data.horizontalFreedom) + " (counter=" + data.horizontalVelocityCounter +"/used="+data.horizontalVelocityUsed); // } - if (!data.hVelActive.isEmpty()) { - builder.append("\n" + " horizontal velocity (active):"); - addVeloctiy(builder, data.hVelActive); - } - if (!data.hVelQueued.isEmpty()) { - builder.append("\n" + " horizontal velocity (queued):"); - addVeloctiy(builder, data.hVelQueued); - } + data.addHorizontalVelocity(builder); if (!resetFrom && !resetTo) { if (cc.survivalFlyAccountingV && data.vDistAcc.count() > data.vDistAcc.bucketCapacity()) builder.append("\n" + " vacc=" + data.vDistAcc.toInformalString()); } @@ -1430,11 +1422,4 @@ public class SurvivalFly extends Check { System.out.print(builder.toString()); } - private void addVeloctiy(final StringBuilder builder, final List entries) { - for (final Velocity vel: entries) { - builder.append(" "); - builder.append(vel); - } - } - }