Move auxiliary code.

This commit is contained in:
asofold 2013-05-21 15:51:51 +02:00
parent 6519ea1e19
commit 6e6b198188
15 changed files with 483 additions and 467 deletions

View File

@ -88,5 +88,81 @@ public class StringUtil {
}
return out;
}
/**
* Return if the two Strings are similar based on the given threshold.
*
* @param s
* the first String, must not be null
* @param t
* the second String, must not be null
* @param threshold
* the minimum value of the correlation coefficient
* @return result true if the two Strings are similar, false otherwise
*/
public static boolean isSimilar(final String s, final String t, final float threshold)
{
return 1.0f - (float) levenshteinDistance(s, t) / Math.max(1.0, Math.max(s.length(), t.length())) > threshold;
}
/**
* Find the Levenshtein distance between two Strings.
*
* This is the number of changes needed to change one String into another,
* where each change is a single character modification (deletion, insertion or substitution).
*
* @param s
* the first String, must not be null
* @param t
* the second String, must not be null
* @return result distance
*/
public static int levenshteinDistance(CharSequence s, CharSequence t) {
if (s == null || t == null) throw new IllegalArgumentException("Strings must not be null");
int n = s.length();
int m = t.length();
if (n == 0) return m;
else if (m == 0) return n;
if (n > m) {
final CharSequence tmp = s;
s = t;
t = tmp;
n = m;
m = t.length();
}
int p[] = new int[n + 1];
int d[] = new int[n + 1];
int _d[];
int i;
int j;
char t_j;
int cost;
for (i = 0; i <= n; i++)
p[i] = i;
for (j = 1; j <= m; j++) {
t_j = t.charAt(j - 1);
d[0] = j;
for (i = 1; i <= n; i++) {
cost = s.charAt(i - 1) == t_j ? 0 : 1;
d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost);
}
_d = p;
p = d;
d = _d;
}
return p[n];
}
}

View File

@ -0,0 +1,41 @@
package fr.neatmonster.nocheatplus.utilities;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Vehicle;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
public class TeleportUtil {
/**
* Teleport the player with vehicle, temporarily eject the passenger and set teleported in MovingData.
* @param vehicle
* @param player
* @param location
*/
public static void teleport(final Vehicle vehicle, final Player player, final Location location, final boolean debug) {
// TODO: This handling could conflict with WorldGuard region flags.
final Entity passenger = vehicle.getPassenger();
final boolean vehicleTeleported;
final boolean playerIsPassenger = player.equals(passenger);
if (playerIsPassenger && !vehicle.isDead()){ // && vehicle.equals(player.getVehicle).
vehicle.eject();
vehicleTeleported = vehicle.teleport(location, TeleportCause.PLUGIN);
}
else if (passenger == null && !vehicle.isDead()){
vehicleTeleported = vehicle.teleport(location, TeleportCause.PLUGIN);
}
else vehicleTeleported = false;
final boolean playerTeleported = player.teleport(location);
if (playerIsPassenger && playerTeleported && vehicleTeleported && player.getLocation().distance(vehicle.getLocation()) < 1.0){
// Somewhat check against tp showing something wrong (< 1.0).
vehicle.setPassenger(player);
}
if (debug){
System.out.println(player.getName() + " vehicle set back: " + location);
}
}
}

View File

