mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-06-28 23:34:43 +02:00
Quickly add box margins to LocationTrace/ITraceElement.
* Remove SharedContext.
This commit is contained in:
parent
65525f3c14
commit
4653b46579
|
@ -117,21 +117,17 @@ public class Direction extends Check {
|
|||
*/
|
||||
public DirectionContext getContext(final Player player, final Location loc,
|
||||
final Entity damaged, final boolean damagedIsFake, final Location damagedLoc,
|
||||
final FightData data, final FightConfig cc, final SharedContext sharedContext) {
|
||||
final FightData data, final FightConfig cc) {
|
||||
final DirectionContext context = new DirectionContext();
|
||||
// Find out how wide the entity is.
|
||||
if (damagedIsFake) {
|
||||
// Assume player / default.
|
||||
context.damagedComplex = false; // Later prefer bukkit based provider.
|
||||
context.damagedWidth = 0.6;
|
||||
}
|
||||
else {
|
||||
final MCAccess mcAccess = this.mcAccess.getHandle();
|
||||
context.damagedComplex = mcAccess.isComplexPart(damaged);
|
||||
context.damagedWidth = mcAccess.getWidth(damaged);
|
||||
}
|
||||
// entity.height is broken and will always be 0, therefore. Calculate height instead based on boundingBox.
|
||||
context.damagedHeight = sharedContext.damagedHeight;
|
||||
context.direction = loc.getDirection();
|
||||
context.lengthDirection = context.direction.length();
|
||||
return context;
|
||||
|
@ -161,19 +157,20 @@ public class Direction extends Check {
|
|||
|
||||
// How far "off" is the player with their aim. We calculate from the players eye location and view direction to
|
||||
// the center of the target entity. If the line of sight is more too far off, "off" will be bigger than 0.
|
||||
|
||||
final double damagedBoxMarginHorizontal = dLoc.getBoxMarginHorizontal();
|
||||
final double damagedBoxMarginVertical = dLoc.getBoxMarginVertical();
|
||||
final double off;
|
||||
if (cc.directionStrict){
|
||||
off = TrigUtil.combinedDirectionCheck(loc, player.getEyeHeight(), context.direction, dLoc.getX(), dLoc.getY() + context.damagedHeight / 2D, dLoc.getZ(), context.damagedWidth, context.damagedHeight, TrigUtil.DIRECTION_LOOP_PRECISION, 80.0);
|
||||
off = TrigUtil.combinedDirectionCheck(loc, player.getEyeHeight(), context.direction, dLoc.getX(), dLoc.getY() + damagedBoxMarginVertical / 2D, dLoc.getZ(), damagedBoxMarginHorizontal * 2.0, damagedBoxMarginVertical, TrigUtil.DIRECTION_LOOP_PRECISION, 80.0);
|
||||
}
|
||||
else{
|
||||
// Also take into account the angle.
|
||||
off = TrigUtil.directionCheck(loc, player.getEyeHeight(), context.direction, dLoc.getX(), dLoc.getY() + context.damagedHeight / 2D, dLoc.getZ(), context.damagedWidth, context.damagedHeight, TrigUtil.DIRECTION_LOOP_PRECISION);
|
||||
off = TrigUtil.directionCheck(loc, player.getEyeHeight(), context.direction, dLoc.getX(), dLoc.getY() + damagedBoxMarginVertical / 2D, dLoc.getZ(), damagedBoxMarginHorizontal * 2.0, damagedBoxMarginVertical, TrigUtil.DIRECTION_LOOP_PRECISION);
|
||||
}
|
||||
|
||||
if (off > 0.1) {
|
||||
// Player failed the check. Let's try to guess how far they were from looking directly to the entity...
|
||||
final Vector blockEyes = new Vector(dLoc.getX() - loc.getX(), dLoc.getY() + context.damagedHeight / 2D - loc.getY() - player.getEyeHeight(), dLoc.getZ() - loc.getZ());
|
||||
final Vector blockEyes = new Vector(dLoc.getX() - loc.getX(), dLoc.getY() + damagedBoxMarginVertical / 2D - loc.getY() - player.getEyeHeight(), dLoc.getZ() - loc.getZ());
|
||||
final double distance = blockEyes.crossProduct(context.direction).length() / context.lengthDirection;
|
||||
context.minViolation = Math.min(context.minViolation, distance);
|
||||
cancel = true;
|
||||
|
|
|
@ -18,14 +18,13 @@ import org.bukkit.util.Vector;
|
|||
|
||||
/**
|
||||
* Context data for the direction check, for repeated use within a loop.
|
||||
* @author mc_dev
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public class DirectionContext {
|
||||
|
||||
public boolean damagedComplex;
|
||||
public double damagedWidth;
|
||||
public double damagedHeight;
|
||||
public Vector direction = null;
|
||||
public double lengthDirection;
|
||||
|
||||
|
|
|
@ -200,7 +200,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
|||
// Get+update the damaged players.
|
||||
// TODO: Problem with NPCs: data stays (not a big problem).
|
||||
// (This is done even if the event has already been cancelled, to keep track, if the player is on a horse.)
|
||||
damagedTrace = MovingData.getData(damagedPlayer).updateTrace(damagedPlayer, damagedLoc, tick);
|
||||
damagedTrace = MovingData.getData(damagedPlayer).updateTrace(damagedPlayer, damagedLoc, tick, damagedIsFake ? null : mcAccess.getHandle());
|
||||
}
|
||||
else {
|
||||
damagedPlayer = null; // TODO: This is a temporary workaround.
|
||||
|
@ -410,9 +410,8 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
|||
boolean cancelled = false;
|
||||
|
||||
// (Might pass generic context to factories, for shared + heavy properties.)
|
||||
final SharedContext sharedContext = new SharedContext(damaged, damagedIsFake, mcAccess.getHandle());
|
||||
final ReachContext reachContext = reachEnabled ? reach.getContext(player, loc, damaged, damagedLoc, data, cc, sharedContext) : null;
|
||||
final DirectionContext directionContext = directionEnabled ? direction.getContext(player, loc, damaged, damagedIsFake, damagedLoc, data, cc, sharedContext) : null;
|
||||
final ReachContext reachContext = reachEnabled ? reach.getContext(player, loc, damaged, damagedLoc, data, cc) : null;
|
||||
final DirectionContext directionContext = directionEnabled ? direction.getContext(player, loc, damaged, damagedIsFake, damagedLoc, data, cc) : null;
|
||||
|
||||
final long traceOldest = tick - cc.loopMaxLatencyTicks; // TODO: Set by latency-window.
|
||||
// TODO: Iterating direction, which, static/dynamic choice.
|
||||
|
@ -424,6 +423,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
|||
// TODO: Maintain a latency estimate + max diff and invalidate completely (i.e. iterate from latest NEXT time)], or just max latency.
|
||||
// TODO: Consider a max-distance to "now", for fast invalidation.
|
||||
long latencyEstimate = -1;
|
||||
ITraceEntry successEntry = null;
|
||||
while (traceIt.hasNext()) {
|
||||
final ITraceEntry entry = traceIt.next();
|
||||
// Simplistic just check both until end or hit.
|
||||
|
@ -450,6 +450,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
|||
// TODO: Log/set estimated latency.
|
||||
violation = false;
|
||||
latencyEstimate = now - entry.getTime();
|
||||
successEntry = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -458,7 +459,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
|||
// TODO: violation vs. reachPassed + directionPassed (current: fail one = fail all).
|
||||
if (reachEnabled) {
|
||||
// TODO: Might ignore if already cancelled by mixed/silent cancel.
|
||||
if (reach.loopFinish(player, loc, damaged, reachContext, violation, data, cc)) {
|
||||
if (reach.loopFinish(player, loc, damaged, reachContext, successEntry, violation, data, cc)) {
|
||||
cancelled = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,11 +162,10 @@ public class Reach extends Check {
|
|||
* @param cc
|
||||
* @return
|
||||
*/
|
||||
public ReachContext getContext(final Player player, final Location pLoc, final Entity damaged, final Location damagedLoc, final FightData data, final FightConfig cc, final SharedContext sharedContext) {
|
||||
public ReachContext getContext(final Player player, final Location pLoc, final Entity damaged, final Location damagedLoc, final FightData data, final FightConfig cc) {
|
||||
final ReachContext context = new ReachContext();
|
||||
context.distanceLimit = player.getGameMode() == GameMode.CREATIVE ? CREATIVE_DISTANCE : cc.reachSurvivalDistance + getDistMod(damaged);
|
||||
context.distanceMin = (context.distanceLimit - cc.reachReduceDistance) / context.distanceLimit;
|
||||
context.damagedHeight = sharedContext.damagedHeight;
|
||||
//context.eyeHeight = player.getEyeHeight();
|
||||
context.pY = pLoc.getY() + player.getEyeHeight();
|
||||
return context;
|
||||
|
@ -183,7 +182,9 @@ public class Reach extends Check {
|
|||
* @param cc
|
||||
* @return
|
||||
*/
|
||||
public boolean loopCheck(final Player player, final Location pLoc, final Entity damaged, final ITraceEntry dRef, final ReachContext context, final FightData data, final FightConfig cc) {
|
||||
public boolean loopCheck(final Player player, final Location pLoc, final Entity damaged,
|
||||
final ITraceEntry dRef, final ReachContext context,
|
||||
final FightData data, final FightConfig cc) {
|
||||
boolean cancel = false;
|
||||
|
||||
// Refine y position.
|
||||
|
@ -193,8 +194,8 @@ public class Reach extends Check {
|
|||
if (context.pY <= dY) {
|
||||
// Keep the foot level y.
|
||||
}
|
||||
else if (context.pY >= dY + context.damagedHeight) {
|
||||
y = dY + context.damagedHeight; // Highest ref y.
|
||||
else if (context.pY >= dY + dRef.getBoxMarginVertical()) {
|
||||
y = dY + dRef.getBoxMarginVertical(); // Highest ref y.
|
||||
}
|
||||
else {
|
||||
y = context.pY; // Level with damaged.
|
||||
|
@ -230,7 +231,9 @@ public class Reach extends Check {
|
|||
* @param cc
|
||||
* @return
|
||||
*/
|
||||
public boolean loopFinish(final Player player, final Location pLoc, final Entity damaged, final ReachContext context, final boolean forceViolation, final FightData data, final FightConfig cc) {
|
||||
public boolean loopFinish(final Player player, final Location pLoc, final Entity damaged,
|
||||
final ReachContext context, final ITraceEntry traceEntry, final boolean forceViolation,
|
||||
final FightData data, final FightConfig cc) {
|
||||
final double lenpRel = forceViolation && context.minViolation != Double.MAX_VALUE ? context.minViolation : context.minResult;
|
||||
if (lenpRel == Double.MAX_VALUE) {
|
||||
return false;
|
||||
|
@ -281,7 +284,8 @@ public class Reach extends Check {
|
|||
}
|
||||
|
||||
if (data.debug && player.hasPermission(Permissions.ADMINISTRATION_DEBUG)){
|
||||
player.sendMessage("NC+: Attack/reach " + damaged.getType()+ " height="+ StringUtil.fdec3.format(context.damagedHeight) + " dist=" + StringUtil.fdec3.format(lenpRel) +" @" + StringUtil.fdec3.format(data.reachMod));
|
||||
// TODO: Height: remember successful ITraceEntry
|
||||
player.sendMessage("NC+: Attack/reach " + damaged.getType()+ (traceEntry == null ? "" : (" height=" + traceEntry.getBoxMarginVertical())) + " dist=" + StringUtil.fdec3.format(lenpRel) +" @" + StringUtil.fdec3.format(data.reachMod));
|
||||
}
|
||||
|
||||
return cancel;
|
||||
|
|
|
@ -16,16 +16,16 @@ package fr.neatmonster.nocheatplus.checks.fight;
|
|||
|
||||
/**
|
||||
* Context data for the reach check, for repeated use within a loop.
|
||||
* @author mc_dev
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public class ReachContext {
|
||||
|
||||
public double distanceLimit;
|
||||
public double distanceMin;
|
||||
public double damagedHeight;
|
||||
// /** Attacking player. */
|
||||
// public double eyeHeight;
|
||||
// /** Attacking player. */
|
||||
// public double eyeHeight;
|
||||
/** Eye location y of the attacking player. */
|
||||
public double pY;
|
||||
/** Minimum value of lenpRel that was a violation. */
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package fr.neatmonster.nocheatplus.checks.fight;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
|
||||
import fr.neatmonster.nocheatplus.compat.MCAccess;
|
||||
|
||||
public class SharedContext {
|
||||
public final double damagedHeight;
|
||||
|
||||
public SharedContext(Entity damaged, boolean damagedIsFake, MCAccess mcAccess) {
|
||||
if (damagedIsFake) {
|
||||
// Assume something lenient then.
|
||||
damagedHeight = damaged instanceof LivingEntity ? ((LivingEntity) damaged).getEyeHeight() : 1.75;
|
||||
}
|
||||
else {
|
||||
this.damagedHeight = mcAccess.getHeight(damaged);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -43,6 +43,7 @@ import fr.neatmonster.nocheatplus.checks.moving.velocity.FrictionAxisVelocity;
|
|||
import fr.neatmonster.nocheatplus.checks.moving.velocity.SimpleAxisVelocity;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.velocity.SimpleEntry;
|
||||
import fr.neatmonster.nocheatplus.checks.workaround.WRPT;
|
||||
import fr.neatmonster.nocheatplus.compat.MCAccess;
|
||||
import fr.neatmonster.nocheatplus.compat.blocks.BlockChangeTracker.BlockChangeEntry;
|
||||
import fr.neatmonster.nocheatplus.compat.blocks.BlockChangeTracker.BlockChangeReference;
|
||||
import fr.neatmonster.nocheatplus.components.data.ICanHandleTimeRunningBackwards;
|
||||
|
@ -1062,36 +1063,39 @@ public class MovingData extends ACheckData {
|
|||
}
|
||||
|
||||
/**
|
||||
* Convenience method to add a location to the trace, creates the trace if necessary.
|
||||
* Convenience method to add a location to the trace, creates the trace if
|
||||
* necessary.
|
||||
*
|
||||
* @param player
|
||||
* @param loc
|
||||
* @param time
|
||||
* @return Updated LocationTrace instance, for convenient use, without sticking too much to MovingData.
|
||||
* @param mcAccess
|
||||
* If null getEyeHeight and 0.3 are used (assume fake player).
|
||||
* @return Updated LocationTrace instance, for convenient use, without
|
||||
* sticking too much to MovingData.
|
||||
*/
|
||||
public LocationTrace updateTrace(final Player player, final Location loc, final long time) {
|
||||
public LocationTrace updateTrace(final Player player, final Location loc, final long time,
|
||||
final MCAccess mcAccess) {
|
||||
final LocationTrace trace = getTrace(player);
|
||||
trace.addEntry(time, loc.getX(), loc.getY(), loc.getZ());
|
||||
if (mcAccess == null) {
|
||||
// TODO: 0.3 from bukkit based default heights (needs extra registered classes).
|
||||
trace.addEntry(time, loc.getX(), loc.getY(), loc.getZ(), 0.3, player.getEyeHeight());
|
||||
}
|
||||
else {
|
||||
trace.addEntry(time, loc.getX(), loc.getY(), loc.getZ(), mcAccess.getWidth(player) / 2.0, Math.max(player.getEyeHeight(), mcAccess.getHeight(player)));
|
||||
}
|
||||
return trace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience
|
||||
* @param player
|
||||
* @param loc
|
||||
*/
|
||||
public void resetTrace(final Player player, final Location loc, final long time) {
|
||||
final MovingConfig cc = MovingConfig.getConfig(player);
|
||||
resetTrace(loc, time, cc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience.
|
||||
* @param loc
|
||||
* @param time
|
||||
* @param cc
|
||||
*/
|
||||
public void resetTrace(final Location loc, final long time, final MovingConfig cc) {
|
||||
resetTrace(loc, time, cc.traceMaxAge, cc.traceMaxSize);
|
||||
public void resetTrace(final Player player, final Location loc, final long time,
|
||||
final MCAccess mcAccess, final MovingConfig cc) {
|
||||
resetTrace(player, loc, time, cc.traceMaxAge, cc.traceMaxSize, mcAccess);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1101,11 +1105,13 @@ public class MovingData extends ACheckData {
|
|||
* @param mergeDist
|
||||
* @param traceMergeDist
|
||||
*/
|
||||
public void resetTrace(final Location loc, final long time, final int maxAge, final int maxSize) {
|
||||
public void resetTrace(final Player player, final Location loc, final long time,
|
||||
final int maxAge, final int maxSize, final MCAccess mcAccess) {
|
||||
if (trace != null) {
|
||||
trace.reset();
|
||||
}
|
||||
getTrace(maxAge, maxSize).addEntry(time, loc.getX(), loc.getY(), loc.getZ());
|
||||
getTrace(maxAge, maxSize).addEntry(time, loc.getX(), loc.getY(), loc.getZ(),
|
||||
mcAccess.getWidth(player) / 2.0, Math.max(player.getEyeHeight(), mcAccess.getHeight(player)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -313,7 +313,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
MovingUtil.ensureChunksLoaded(player, loc, "world change", data, cc);
|
||||
}
|
||||
aux.resetPositionsAndMediumProperties(player, loc, data, cc);
|
||||
data.resetTrace(loc, TickTask.getTick(), cc);
|
||||
data.resetTrace(player, loc, TickTask.getTick(), mcAccess.getHandle(), cc);
|
||||
if (cc.enforceLocation) {
|
||||
// Just in case.
|
||||
playersEnforce.add(player.getName());
|
||||
|
@ -1109,7 +1109,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
// TODO: teleported + other resetting ?
|
||||
Combined.feedYawRate(player, from.getYaw(), now, from.getWorld().getName(), data);
|
||||
aux.resetPositionsAndMediumProperties(player, from, mData, mCc);
|
||||
mData.resetTrace(player, from, tick); // TODO: Should probably leave this to the teleport event!
|
||||
mData.resetTrace(player, from, tick, mcAccess.getHandle(), mCc); // TODO: Should probably leave this to the teleport event!
|
||||
if (((NetConfig) CheckType.NET_FLYINGFREQUENCY.getConfigFactory().getConfig(player)).flyingFrequencyActive) {
|
||||
((NetData) CheckType.NET_FLYINGFREQUENCY.getDataFactory().getData(player)).teleportQueue.onTeleportEvent(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch());
|
||||
}
|
||||
|
@ -1135,12 +1135,12 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
final Location ref = player.getVehicle().getLocation(useLoc);
|
||||
aux.resetPositionsAndMediumProperties(player, ref, mData, mCc); // TODO: Consider using to and intercept cheat attempts in another way.
|
||||
useLoc.setWorld(null);
|
||||
mData.updateTrace(player, to, tick); // TODO: Can you become invincible by sending special moves?
|
||||
mData.updateTrace(player, to, tick, mcAccess.getHandle()); // TODO: Can you become invincible by sending special moves?
|
||||
}
|
||||
else if (!from.getWorld().getName().equals(toWorldName)) {
|
||||
// A teleport event should follow.
|
||||
aux.resetPositionsAndMediumProperties(player, to, mData, mCc);
|
||||
mData.resetTrace(player, to, tick);
|
||||
mData.resetTrace(player, to, tick, mcAccess.getHandle(), mCc);
|
||||
}
|
||||
else {
|
||||
// TODO: Detect differing location (a teleport event would follow).
|
||||
|
@ -1152,7 +1152,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
else {
|
||||
// Normal move, nothing to do.
|
||||
}
|
||||
mData.updateTrace(player, to, tick);
|
||||
mData.updateTrace(player, to, tick, mcAccess.getHandle());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1610,7 +1610,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
data.clearVehicleData(); // TODO: Uncertain here, what to check.
|
||||
data.clearAllMorePacketsData();
|
||||
data.removeAllVelocity();
|
||||
data.resetTrace(loc, tick, cc); // Might reset to loc instead of set-back ?
|
||||
data.resetTrace(player, loc, tick, mcAccess.getHandle(), cc); // Might reset to loc instead of set-back ?
|
||||
|
||||
// More resetting.
|
||||
data.vDistAcc.clear();
|
||||
|
|
|
@ -18,6 +18,7 @@ import java.util.Iterator;
|
|||
|
||||
import fr.neatmonster.nocheatplus.components.location.IGetPosition;
|
||||
import fr.neatmonster.nocheatplus.components.pool.AbstractPool;
|
||||
import fr.neatmonster.nocheatplus.utilities.RichBoundsLocation;
|
||||
|
||||
/**
|
||||
* This class is meant to record locations for players moving, in order to allow
|
||||
|
@ -45,18 +46,22 @@ public class LocationTrace {
|
|||
|
||||
public static interface ITraceEntry extends IGetPosition {
|
||||
|
||||
public double getBoxMarginHorizontal();
|
||||
|
||||
public double getBoxMarginVertical();
|
||||
|
||||
public long getTime();
|
||||
|
||||
}
|
||||
|
||||
public static class TraceEntry implements ITraceEntry {
|
||||
|
||||
|
||||
// TODO: Consider using a simple base implementation for IGetSetPosiotion.
|
||||
|
||||
/** We keep it open, if ticks or ms are used. */
|
||||
private long time;
|
||||
/** Coordinates. */
|
||||
private double x, y, z;
|
||||
private double x, y, z, boxMarginHorizontal, boxMarginVertical;
|
||||
|
||||
/** Older/next. */
|
||||
private TraceEntry next;
|
||||
|
@ -71,10 +76,13 @@ public class LocationTrace {
|
|||
* @param y
|
||||
* @param z
|
||||
*/
|
||||
public void set(long time, double x, double y, double z) {
|
||||
public void set(long time, double x, double y, double z,
|
||||
double boxMarginHorizontal, double boxMarginVertical) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.boxMarginHorizontal = boxMarginHorizontal;
|
||||
this.boxMarginVertical = boxMarginVertical;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
|
@ -93,6 +101,14 @@ public class LocationTrace {
|
|||
return z;
|
||||
}
|
||||
|
||||
public double getBoxMarginHorizontal() {
|
||||
return boxMarginHorizontal;
|
||||
}
|
||||
|
||||
public double getBoxMarginVertical() {
|
||||
return boxMarginVertical;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTime() {
|
||||
return time;
|
||||
|
@ -192,16 +208,35 @@ public class LocationTrace {
|
|||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
public final void addEntry(final long time, final double x, final double y, final double z) {
|
||||
public final void addEntry(final long time, final RichBoundsLocation loc) {
|
||||
addEntry(time, loc.getX(), loc.getY(), loc.getZ(), loc.getBoxMarginHorizontal(), loc.getBoxMarginVertical());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param time
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param boxMarginHorizontal
|
||||
* Margin from the foot position to the side(s) of the box.
|
||||
* @param boxMarginVertical
|
||||
* Margin from the foot position to the top of the box.
|
||||
*/
|
||||
public final void addEntry(final long time, final double x, final double y, final double z,
|
||||
final double boxMarginHorizontal, final double boxMarginVertical) {
|
||||
if (size > 0) {
|
||||
if (x == firstEntry.x && y == firstEntry.y && z == firstEntry.z) {
|
||||
// TODO: Might update box to bigger or remove margins ?
|
||||
if (x == firstEntry.x && y == firstEntry.y && z == firstEntry.z
|
||||
&& boxMarginHorizontal == firstEntry.boxMarginHorizontal
|
||||
&& boxMarginVertical == firstEntry.boxMarginVertical) {
|
||||
// (No update of time. firstEntry ... now always counts.)
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Add a new entry.
|
||||
final TraceEntry newEntry = pool.getInstance();
|
||||
newEntry.set(time, x, y, z);
|
||||
newEntry.set(time, x, y, z, boxMarginHorizontal, boxMarginVertical);
|
||||
setFirst(newEntry);
|
||||
// Remove the last entry, if maxSize is exceeded.
|
||||
if (size > maxSize) {
|
||||
|
|
|
@ -76,14 +76,14 @@ public class TestLocationTrace {
|
|||
}
|
||||
// Adding up to size elements.
|
||||
for (int i = 0; i < size ; i++) {
|
||||
trace.addEntry(i, i, i, i);
|
||||
trace.addEntry(i, i, i, i, 0, 0);
|
||||
if (trace.size() != i + 1) {
|
||||
fail("Wrong size, expect " + (i + 1) + ", got instead: " + trace.size());
|
||||
}
|
||||
}
|
||||
// Adding a lot of elements.
|
||||
for (int i = 0; i < 1000; i ++) {
|
||||
trace.addEntry(i + size, i, i, i);
|
||||
trace.addEntry(i + size, i, i, i, 0, 0);
|
||||
if (trace.size() != size) {
|
||||
fail("Wrong size, expect " + size + ", got instead: " + trace.size());
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ public class TestLocationTrace {
|
|||
int size = 80;
|
||||
LocationTrace trace = new LocationTrace(size, size, pool);
|
||||
for (int i = 0; i < 1000; i ++) {
|
||||
trace.addEntry(i + size, 0 , 0, 0);
|
||||
trace.addEntry(i + size, 0 , 0, 0, 0, 0);
|
||||
if (trace.size() != 1) {
|
||||
fail("Wrong size, expect 1, got instead: " + trace.size());
|
||||
}
|
||||
|
@ -133,13 +133,13 @@ public class TestLocationTrace {
|
|||
LocationTrace trace = new LocationTrace(size, size, pool);
|
||||
// Adding up to size elements.
|
||||
for (int i = 0; i < size; i++) {
|
||||
trace.addEntry(i, i, i, i);
|
||||
trace.addEntry(i, i, i, i, 0, 0);
|
||||
}
|
||||
// Test size with one time filled up.
|
||||
testIteratorSizeAndOrder(trace, 80);
|
||||
// Add size / 2 elements, to test cross-boundary iteration.
|
||||
for (int i = 0; i < size / 2; i++) {
|
||||
trace.addEntry(i + size, i, i, i);
|
||||
trace.addEntry(i + size, i, i, i, 0, 0);
|
||||
}
|
||||
// Test size again.
|
||||
testIteratorSizeAndOrder(trace, 80);
|
||||
|
@ -195,7 +195,7 @@ public class TestLocationTrace {
|
|||
LocationTrace trace = new LocationTrace(size, size, pool);
|
||||
// Adding up to size elements.
|
||||
for (int i = 0; i < size; i++) {
|
||||
trace.addEntry(i, i, i, i);
|
||||
trace.addEntry(i, i, i, i, 0, 0);
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
Iterator<ITraceEntry> it = trace.maxAgeIterator(i);
|
||||
|
@ -218,11 +218,11 @@ public class TestLocationTrace {
|
|||
public void testMaxAgeFirstElementAnyway() {
|
||||
int size = 80;
|
||||
LocationTrace trace = new LocationTrace(size, size, pool);
|
||||
trace.addEntry(0, 0, 0, 0);
|
||||
trace.addEntry(0, 0, 0, 0, 0, 0);
|
||||
if (!trace.maxAgeIterator(1000).hasNext()) {
|
||||
fail("Expect iterator (maxAge) to always contain the latest element.");
|
||||
}
|
||||
trace.addEntry(1, 0, 0, 0);
|
||||
trace.addEntry(1, 0, 0, 0, 0, 0);
|
||||
final Iterator<ITraceEntry> it = trace.maxAgeIterator(2);
|
||||
if (!it.hasNext()) {
|
||||
fail("Expect iterator (maxAge) to always contain the latest element.");
|
||||
|
|
Loading…
Reference in New Issue
Block a user