Skip to content

Commit

Permalink
Refactor horizontal velocity to use an abstract AxisVelocity class.
Browse files Browse the repository at this point in the history
AxisVelocity will later represent per-axis velocity accounting for both
directions along an axis.

There have been no changes to the functionality, so it still only
accounts for positive values.
  • Loading branch information
asofold committed Aug 23, 2014
1 parent 53c0d95 commit 32a11f0
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 108 deletions.
@@ -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<Velocity> queued = new ArrayList<Velocity>();
private final List<Velocity> active = new ArrayList<Velocity>();

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<Velocity> it = queued.iterator();
while (it.hasNext()) {
it.next().actCount --;
}
}

/**
* Remove all velocity entries that are invalid. Checks both active and queued.
* <br>(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<Velocity> 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).
* <br>
* 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<Velocity> 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<Velocity> entries) {
for (final Velocity vel: entries) {
builder.append(" ");
builder.append(vel);
}
}

}
Expand Up @@ -96,7 +96,7 @@ public Location check(final Player player, final PlayerLocation from, final Play
}
}
else{
data.hVelActive.clear(); // TODO: test/check !
data.clearActiveHVel(); // TODO: test/check !
}

final boolean sprinting = time <= data.timeSprinting + cc.sprintingGrace;
Expand Down
@@ -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;
Expand Down Expand Up @@ -123,10 +120,8 @@ public static void onReload() {
public double verticalFreedom;
public double verticalVelocity;
public int verticalVelocityUsed = 0;
/** Active velocity entries (horizontal distance). */
public final List<Velocity> hVelActive = new LinkedList<Velocity>();
/** Queued velocity entries (horizontal distance). */
public final List<Velocity> hVelQueued = new LinkedList<Velocity>();
/** Horizontal velocity modeled as an axis (always positive) */
private final AxisVelocity hVel = new AxisVelocity();

// Coordinates.
/** Last from coordinates. */
Expand Down Expand Up @@ -524,16 +519,14 @@ public final void setTo(final Location to) {
* @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();
}

/**
Expand All @@ -542,86 +535,62 @@ public void removeAllVelocity() {
* @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<Velocity> 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();
}

/**
* Called for moving events, increase age of velocity, decrease amounts, check which entries are invalid. Both horizontal and vertical.
*/
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<Velocity> 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;
}
}
}

/**
* Get effective amount of all used velocity. Non-destructive.
* @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();
}

/**
Expand All @@ -633,19 +602,22 @@ public double getHorizontalFreedom() {
* @return
*/
public double useHorizontalVelocity(final double amount) {
final Iterator<Velocity> 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);
}
}

/**
Expand Down

0 comments on commit 32a11f0

Please sign in to comment.