@ -0,0 +1,335 @@
package fr.neatmonster.nocheatplus.utilities;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
/**
* Auxiliary methods for trigonometry related tasks, such as distances, directions, angles.
* @author mc_dev
*
*/
public class TrigUtil {
/** Used for internal calculations, no passing on, beware of nested calls. */
private static final Vector vec1 = new Vector();
/** Used for internal calculations, no passing on, beware of nested calls. */
private static final Vector vec2 = new Vector();
/** Multiply to get grad from rad. */
public static final double fRadToGrad = 360.0 / (2.0 * Math.PI);
/** Some default precision value for the directionCheck method. */
public static final double DIRECTION_PRECISION = 2.6;
/**
* Check if a player looks at a target of a specific size, with a specific
* precision value (roughly).
*
* @param player
* the player
* @param targetX
* the target x
* @param targetY
* the target y
* @param targetZ
* the target z
* @param targetWidth
* the target width
* @param targetHeight
* the target height
* @param precision
* the precision
* @return
*/
public static double directionCheck(final Player player, final double targetX, final double targetY, final double targetZ, final double targetWidth, final double targetHeight, final double precision)
{
final Location loc = player.getLocation();
final Vector dir = loc.getDirection();
return directionCheck(loc.getX(), loc.getY() + player.getEyeHeight(), loc.getZ(), dir.getX(), dir.getY(), dir.getZ(), targetX, targetY, targetZ, targetWidth, targetHeight, precision);
}
/**
* Convenience method.
* @param sourceFoot
* @param eyeHeight
* @param dir
* @param target
* @param precision (width/height are set to 1)
* @return
*/
public static double directionCheck(final Location sourceFoot, final double eyeHeight, final Vector dir, final Block target, final double precision)
{
return directionCheck(sourceFoot.getX(), sourceFoot.getY() + eyeHeight, sourceFoot.getZ(), dir.getX(), dir.getY(), dir.getZ(), target.getX(), target.getY(), target.getZ(), 1, 1, precision);
}
/**
* Convenience method.
* @param sourceFoot
* @param eyeHeight
* @param dir
* @param targetX
* @param targetY
* @param targetZ
* @param targetWidth
* @param targetHeight
* @param precision
* @return
*/
public static double directionCheck(final Location sourceFoot, final double eyeHeight, final Vector dir, final double targetX, final double targetY, final double targetZ, final double targetWidth, final double targetHeight, final double precision)
{
return directionCheck(sourceFoot.getX(), sourceFoot.getY() + eyeHeight, sourceFoot.getZ(), dir.getX(), dir.getY(), dir.getZ(), targetX, targetY, targetZ, targetWidth, targetHeight, precision);
}
/**
* Check how far the looking direction is off the target.
* @param sourceX Source location of looking direction.
* @param sourceY
* @param sourceZ
* @param dirX Looking direction.
* @param dirY
* @param dirZ
* @param targetX Location that should be looked towards.
* @param targetY
* @param targetZ
* @param targetWidth xz extent
* @param targetHeight y extent
* @param precision
* @return Some offset.
*/
public static double directionCheck(final double sourceX, final double sourceY, final double sourceZ, final double dirX, final double dirY, final double dirZ, final double targetX, final double targetY, final double targetZ, final double targetWidth, final double targetHeight, final double precision)
{
// // TODO: Here we have 0.x vs. 2.x, sometimes !
// System.out.println("COMBINED: " + combinedDirectionCheck(sourceX, sourceY, sourceZ, dirX, dirY, dirZ, targetX, targetY, targetZ, targetWidth, targetHeight, precision, 60));
// TODO: rework / standardize.
double dirLength = Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ);
if (dirLength == 0.0) dirLength = 1.0; // ...
final double dX = targetX - sourceX;
final double dY = targetY - sourceY;
final double dZ = targetZ - sourceZ;
final double targetDist = Math.sqrt(dX * dX + dY * dY + dZ * dZ);
final double xPrediction = targetDist * dirX / dirLength;
final double yPrediction = targetDist * dirY / dirLength;
final double zPrediction = targetDist * dirZ / dirLength;
double off = 0.0D;
off += Math.max(Math.abs(dX - xPrediction) - (targetWidth / 2 + precision), 0.0D);
off += Math.max(Math.abs(dZ - zPrediction) - (targetWidth / 2 + precision), 0.0D);
off += Math.max(Math.abs(dY - yPrediction) - (targetHeight / 2 + precision), 0.0D);
if (off > 1) off = Math.sqrt(off);
return off;
}
public static double combinedDirectionCheck(final Location sourceFoot, final double eyeHeight, final Vector dir, final double targetX, final double targetY, final double targetZ, final double targetWidth, final double targetHeight, final double precision, final double anglePrecision)
{
return combinedDirectionCheck(sourceFoot.getX(), sourceFoot.getY() + eyeHeight, sourceFoot.getZ(), dir.getX(), dir.getY(), dir.getZ(), targetX, targetY, targetZ, targetWidth, targetHeight, precision, anglePrecision);
}
public static double combinedDirectionCheck(final Location sourceFoot, final double eyeHeight, final Vector dir, final Block target, final double precision, final double anglePrecision)
{
return combinedDirectionCheck(sourceFoot.getX(), sourceFoot.getY() + eyeHeight, sourceFoot.getZ(), dir.getX(), dir.getY(), dir.getZ(), target.getX(), target.getY(), target.getZ(), 1, 1, precision, anglePrecision);
}
/**
* Combine directionCheck with angle, in order to prevent low-distance abuse.
* @param sourceX
* @param sourceY
* @param sourceZ
* @param dirX
* @param dirY
* @param dirZ
* @param targetX
* @param targetY
* @param targetZ
* @param targetWidth
* @param targetHeight
* @param blockPrecision
* @param anglePrecision Precision in grad.
* @return
*/
public static double combinedDirectionCheck(final double sourceX, final double sourceY, final double sourceZ, final double dirX, final double dirY, final double dirZ, final double targetX, final double targetY, final double targetZ, final double targetWidth, final double targetHeight, final double blockPrecision, final double anglePrecision)
{
double dirLength = Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ);
if (dirLength == 0.0) dirLength = 1.0; // ...
final double dX = targetX - sourceX;
final double dY = targetY - sourceY;
final double dZ = targetZ - sourceZ;
final double targetDist = Math.sqrt(dX * dX + dY * dY + dZ * dZ);
if (targetDist > Math.max(targetHeight, targetWidth) / 2.0 && angle(sourceX, sourceY, sourceZ, dirX, dirY, dirZ, targetX, targetY, targetZ) * fRadToGrad > anglePrecision){
return targetDist - Math.max(targetHeight, targetWidth) / 2.0;
}
final double xPrediction = targetDist * dirX / dirLength;
final double yPrediction = targetDist * dirY / dirLength;
final double zPrediction = targetDist * dirZ / dirLength;
double off = 0.0D;
off += Math.max(Math.abs(dX - xPrediction) - (targetWidth / 2 + blockPrecision), 0.0D);
off += Math.max(Math.abs(dZ - zPrediction) - (targetWidth / 2 + blockPrecision), 0.0D);
off += Math.max(Math.abs(dY - yPrediction) - (targetHeight / 2 + blockPrecision), 0.0D);
if (off > 1) off = Math.sqrt(off);
return off;
}
/**
* 3D-distance of two locations. This is obsolete, since it has been fixed. To ignore world checks it might be "useful".
*
* @param location1
* the location1
* @param location2
* the location2
* @return the double
*/
public static final double distance(final Location location1, final Location location2)
{
return distance(location1.getX(), location1.getY(), location1.getZ(), location2.getX(), location2.getY(), location2.getZ());
}
/**
* 3d-distance from location (exact) to block middle.
* @param location
* @param block
* @return
*/
public static final double distance(final Location location, final Block block)
{
return distance(location.getX(), location.getY(), location.getZ(), 0.5 + block.getX(), 0.5 + block.getY(), 0.5 + block.getZ());
}
/**
* 3D-distance.
* @param x1
* @param y1
* @param z1
* @param x2
* @param y2
* @param z2
* @return
*/
public static final double distance(final double x1, final double y1, final double z1, final double x2, final double y2, final double z2) {
final double dx = Math.abs(x1 - x2);
final double dy = Math.abs(y1 - y2);
final double dz = Math.abs(z1 - z2);
return Math.sqrt(dx * dx + dy * dy + dz * dz);
}
/**
* 2D-distance in x-z plane.
* @param location1
* @param location2
* @return
*/
public static final double xzDistance(final Location location1, final Location location2)
{
return distance(location1.getX(), location1.getZ(), location2.getX(), location2.getZ());
}
/**
* 2D-distance.
* @param x1
* @param z1
* @param x2
* @param z2
* @return
*/
public static final double distance(final double x1, final double z1, final double x2, final double z2) {
final double dx = Math.abs(x1 - x2);
final double dz = Math.abs(z1 - z2);
return Math.sqrt(dx * dx + dz * dz);
}
/**
* Positive angle between vector from source to target and the vector for the given direction [0...PI].
* @param sourceX
* @param sourceY
* @param sourceZ
* @param dirX
* @param dirY
* @param dirZ
* @param targetX
* @param targetY
* @param targetZ
* @return Positive angle between vector from source to target and the vector for the given direction [0...PI].
*/
public static float angle(final double sourceX, final double sourceY, final double sourceZ, final double dirX, final double dirY, final double dirZ, final double targetX, final double targetY, final double targetZ) {
double dirLength = Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ);
if (dirLength == 0.0) dirLength = 1.0; // ...
final double dX = targetX - sourceX;
final double dY = targetY - sourceY;
final double dZ = targetZ - sourceZ;
vec1.setX(dX);
vec1.setY(dY);
vec1.setZ(dZ);
vec2.setX(dirX);
vec2.setY(dirY);
vec2.setZ(dirZ);
return vec2.angle(vec1);
}
/**
* Angle of a 2d vector, x being the side at the angle. (radians).
* @param x
* @param z
* @return
*/
public static final double angle(final double x, final double z){
final double a;
if (x > 0.0) a = Math.atan(z / x);
else if (x < 0.0) a = Math.atan(z / x) + Math.PI;
else{
if (z < 0.0) a=3.0 * Math.PI / 2.0;
else if (z > 0.0) a = Math.PI / 2.0;
else return Double.NaN;
}
if (a < 0.0) return a + 2.0 * Math.PI;
else return a;
}
/**
* Get the difference of angles (radians) as given from angle(x,z), from a1 to a2, i.e. rather a2 - a1 in principle.
* @param a1
* @param a2
* @return Difference of angle from -pi to pi
*/
public static final double angleDiff(final double a1, final double a2){
if (Double.isNaN(a1) || Double.isNaN(a1)) return Double.NaN;
final double diff = a2 - a1;
if (diff < -Math.PI) return diff + 2.0 * Math.PI;
else if (diff > Math.PI) return diff - 2.0 * Math.PI;
else return diff;
}
/**
* Yaw (angle in grad) difference. This ensures inputs are interpreted correctly (for 360 degree offsets).
* @param fromYaw
* @param toYaw
* @return Angle difference to get from fromYaw to toYaw. Result is in [-180, 180].
*/
public static final float yawDiff(float fromYaw, float toYaw){
if (fromYaw <= -360f) fromYaw = -((-fromYaw) % 360f);
else if (fromYaw >= 360f) fromYaw = fromYaw % 360f;
if (toYaw <= -360f) toYaw = -((-toYaw) % 360f);
else if (toYaw >= 360f) toYaw = toYaw % 360f;
float yawDiff = toYaw - fromYaw;
if (yawDiff < -180f) yawDiff += 360f;
else if (yawDiff > 180f) yawDiff -= 360f;
return yawDiff;
}
}

