[SAFETY COMMIT] Freeze changes to vertical velocity.

Since other fixes migth be in focus, some changes are commited
merged/commented out:
* Prepare AxisVelocity to carry positive and negative values.
* Prepare MovingData to use vertical AxisVelocity. Rename hVel.
* Prepare CreativeFly (...), do not count velocity for height limit.

(Most preparations were unfinished, just hinting at the direction.)
This commit is contained in:
asofold 2014-10-10 15:15:22 +02:00
parent 3ea098876f
commit af974a85ac
4 changed files with 100 additions and 38 deletions

View File

@ -11,12 +11,19 @@ import java.util.List;
*/ */
public class AxisVelocity { public class AxisVelocity {
/** Velocity with a smaller absolute amount is removed. */
private static final double minValue = 0.001;
private static final double frictionFactor = 0.93;
private final List<Velocity> queued = new ArrayList<Velocity>(); private final List<Velocity> queued = new ArrayList<Velocity>();
private final List<Velocity> active = new ArrayList<Velocity>(); private final List<Velocity> active = new ArrayList<Velocity>();
public void add(Velocity vel) { public void add(Velocity vel) {
// TODO: Merging behavior? // TODO: Merging behavior?
queued.add(vel); if (Math.abs(vel.value) != 0.0) {
queued.add(vel);
}
} }
public boolean hasActive() { public boolean hasActive() {
@ -34,10 +41,11 @@ public class AxisVelocity {
// Decrease counts for active. // Decrease counts for active.
// TODO: Actual friction. Could pass as an argument (special value for not to be used). // TODO: Actual friction. Could pass as an argument (special value for not to be used).
// TODO: Consider removing already invalidated here. // TODO: Consider removing already invalidated here.
// TODO: Consider working removeInvalid into this ?
for (final Velocity vel : active) { for (final Velocity vel : active) {
vel.valCount --; vel.valCount --;
vel.sum += vel.value; vel.sum += vel.value;
vel.value *= 0.93; // vel.frictionFactor; vel.value *= frictionFactor; // vel.frictionFactor;
// (Altered entries should be kept, since they get used right away.) // (Altered entries should be kept, since they get used right away.)
} }
// Decrease counts for queued. // Decrease counts for queued.
@ -61,7 +69,7 @@ public class AxisVelocity {
final Velocity vel = it.next(); final Velocity vel = it.next();
// TODO: 0.001 can be stretched somewhere else, most likely... // TODO: 0.001 can be stretched somewhere else, most likely...
// TODO: Somehow use tick here too (actCount, valCount)? // TODO: Somehow use tick here too (actCount, valCount)?
if (vel.valCount <= 0 || vel.value <= 0.001) { if (vel.valCount <= 0 || Math.abs(vel.value) <= minValue) {
// System.out.prsintln("Invalidate active: " + vel); // System.out.prsintln("Invalidate active: " + vel);
it.remove(); it.remove();
} }
@ -69,6 +77,7 @@ public class AxisVelocity {
// Queued. // Queued.
it = queued.iterator(); it = queued.iterator();
while (it.hasNext()) { while (it.hasNext()) {
// TODO: Could check for alternating signum (error).
final Velocity vel = it.next(); final Velocity vel = it.next();
if (vel.actCount <= 0 || vel.tick < tick) { if (vel.actCount <= 0 || vel.tick < tick) {
// System.out.println("Invalidate queued: " + vel); // System.out.println("Invalidate queued: " + vel);
@ -79,10 +88,10 @@ public class AxisVelocity {
/** /**
* Get the sum of active velocity values. * Get the sum of active velocity values.
* @return * @return Can be positive or negative.
*/ */
public double getFreedom() { public double getFreedom() {
// TODO: model/calculate it as accurate as possible... // TODO: model/calculate it as accurate as possible...
double f = 0; double f = 0;
for (final Velocity vel : active) { for (final Velocity vel : active) {
f += vel.value; f += vel.value;
@ -95,18 +104,31 @@ public class AxisVelocity {
* Amount is the horizontal distance that is to be covered by velocity (active has already been checked). * Amount is the horizontal distance that is to be covered by velocity (active has already been checked).
* <br> * <br>
* If the modeling changes (max instead of sum or similar), then this will be affected. * If the modeling changes (max instead of sum or similar), then this will be affected.
* @param amount The amount used. * @param amount The amount used, should be negative or positive depending on direction.
* @return * @return
*/ */
public double use(final double amount) { public double use(final double amount) {
if (!active.isEmpty()) {
// Invalidate active on "direction change" [direction of consumption].
if (amount * active.get(0).value < 0.0) {
active.clear();
}
}
final Iterator<Velocity> it = queued.iterator(); final Iterator<Velocity> it = queued.iterator();
double used = 0; double used = 0;
while (it.hasNext()) { while (it.hasNext()) {
final Velocity vel = it.next(); final Velocity vel = it.next();
if (vel.value * amount < 0.0) {
// Not aligned.
// TODO: This could be a problem with small amounts of velocity.
// TODO: break or remove !? -> need find "next fitting one" and remove all non-fitting before (iff fitting found) ...
it.remove(); // TODO: queues ~ continue? vs. invalidate (remove) vs. break; vs. collect and invalidate non-matching BEFORE.
continue;
}
used += vel.value; used += vel.value;
active.add(vel); active.add(vel);
it.remove(); it.remove();
if (used >= amount) { if (Math.abs(used) >= Math.abs(amount)) {
break; break;
} }
} }

View File

@ -50,9 +50,10 @@ public class CreativeFly extends Check {
// Before doing anything, do a basic height check to determine if players are flying too high. // Before doing anything, do a basic height check to determine if players are flying too high.
final int maximumHeight = cc.creativeFlyMaxHeight + player.getWorld().getMaxHeight(); final int maximumHeight = cc.creativeFlyMaxHeight + player.getWorld().getMaxHeight();
if (to.getY() - data.verticalFreedom > maximumHeight) if (to.getY() > maximumHeight) {
return new Location(player.getWorld(), data.getSetBackX(), maximumHeight - 10D, data.getSetBackZ(), // TODO: USE velocity if possible.
to.getYaw(), to.getPitch()); return new Location(player.getWorld(), data.getSetBackX(), Math.max(maximumHeight - 10D, to.getWorld().getMaxHeight()), data.getSetBackZ(), to.getYaw(), to.getPitch());
}
// Calculate some distances. // Calculate some distances.
final double xDistance = to.getX() - from.getX(); final double xDistance = to.getX() - from.getX();
@ -96,7 +97,7 @@ public class CreativeFly extends Check {
} }
} }
else{ else{
data.clearActiveHVel(); // TODO: test/check ! data.clearActiveHorVel(); // TODO: test/check !
} }
final boolean sprinting = time <= data.timeSprinting + cc.sprintingGrace; final boolean sprinting = time <= data.timeSprinting + cc.sprintingGrace;
@ -119,8 +120,16 @@ public class CreativeFly extends Check {
// Super simple, just check distance compared to max distance vertical. // Super simple, just check distance compared to max distance vertical.
// TODO: max descending speed ! [max fall speed, use maximum with speed or added ?] // TODO: max descending speed ! [max fall speed, use maximum with speed or added ?]
// TODO:_ signum considerations (aligned ...).
// double vDistanceAboveLimit = yDistance - data.getVerticalFreedom() - limitV;
// if (vDistanceAboveLimit > 0.0) {
// // TODO: consume / use vvel
// }
// final double resultV = (vDistanceAboveLimit - limitV) * 100D;
// final double result = Math.max(0.0, resultH) + Math.max(0D, resultV);
// Old handling.
final double resultV = (yDistance - data.verticalFreedom - limitV) * 100D; final double resultV = (yDistance - data.verticalFreedom - limitV) * 100D;
final double result = Math.max(0.0, resultH) + Math.max(0D, resultV); final double result = Math.max(0.0, resultH) + Math.max(0D, resultV);
// The player went to far, either horizontal or vertical. // The player went to far, either horizontal or vertical.

View File

@ -116,12 +116,15 @@ public class MovingData extends ACheckData {
// Velocity handling. // Velocity handling.
// TODO: consider resetting these with clearFlyData and onSetBack. // TODO: consider resetting these with clearFlyData and onSetBack.
/** Vertical velocity modeled as an axis (positive and negative possible) */
//private final AxisVelocity verVel = new AxisVelocity();
public int verticalVelocityCounter; public int verticalVelocityCounter;
public double verticalFreedom; public double verticalFreedom;
public double verticalVelocity; public double verticalVelocity;
public int verticalVelocityUsed = 0; public int verticalVelocityUsed = 0;
/** Horizontal velocity modeled as an axis (always positive) */ /** Horizontal velocity modeled as an axis (always positive) */
private final AxisVelocity hVel = new AxisVelocity(); private final AxisVelocity horVel = new AxisVelocity();
// Coordinates. // Coordinates.
/** Last from coordinates. */ /** Last from coordinates. */
@ -515,18 +518,26 @@ public class MovingData extends ACheckData {
/** /**
* Add horizontal velocity (distance). <br> * Add horizontal velocity (distance). <br>
* Since velocity is seldom an access method should be better. Flying players are expensive anyway, so this should not matter too much. * @param vel Assumes positive values always.
* @param vel
*/ */
public void addHorizontalVelocity(final Velocity vel) { public void addHorizontalVelocity(final Velocity vel) {
hVel.add(vel); horVel.add(vel);
}
/**
* Add vertical velocity (distance). <br>
* @param vel
*/
public void addVerticalVelocity(final Velocity vel) {
horVel.add(vel);
} }
/** /**
* Currently only applies to horizontal velocity. * Remove all vertical and horizontal velocity.
*/ */
public void removeAllVelocity() { public void removeAllVelocity() {
hVel.clear(); horVel.clear();
// verVel.clear();
} }
/** /**
@ -535,32 +546,49 @@ public class MovingData extends ACheckData {
* @param tick All velocity added before this tick gets removed. * @param tick All velocity added before this tick gets removed.
*/ */
public void removeInvalidVelocity(final int tick) { public void removeInvalidVelocity(final int tick) {
hVel.removeInvalid(tick); horVel.removeInvalid(tick);
// verVel.removeInvalid(tick);
} }
/** /**
* Clear only active horizontal velocity. * Clear only active horizontal velocity.
*/ */
public void clearActiveHVel() { public void clearActiveHorVel() {
hVel.clearActive(); horVel.clearActive();
}
/**
* Clear only active horizontal velocity.
*/
public void clearActiveVerVel() {
horVel.clearActive();
} }
public boolean hasActiveHVel() { public boolean hasActiveHorVel() {
return hVel.hasActive(); return horVel.hasActive();
} }
public boolean hasQueuedHVel() { public boolean hasQueuedHorVel() {
return hVel.hasQueued(); return horVel.hasQueued();
} }
// public boolean hasActiveVerVel() {
// return verVel.hasActive();
// }
// public boolean hasQueuedVerVel() {
// return verVel.hasQueued();
// }
/** /**
* Called for moving events, increase age of velocity, decrease amounts, check which entries are invalid. Both horizontal and vertical. * Called for moving events, increase age of velocity, decrease amounts, check which entries are invalid. Both horizontal and vertical.
*/ */
public void velocityTick() { public void velocityTick() {
// Horizontal velocity (intermediate concept). // Horizontal velocity (intermediate concept).
hVel.tick(); horVel.tick();
// Vertical velocity (old concept). // Vertical velocity (new concept).
// verVel.tick();
if (verticalVelocity <= 0.09D) { if (verticalVelocity <= 0.09D) {
verticalVelocityUsed ++; verticalVelocityUsed ++;
verticalVelocityCounter--; verticalVelocityCounter--;
@ -590,7 +618,7 @@ public class MovingData extends ACheckData {
* @return * @return
*/ */
public double getHorizontalFreedom() { public double getHorizontalFreedom() {
return hVel.getFreedom(); return horVel.getFreedom();
} }
/** /**
@ -602,7 +630,7 @@ public class MovingData extends ACheckData {
* @return * @return
*/ */
public double useHorizontalVelocity(final double amount) { public double useHorizontalVelocity(final double amount) {
return hVel.use(amount); return horVel.use(amount);
} }
/** /**
@ -610,13 +638,13 @@ public class MovingData extends ACheckData {
* @param builder * @param builder
*/ */
public void addHorizontalVelocity(final StringBuilder builder) { public void addHorizontalVelocity(final StringBuilder builder) {
if (hVel.hasActive()) { if (horVel.hasActive()) {
builder.append("\n" + " horizontal velocity (active):"); builder.append("\n" + " horizontal velocity (active):");
hVel.addActive(builder); horVel.addActive(builder);
} }
if (hVel.hasQueued()) { if (horVel.hasQueued()) {
builder.append("\n" + " horizontal velocity (queued):"); builder.append("\n" + " horizontal velocity (queued):");
hVel.AddQueued(builder); horVel.AddQueued(builder);
} }
} }

View File

@ -204,7 +204,7 @@ public class SurvivalFly extends Check {
hFreedom = res[2]; hFreedom = res[2];
} }
else{ else{
data.clearActiveHVel(); data.clearActiveHorVel();
hFreedom = 0.0; hFreedom = 0.0;
if (resetFrom && data.bunnyhopDelay <= 6) { if (resetFrom && data.bunnyhopDelay <= 6) {
data.bunnyhopDelay = 0; data.bunnyhopDelay = 0;
@ -223,7 +223,7 @@ public class SurvivalFly extends Check {
} }
// Prevent players from sprinting if they're moving backwards (allow buffers to cover up !?). // Prevent players from sprinting if they're moving backwards (allow buffers to cover up !?).
if (sprinting && data.lostSprintCount == 0 && !cc.assumeSprint && hDistance > walkSpeed && !data.hasActiveHVel()) { if (sprinting && data.lostSprintCount == 0 && !cc.assumeSprint && hDistance > walkSpeed && !data.hasActiveHorVel()) {
// (Ignore some cases, in order to prevent false positives.) // (Ignore some cases, in order to prevent false positives.)
// TODO: speed effects ? // TODO: speed effects ?
if (TrigUtil.isMovingBackwards(xDistance, zDistance, from.getYaw()) && !player.hasPermission(Permissions.MOVING_SURVIVALFLY_SPRINTING)) { if (TrigUtil.isMovingBackwards(xDistance, zDistance, from.getYaw()) && !player.hasPermission(Permissions.MOVING_SURVIVALFLY_SPRINTING)) {
@ -474,7 +474,7 @@ public class SurvivalFly extends Check {
// TODO: Should there be other side conditions? // TODO: Should there be other side conditions?
// Invalidate used horizontal velocity. // Invalidate used horizontal velocity.
// System.out.println("*** INVALIDATE ON SPEED"); // System.out.println("*** INVALIDATE ON SPEED");
data.clearActiveHVel(); data.clearActiveHorVel();
// if (data.horizontalVelocityUsed > cc.velocityGraceTicks) { // if (data.horizontalVelocityUsed > cc.velocityGraceTicks) {
// data.horizontalFreedom = 0; // data.horizontalFreedom = 0;
// data.horizontalVelocityCounter = 0; // data.horizontalVelocityCounter = 0;
@ -727,6 +727,8 @@ public class SurvivalFly extends Check {
private double yDirChange(final PlayerLocation from, final PlayerLocation to, final double yDistance, double vDistanceAboveLimit, final MovingData data) { private double yDirChange(final PlayerLocation from, final PlayerLocation to, final double yDistance, double vDistanceAboveLimit, final MovingData data) {
// TODO: Does this account for velocity in a sufficient way? // TODO: Does this account for velocity in a sufficient way?
if (yDistance > 0) { if (yDistance > 0) {
// TODO: Clear active vertical velocity here ?
// TODO: Demand consuming queued velocity for valid change (!).
// Increase // Increase
if (data.toWasReset) { if (data.toWasReset) {
tags.add("ychinc"); tags.add("ychinc");
@ -747,6 +749,7 @@ public class SurvivalFly extends Check {
// Decrease // Decrease
tags.add("ychdec"); tags.add("ychdec");
// Detect low jumping. // Detect low jumping.
// TODO: sfDirty: Account for actual velocity (demands consuming queued for dir-change(!))!
if (!data.sfNoLowJump && !data.sfDirty && data.mediumLiftOff == MediumLiftOff.GROUND) { if (!data.sfNoLowJump && !data.sfDirty && data.mediumLiftOff == MediumLiftOff.GROUND) {
final double setBackYDistance = to.getY() - data.getSetBackY(); final double setBackYDistance = to.getY() - data.getSetBackY();
if (setBackYDistance > 0.0) { if (setBackYDistance > 0.0) {