View File

@ -7,7 +7,7 @@ import org.bukkit.util.Vector;
import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
/*
* M""""""'YMM oo dP oo
@ -47,7 +47,7 @@ public class Direction extends Check {
// the center of the target block. If the line of sight is more too far off, "off" will be bigger than 0.
final Location loc = player.getLocation();
final Vector direction = loc.getDirection();
final double off = CheckUtils.directionCheck(loc, player.getEyeHeight(), direction, block, CheckUtils.DIRECTION_PRECISION);
final double off = TrigUtil.directionCheck(loc, player.getEyeHeight(), direction, block, TrigUtil.DIRECTION_PRECISION);
if (off > 0.1D) {
// Player failed the check. Let's try to guess how far he was from looking directly to the block...

View File

@ -10,7 +10,7 @@ import fr.neatmonster.nocheatplus.actions.ParameterName;
import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.ViolationData;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
/*
* MM"""""""`MM dP
@ -56,7 +56,7 @@ public class Reach extends Check {
// Distance is calculated from eye location to center of targeted block. If the player is further away from his
// target than allowed, the difference will be assigned to "distance".
final double distance = CheckUtils.distance(player.getEyeLocation(), block) - distanceLimit;
final double distance = TrigUtil.distance(player.getEyeLocation(), block) - distanceLimit;
if (distance > 0) {
// He failed, increment violation level.

View File

@ -7,7 +7,7 @@ import org.bukkit.util.Vector;
import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
/*
* M""""""'YMM oo dP oo
@ -46,7 +46,7 @@ public class Direction extends Check {
// How far "off" is the player with his aim. We calculate from the players eye location and view direction to
// the center of the target block. If the line of sight is more too far off, "off" will be bigger than 0.
final Vector direction = loc.getDirection();
final double off = CheckUtils.directionCheck(loc, player.getEyeHeight(), direction, block, CheckUtils.DIRECTION_PRECISION);
final double off = TrigUtil.directionCheck(loc, player.getEyeHeight(), direction, block, TrigUtil.DIRECTION_PRECISION);
if (off > 0.1D) {
// Player failed the check. Let's try to guess how far he was from looking directly to the block...

View File

@ -9,7 +9,7 @@ import fr.neatmonster.nocheatplus.actions.ParameterName;
import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.ViolationData;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
/*
* MM"""""""`MM dP
@ -55,7 +55,7 @@ public class Reach extends Check {
// Distance is calculated from eye location to center of targeted block. If the player is further away from his
// target than allowed, the difference will be assigned to "distance".
final double distance = CheckUtils.distance(loc.getX(), loc.getY() + player.getEyeHeight(), loc.getZ(), 0.5 + block.getX(), 0.5 + block.getY(), 0.5 + block.getZ()) - distanceLimit;
final double distance = TrigUtil.distance(loc.getX(), loc.getY() + player.getEyeHeight(), loc.getZ(), 0.5 + block.getX(), 0.5 + block.getY(), 0.5 + block.getZ()) - distanceLimit;
if (distance > 0) {
// He failed, increment violation level.

View File

@ -7,7 +7,7 @@ import org.bukkit.util.Vector;
import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
/*
* M""""""'YMM oo dP oo
@ -48,7 +48,7 @@ public class Direction extends Check {
// the center of the target block. If the line of sight is more too far off, "off" will be bigger than 0.
final Location loc = player.getLocation();
final Vector direction = loc.getDirection();
double off = CheckUtils.directionCheck(loc, player.getEyeHeight(), direction, against, CheckUtils.DIRECTION_PRECISION);
double off = TrigUtil.directionCheck(loc, player.getEyeHeight(), direction, against, TrigUtil.DIRECTION_PRECISION);
// Now check if the player is looking at the block from the correct side.
double off2 = 0.0D;

View File

@ -10,7 +10,7 @@ import fr.neatmonster.nocheatplus.actions.ParameterName;
import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.ViolationData;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
/*
* MM"""""""`MM dP
@ -57,7 +57,7 @@ public class Reach extends Check {
// Distance is calculated from eye location to center of targeted block. If the player is further away from his
// target than allowed, the difference will be assigned to "distance".
final double distance = CheckUtils.distance(player.getEyeLocation(), block) - distanceLimit;
final double distance = TrigUtil.distance(player.getEyeLocation(), block) - distanceLimit;
if (distance > 0) {
// He failed, increment violation level.

View File

@ -20,7 +20,6 @@ import fr.neatmonster.nocheatplus.command.INotifyReload;
import fr.neatmonster.nocheatplus.config.ConfigFile;
import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.logging.LogUtil;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.ColorUtil;
import fr.neatmonster.nocheatplus.utilities.StringUtil;
@ -159,21 +158,21 @@ public class Text extends AsyncCheck implements INotifyReload{
final long timeout = 8000; // TODO: maybe set dynamically in data.
// Repetition of last message.
if (cc.textMsgRepeatSelf != 0f && time - data.chatLastTime < timeout){
if (CheckUtils.isSimilar(lcMessage, data.chatLastMessage, 0.8f)){
if (StringUtil.isSimilar(lcMessage, data.chatLastMessage, 0.8f)){
final float timeWeight = (float) (timeout - (time - data.chatLastTime)) / (float) timeout;
score += cc.textMsgRepeatSelf * timeWeight;
}
}
// Repetition of last global message.
if (cc.textMsgRepeatGlobal != 0f && time - lastGlobalTime < timeout){
if (CheckUtils.isSimilar(lcMessage, lastGlobalMessage, 0.8f)){
if (StringUtil.isSimilar(lcMessage, lastGlobalMessage, 0.8f)){
final float timeWeight = (float) (timeout - (time - lastGlobalTime)) / (float) timeout;
score += cc.textMsgRepeatGlobal * timeWeight;
}
}
// Repetition of last cancelled message.
if (cc.textMsgRepeatCancel != 0f && time - lastCancelledTime < timeout){
if (CheckUtils.isSimilar(lcMessage, lastCancelledMessage, 0.8f)){
if (StringUtil.isSimilar(lcMessage, lastCancelledMessage, 0.8f)){
final float timeWeight = (float) (timeout - (time - lastCancelledTime)) / (float) timeout;
score += cc.textMsgRepeatCancel * timeWeight;
}

View File

@ -7,8 +7,8 @@ import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.TickTask;
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
/*
* MMP"""""""MM dP
@ -84,7 +84,7 @@ public class Angle extends Check {
// Calculate the time elapsed between the two hits.
deltaTime += previousTime - time;
// Calculate the difference of the yaw between the two locations.
final float dYaw = CheckUtils.yawDiff(previousLocation.getYaw(), location.getYaw());
final float dYaw = TrigUtil.yawDiff(previousLocation.getYaw(), location.getYaw());
deltaYaw += Math.abs(dYaw);
}
// Remember the current time and location.

View File

@ -7,7 +7,7 @@ import org.bukkit.util.Vector;
import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
/*
* M""""""'YMM oo dP oo
@ -67,11 +67,11 @@ public class Direction extends Check {
final double off;
if (cc.directionStrict){
off = CheckUtils.combinedDirectionCheck(loc, player.getEyeHeight(), direction, dLoc.getX(), dLoc.getY() + height / 2D, dLoc.getZ(), width, height, CheckUtils.DIRECTION_PRECISION, 80.0);
off = TrigUtil.combinedDirectionCheck(loc, player.getEyeHeight(), direction, dLoc.getX(), dLoc.getY() + height / 2D, dLoc.getZ(), width, height, TrigUtil.DIRECTION_PRECISION, 80.0);
}
else{
// Also take into account the angle.
off = CheckUtils.directionCheck(loc, player.getEyeHeight(), direction, dLoc.getX(), dLoc.getY() + height / 2D, dLoc.getZ(), width, height, CheckUtils.DIRECTION_PRECISION);
off = TrigUtil.directionCheck(loc, player.getEyeHeight(), direction, dLoc.getX(), dLoc.getY() + height / 2D, dLoc.getZ(), width, height, TrigUtil.DIRECTION_PRECISION);
}
if (off > 0.1) {

View File

@ -27,8 +27,8 @@ import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.checks.moving.MovingListener;
import fr.neatmonster.nocheatplus.components.JoinLeaveListener;
import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.TickTask;
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
import fr.neatmonster.nocheatplus.utilities.build.BuildParameters;
/*
@ -124,7 +124,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
else{
tickAge = tick - data.lastAttackTick;
// TODO: Maybe use 3d distance if dy(normalized) is too big.
targetMove = CheckUtils.distance(data.lastAttackedX, data.lastAttackedZ, targetLoc.getX(), targetLoc.getZ());
targetMove = TrigUtil.distance(data.lastAttackedX, data.lastAttackedZ, targetLoc.getX(), targetLoc.getZ());
msAge = (long) (50f * TickTask.getLag(50L * tickAge) * (float) tickAge);
normalizedMove = msAge == 0 ? targetMove : targetMove * Math.min(20.0, 1000.0 / (double) msAge);
}
@ -218,17 +218,17 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
// data.lastAttackedDist = targetDist;
// Velocity freedom adaption.
if (!cancelled && player.isSprinting() && CheckUtils.distance(loc.getX(), loc.getZ(), targetLoc.getX(), targetLoc.getZ()) < 3.0){
if (!cancelled && player.isSprinting() && TrigUtil.distance(loc.getX(), loc.getZ(), targetLoc.getX(), targetLoc.getZ()) < 3.0){
// Add "mini" freedom.
final MovingData mData = MovingData.getData(player);
// TODO: Check distance of other entity.
if (mData.fromX != Double.MAX_VALUE){
final double hDist = CheckUtils.distance(loc.getX(), loc.getZ(), mData.fromX, mData.fromZ) ;
final double hDist = TrigUtil.distance(loc.getX(), loc.getZ(), mData.fromX, mData.fromZ) ;
if (hDist >= 0.23 && mData.sfHorizontalBuffer > 0.5 && MovingListener.shouldCheckSurvivalFly(player, mData, MovingConfig.getConfig(player))){
// Allow extra consumption with buffer.
mData.sfHBufExtra = 7;
if (cc.debug && BuildParameters.debugLevel > 0){
System.out.println(player.getName() + " attacks, hDist to last from: " + hDist + " | targetdist=" + CheckUtils.distance(loc.getX(), loc.getZ(), targetLoc.getX(), targetLoc.getZ()) + " | sprinting=" + player.isSprinting() + " | food=" + player.getFoodLevel() +" | hbuf=" + mData.sfHorizontalBuffer);
System.out.println(player.getName() + " attacks, hDist to last from: " + hDist + " | targetdist=" + TrigUtil.distance(loc.getX(), loc.getZ(), targetLoc.getX(), targetLoc.getZ()) + " | sprinting=" + player.isSprinting() + " | food=" + player.getFoodLevel() +" | hbuf=" + mData.sfHorizontalBuffer);
}
}
}

View File

@ -65,7 +65,9 @@ import fr.neatmonster.nocheatplus.utilities.BlockProperties;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.PlayerLocation;
import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.utilities.TeleportUtil;
import fr.neatmonster.nocheatplus.utilities.TickTask;
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
import fr.neatmonster.nocheatplus.utilities.build.BuildParameters;
/*
@ -901,12 +903,12 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
if (cause == TeleportCause.UNKNOWN){
// Check special small range teleports (moved too quickly).
if (from != null && from.getWorld().equals(to.getWorld())){
if (CheckUtils.distance(from, to) < margin){
if (TrigUtil.distance(from, to) < margin){
smallRange = true;
}
else if (data.toX != Double.MAX_VALUE && data.hasSetBack()){
final Location setBack = data.getSetBack(to);
if (CheckUtils.distance(to.getX(), to.getY(), to.getZ(), setBack.getX(), setBack.getY(), setBack.getZ()) < margin){
if (TrigUtil.distance(to.getX(), to.getY(), to.getZ(), setBack.getX(), setBack.getY(), setBack.getZ()) < margin){
smallRange = true;
}
}
@ -1120,7 +1122,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
public void run() {
data.morePacketsVehicleTaskId = -1;
try{
CheckUtils.teleport(vehicle, player, location);
MovingData.getData(player).setTeleported(location);
TeleportUtil.teleport(vehicle, player, location, MovingConfig.getConfig(player).debug);
}
catch(Throwable t){
LogUtil.logSevere(t);

View File

@ -1,19 +1,11 @@
package fr.neatmonster.nocheatplus.utilities;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Vehicle;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.util.Vector;
import fr.neatmonster.nocheatplus.checks.blockbreak.BlockBreakData;
import fr.neatmonster.nocheatplus.checks.combined.CombinedData;
import fr.neatmonster.nocheatplus.checks.fight.FightData;
import fr.neatmonster.nocheatplus.checks.inventory.InventoryData;
import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.logging.LogUtil;
/**
@ -21,404 +13,6 @@ import fr.neatmonster.nocheatplus.logging.LogUtil;
*/
public class CheckUtils {
/** Used for internal calculations, no passing on, beware of nested calls. */
private static final Vector vec1 = new Vector();
/** Used for internal calculations, no passing on, beware of nested calls. */
private static final Vector vec2 = new Vector();
/** Multiply to get grad from rad. */
public static final double fRadToGrad = 360.0 / (2.0 * Math.PI);
/** Some default precision value for the directionCheck method. */
public static final double DIRECTION_PRECISION = 2.6;
/**
* Check if a player looks at a target of a specific size, with a specific
* precision value (roughly).
*
* @param player
* the player
* @param targetX
* the target x
* @param targetY
* the target y
* @param targetZ
* the target z
* @param targetWidth
* the target width
* @param targetHeight
* the target height
* @param precision
* the precision
* @return
*/
public static double directionCheck(final Player player, final double targetX, final double targetY, final double targetZ, final double targetWidth, final double targetHeight, final double precision)
{
final Location loc = player.getLocation();
final Vector dir = loc.getDirection();
return directionCheck(loc.getX(), loc.getY() + player.getEyeHeight(), loc.getZ(), dir.getX(), dir.getY(), dir.getZ(), targetX, targetY, targetZ, targetWidth, targetHeight, precision);
}
/**
* Convenience method.
* @param sourceFoot
* @param eyeHeight
* @param dir
* @param target
* @param precision (width/height are set to 1)
* @return
*/
public static double directionCheck(final Location sourceFoot, final double eyeHeight, final Vector dir, final Block target, final double precision)
{
return directionCheck(sourceFoot.getX(), sourceFoot.getY() + eyeHeight, sourceFoot.getZ(), dir.getX(), dir.getY(), dir.getZ(), target.getX(), target.getY(), target.getZ(), 1, 1, precision);
}
/**
* Convenience method.
* @param sourceFoot
* @param eyeHeight
* @param dir
* @param targetX
* @param targetY
* @param targetZ
* @param targetWidth
* @param targetHeight
* @param precision
* @return
*/
public static double directionCheck(final Location sourceFoot, final double eyeHeight, final Vector dir, final double targetX, final double targetY, final double targetZ, final double targetWidth, final double targetHeight, final double precision)
{
return directionCheck(sourceFoot.getX(), sourceFoot.getY() + eyeHeight, sourceFoot.getZ(), dir.getX(), dir.getY(), dir.getZ(), targetX, targetY, targetZ, targetWidth, targetHeight, precision);
}
/**
* Check how far the looking direction is off the target.
* @param sourceX Source location of looking direction.
* @param sourceY
* @param sourceZ
* @param dirX Looking direction.
* @param dirY
* @param dirZ
* @param targetX Location that should be looked towards.
* @param targetY
* @param targetZ
* @param targetWidth xz extent
* @param targetHeight y extent
* @param precision
* @return Some offset.
*/
public static double directionCheck(final double sourceX, final double sourceY, final double sourceZ, final double dirX, final double dirY, final double dirZ, final double targetX, final double targetY, final double targetZ, final double targetWidth, final double targetHeight, final double precision)
{
// // TODO: Here we have 0.x vs. 2.x, sometimes !
// System.out.println("COMBINED: " + combinedDirectionCheck(sourceX, sourceY, sourceZ, dirX, dirY, dirZ, targetX, targetY, targetZ, targetWidth, targetHeight, precision, 60));
// TODO: rework / standardize.
double dirLength = Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ);
if (dirLength == 0.0) dirLength = 1.0; // ...
final double dX = targetX - sourceX;
final double dY = targetY - sourceY;
final double dZ = targetZ - sourceZ;
final double targetDist = Math.sqrt(dX * dX + dY * dY + dZ * dZ);
final double xPrediction = targetDist * dirX / dirLength;
final double yPrediction = targetDist * dirY / dirLength;
final double zPrediction = targetDist * dirZ / dirLength;
double off = 0.0D;
off += Math.max(Math.abs(dX - xPrediction) - (targetWidth / 2 + precision), 0.0D);
off += Math.max(Math.abs(dZ - zPrediction) - (targetWidth / 2 + precision), 0.0D);
off += Math.max(Math.abs(dY - yPrediction) - (targetHeight / 2 + precision), 0.0D);
if (off > 1) off = Math.sqrt(off);
return off;
}
public static double combinedDirectionCheck(final Location sourceFoot, final double eyeHeight, final Vector dir, final double targetX, final double targetY, final double targetZ, final double targetWidth, final double targetHeight, final double precision, final double anglePrecision)
{
return combinedDirectionCheck(sourceFoot.getX(), sourceFoot.getY() + eyeHeight, sourceFoot.getZ(), dir.getX(), dir.getY(), dir.getZ(), targetX, targetY, targetZ, targetWidth, targetHeight, precision, anglePrecision);
}
public static double combinedDirectionCheck(final Location sourceFoot, final double eyeHeight, final Vector dir, final Block target, final double precision, final double anglePrecision)
{
return combinedDirectionCheck(sourceFoot.getX(), sourceFoot.getY() + eyeHeight, sourceFoot.getZ(), dir.getX(), dir.getY(), dir.getZ(), target.getX(), target.getY(), target.getZ(), 1, 1, precision, anglePrecision);
}
/**
* Combine directionCheck with angle, in order to prevent low-distance abuse.
* @param sourceX
* @param sourceY
* @param sourceZ
* @param dirX
* @param dirY
* @param dirZ
* @param targetX
* @param targetY
* @param targetZ
* @param targetWidth
* @param targetHeight
* @param blockPrecision
* @param anglePrecision Precision in grad.
* @return
*/
public static double combinedDirectionCheck(final double sourceX, final double sourceY, final double sourceZ, final double dirX, final double dirY, final double dirZ, final double targetX, final double targetY, final double targetZ, final double targetWidth, final double targetHeight, final double blockPrecision, final double anglePrecision)
{
double dirLength = Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ);
if (dirLength == 0.0) dirLength = 1.0; // ...
final double dX = targetX - sourceX;
final double dY = targetY - sourceY;
final double dZ = targetZ - sourceZ;
final double targetDist = Math.sqrt(dX * dX + dY * dY + dZ * dZ);
if (targetDist > Math.max(targetHeight, targetWidth) / 2.0 && angle(sourceX, sourceY, sourceZ, dirX, dirY, dirZ, targetX, targetY, targetZ) * fRadToGrad > anglePrecision){
return targetDist - Math.max(targetHeight, targetWidth) / 2.0;
}
final double xPrediction = targetDist * dirX / dirLength;
final double yPrediction = targetDist * dirY / dirLength;
final double zPrediction = targetDist * dirZ / dirLength;
double off = 0.0D;
off += Math.max(Math.abs(dX - xPrediction) - (targetWidth / 2 + blockPrecision), 0.0D);
off += Math.max(Math.abs(dZ - zPrediction) - (targetWidth / 2 + blockPrecision), 0.0D);
off += Math.max(Math.abs(dY - yPrediction) - (targetHeight / 2 + blockPrecision), 0.0D);
if (off > 1) off = Math.sqrt(off);
return off;
}
/**
* 3D-distance of two locations. This is obsolete, since it has been fixed. To ignore world checks it might be "useful".
*
* @param location1
* the location1
* @param location2
* the location2
* @return the double
*/
public static final double distance(final Location location1, final Location location2)
{
return distance(location1.getX(), location1.getY(), location1.getZ(), location2.getX(), location2.getY(), location2.getZ());
}
/**
* 3d-distance from location (exact) to block middle.
* @param location
* @param block
* @return
*/
public static final double distance(final Location location, final Block block)
{
return distance(location.getX(), location.getY(), location.getZ(), 0.5 + block.getX(), 0.5 + block.getY(), 0.5 + block.getZ());
}
/**
* 3D-distance.
* @param x1
* @param y1
* @param z1
* @param x2
* @param y2
* @param z2
* @return
*/
public static final double distance(final double x1, final double y1, final double z1, final double x2, final double y2, final double z2) {
final double dx = Math.abs(x1 - x2);
final double dy = Math.abs(y1 - y2);
final double dz = Math.abs(z1 - z2);
return Math.sqrt(dx * dx + dy * dy + dz * dz);
}
/**
* 2D-distance in x-z plane.
* @param location1
* @param location2
* @return
*/
public static final double xzDistance(final Location location1, final Location location2)
{
return distance(location1.getX(), location1.getZ(), location2.getX(), location2.getZ());
}
/**
* 2D-distance.
* @param x1
* @param z1
* @param x2
* @param z2
* @return
*/
public static final double distance(final double x1, final double z1, final double x2, final double z2) {
final double dx = Math.abs(x1 - x2);
final double dz = Math.abs(z1 - z2);
return Math.sqrt(dx * dx + dz * dz);
}
/**
* Return if the two Strings are similar based on the given threshold.
*
* @param s
* the first String, must not be null
* @param t
* the second String, must not be null
* @param threshold
* the minimum value of the correlation coefficient
* @return result true if the two Strings are similar, false otherwise
*/
public static boolean isSimilar(final String s, final String t, final float threshold)
{
return 1.0f - (float) levenshteinDistance(s, t) / Math.max(1.0, Math.max(s.length(), t.length())) > threshold;
}
/**
* Find the Levenshtein distance between two Strings.
*
* This is the number of changes needed to change one String into another,
* where each change is a single character modification (deletion, insertion or substitution).
*
* @param s
* the first String, must not be null
* @param t
* the second String, must not be null
* @return result distance
*/
public static int levenshteinDistance(CharSequence s, CharSequence t) {
if (s == null || t == null) throw new IllegalArgumentException("Strings must not be null");
int n = s.length();
int m = t.length();
if (n == 0) return m;
else if (m == 0) return n;
if (n > m) {
final CharSequence tmp = s;
s = t;
t = tmp;
n = m;
m = t.length();
}
int p[] = new int[n + 1];
int d[] = new int[n + 1];
int _d[];
int i;
int j;
char t_j;
int cost;
for (i = 0; i <= n; i++)
p[i] = i;
for (j = 1; j <= m; j++) {
t_j = t.charAt(j - 1);
d[0] = j;
for (i = 1; i <= n; i++) {
cost = s.charAt(i - 1) == t_j ? 0 : 1;
d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost);
}
_d = p;
p = d;
d = _d;
}
return p[n];
}
/**
* Positive angle between vector from source to target and the vector for the given direction [0...PI].
* @param sourceX
* @param sourceY
* @param sourceZ
* @param dirX
* @param dirY
* @param dirZ
* @param targetX
* @param targetY
* @param targetZ
* @return Positive angle between vector from source to target and the vector for the given direction [0...PI].
*/
public static float angle(final double sourceX, final double sourceY, final double sourceZ, final double dirX, final double dirY, final double dirZ, final double targetX, final double targetY, final double targetZ) {
double dirLength = Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ);
if (dirLength == 0.0) dirLength = 1.0; // ...
final double dX = targetX - sourceX;
final double dY = targetY - sourceY;
final double dZ = targetZ - sourceZ;
vec1.setX(dX);
vec1.setY(dY);
vec1.setZ(dZ);
vec2.setX(dirX);
vec2.setY(dirY);
vec2.setZ(dirZ);
return vec2.angle(vec1);
}
/**
* Angle of a 2d vector, x being the side at the angle. (radians).
* @param x
* @param z
* @return
*/
public static final double angle(final double x, final double z){
final double a;
if (x > 0.0) a = Math.atan(z / x);
else if (x < 0.0) a = Math.atan(z / x) + Math.PI;
else{
if (z < 0.0) a=3.0 * Math.PI / 2.0;
else if (z > 0.0) a = Math.PI / 2.0;
else return Double.NaN;
}
if (a < 0.0) return a + 2.0 * Math.PI;
else return a;
}
/**
* Get the difference of angles (radians) as given from angle(x,z), from a1 to a2, i.e. rather a2 - a1 in principle.
* @param a1
* @param a2
* @return Difference of angle from -pi to pi
*/
public static final double angleDiff(final double a1, final double a2){
if (Double.isNaN(a1) || Double.isNaN(a1)) return Double.NaN;
final double diff = a2 - a1;
if (diff < -Math.PI) return diff + 2.0 * Math.PI;
else if (diff > Math.PI) return diff - 2.0 * Math.PI;
else return diff;
}
/**
* Yaw (angle in grad) difference. This ensures inputs are interpreted correctly (for 360 degree offsets).
* @param fromYaw
* @param toYaw
* @return Angle difference to get from fromYaw to toYaw. Result is in [-180, 180].
*/
public static final float yawDiff(float fromYaw, float toYaw){
if (fromYaw <= -360f) fromYaw = -((-fromYaw) % 360f);
else if (fromYaw >= 360f) fromYaw = fromYaw % 360f;
if (toYaw <= -360f) toYaw = -((-toYaw) % 360f);
else if (toYaw >= 360f) toYaw = toYaw % 360f;
float yawDiff = toYaw - fromYaw;
if (yawDiff < -180f) yawDiff += 360f;
else if (yawDiff > 180f) yawDiff -= 360f;
return yawDiff;
}
/**
* Kick and log.
* @param player
@ -428,38 +22,6 @@ public class CheckUtils {
LogUtil.logWarning("[NCP] Disconnect " + player.getName() + " due to illegal move!");
}
/**
* Teleport the player with vehicle, temporarily eject the passenger and set teleported in MovingData.
* @param vehicle
* @param player
* @param location
*/
public static void teleport(final Vehicle vehicle, final Player player, final Location location) {
// TODO: This handling could conflict with WorldGuard region flags.
final Entity passenger = vehicle.getPassenger();
final boolean vehicleTeleported;
final boolean playerIsPassenger = player.equals(passenger);
if (playerIsPassenger && !vehicle.isDead()){ // && vehicle.equals(player.getVehicle).
vehicle.eject();
vehicleTeleported = vehicle.teleport(location, TeleportCause.PLUGIN);
}
else if (passenger == null && !vehicle.isDead()){
vehicleTeleported = vehicle.teleport(location, TeleportCause.PLUGIN);
}
else vehicleTeleported = false;
final MovingData data = MovingData.getData(player);
data.setTeleported(location);
final boolean playerTeleported = player.teleport(location);
if (playerIsPassenger && playerTeleported && vehicleTeleported && player.getLocation().distance(vehicle.getLocation()) < 1.0){
// Somewhat check against tp showing something wrong (< 1.0).
vehicle.setPassenger(player);
}
if (MovingConfig.getConfig(player).debug){
System.out.println(player.getName() + " vehicle set back: " + location);
}
}
/**
* Guess some last-action time, likely to be replaced with centralized PlayerData use.
* @param player