[BLEEDING] Revive direction checking. Optimizations.

This commit is contained in:
asofold 2013-02-18 02:55:46 +01:00
parent faa9a8637c
commit 52eb97026c
9 changed files with 122 additions and 58 deletions

View File

@ -128,11 +128,11 @@ public class BlockBreakListener extends CheckListener {
cancelled = true;
// Is the block really in reach distance?
if (!cancelled && reach.isEnabled(player) && reach.check(player, block.getLocation(), data))
if (!cancelled && reach.isEnabled(player) && reach.check(player, block, data))
cancelled = true;
// Did the player look at the block at all?
if (!cancelled && direction.isEnabled(player) && direction.check(player, block.getLocation(), data))
if (!cancelled && direction.isEnabled(player) && direction.check(player, block, data))
cancelled = true;
// Destroying liquid blocks.

View File

@ -1,6 +1,7 @@
package fr.neatmonster.nocheatplus.checks.blockbreak;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
@ -38,19 +39,19 @@ public class Direction extends Check {
* the location
* @return true, if successful
*/
public boolean check(final Player player, final Location location, final BlockBreakData data) {
public boolean check(final Player player, final Block block, final BlockBreakData data) {
boolean cancel = false;
// 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 double off = CheckUtils.directionCheck(player, location.getX() + 0.5D, location.getY() + 0.5D,
location.getZ() + 0.5D, 1D, 1D, 50);
final Location loc = player.getLocation();
final Vector direction = loc.getDirection();
final double off = CheckUtils.directionCheck(loc, player.getEyeHeight(), direction, block, CheckUtils.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...
final Vector direction = player.getEyeLocation().getDirection();
final Vector blockEyes = location.add(0.5D, 0.5D, 0.5D).subtract(player.getEyeLocation()).toVector();
final Vector blockEyes = new Vector(0.5 + block.getX() - loc.getX(), 0.5 + block.getY() - loc.getY() - player.getEyeHeight(), 0.5 + block.getZ() - loc.getZ());
final double distance = blockEyes.crossProduct(direction).length() / direction.length();
// Add the overall violation level of the check.

View File

@ -3,7 +3,7 @@ package fr.neatmonster.nocheatplus.checks.blockbreak;
import java.util.Map;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.actions.ParameterName;
@ -48,7 +48,7 @@ public class Reach extends Check {
* the location
* @return true, if successful
*/
public boolean check(final Player player, final Location location, final BlockBreakData data) {
public boolean check(final Player player, final Block block, final BlockBreakData data) {
boolean cancel = false;
@ -56,8 +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(), location.add(0.5D, 0.5D, 0.5D))
- distanceLimit;
final double distance = CheckUtils.distance(player.getEyeLocation(), block) - distanceLimit;
if (distance > 0) {
// He failed, increment violation level.

View File

@ -45,11 +45,11 @@ 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 double off = CheckUtils.directionCheck(player, 0.5 + block.getX(), 0.5 + block.getY(), 0.5 + block.getZ(), 1D, 1D, 50);
final Vector direction = loc.getDirection();
final double off = CheckUtils.directionCheck(loc, player.getEyeHeight(), direction, block, CheckUtils.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...
final Vector direction = loc.getDirection();
final Vector blockEyes = new Vector(0.5 + block.getX() - loc.getX(), 0.5 + block.getY() - loc.getY() - player.getEyeHeight(), 0.5 + block.getZ() - loc.getZ());
final double distance = blockEyes.crossProduct(direction).length() / direction.length();

View File

@ -119,12 +119,11 @@ public class BlockPlaceListener extends CheckListener {
cancelled = true;
// Third, the reach check.
if (!cancelled && reach.isEnabled(player) && reach.check(player, block.getLocation()))
if (!cancelled && reach.isEnabled(player) && reach.check(player, block))
cancelled = true;
// Fourth, the direction check.
if (!cancelled && direction.isEnabled(player)
&& direction.check(player, block.getLocation(), blockAgainst.getLocation()))
if (!cancelled && direction.isEnabled(player) && direction.check(player, block, blockAgainst))
cancelled = true;
// If one of the checks requested to cancel the event, do so.

View File

@ -1,6 +1,7 @@
package fr.neatmonster.nocheatplus.checks.blockplace;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
@ -38,34 +39,34 @@ public class Direction extends Check {
* the location
* @return true, if successful
*/
public boolean check(final Player player, final Location placed, final Location against) {
public boolean check(final Player player, final Block placed, final Block against) {
final BlockPlaceData data = BlockPlaceData.getData(player);
boolean cancel = false;
// 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.
double off = CheckUtils.directionCheck(player, against.getX() + 0.5D, against.getY() + 0.5D,
against.getZ() + 0.5D, 1D, 1D, 75);
final Location loc = player.getLocation();
final Vector direction = loc.getDirection();
double off = CheckUtils.directionCheck(loc, player.getEyeHeight(), direction, against, CheckUtils.DIRECTION_PRECISION);
// Now check if the player is looking at the block from the correct side.
double off2 = 0.0D;
// Find out against which face the player tried to build, and if he
// stood on the correct side of it
final Location eyes = player.getEyeLocation();
if (placed.getX() > against.getX())
off2 = against.getX() + 0.5D - eyes.getX();
off2 = against.getX() + 0.5D - loc.getX();
else if (placed.getX() < against.getX())
off2 = -(against.getX() + 0.5D - eyes.getX());
off2 = -(against.getX() + 0.5D - loc.getX());
else if (placed.getY() > against.getY())
off2 = against.getY() + 0.5D - eyes.getY();
off2 = against.getY() + 0.5D - loc.getY() - player.getEyeHeight();
else if (placed.getY() < against.getY())
off2 = -(against.getY() + 0.5D - eyes.getY());
off2 = -(against.getY() + 0.5D - loc.getY() - player.getEyeHeight());
else if (placed.getZ() > against.getZ())
off2 = against.getZ() + 0.5D - eyes.getZ();
off2 = against.getZ() + 0.5D - loc.getZ();
else if (placed.getZ() < against.getZ())
off2 = -(against.getZ() + 0.5D - eyes.getZ());
off2 = -(against.getZ() + 0.5D - loc.getZ());
// If he wasn't on the correct side, add that to the "off" value
if (off2 > 0.0D)
@ -73,8 +74,7 @@ public class Direction extends Check {
if (off > 0.1D) {
// Player failed the check. Let's try to guess how far he was from looking directly to the block...
final Vector direction = player.getEyeLocation().getDirection();
final Vector blockEyes = placed.add(0.5D, 0.5D, 0.5D).subtract(player.getEyeLocation()).toVector();
final Vector blockEyes = new Vector(0.5 + placed.getX() - loc.getX(), 0.5 + placed.getY() - loc.getY() - player.getEyeHeight(), 0.5 + placed.getZ() - loc.getZ());
final double distance = blockEyes.crossProduct(direction).length() / direction.length();
// Add the overall violation level of the check.

View File

@ -3,7 +3,7 @@ package fr.neatmonster.nocheatplus.checks.blockplace;
import java.util.Map;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.actions.ParameterName;
@ -48,7 +48,7 @@ public class Reach extends Check {
* the location
* @return true, if successful
*/
public boolean check(final Player player, final Location location) {
public boolean check(final Player player, final Block block) {
final BlockPlaceData data = BlockPlaceData.getData(player);
boolean cancel = false;
@ -57,8 +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(), location.add(0.5D, 0.5D, 0.5D))
- distanceLimit;
final double distance = CheckUtils.distance(player.getEyeLocation(), block) - distanceLimit;
if (distance > 0) {
// He failed, increment violation level.

View File

@ -62,14 +62,13 @@ 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 entity. If the line of sight is more too far off, "off" will be bigger than 0.
final double off = CheckUtils.directionCheck(player, dLoc.getX(), dLoc.getY() + height / 2D, dLoc.getZ(),
width, height, 75);
final Location loc = player.getLocation();
final Vector direction = player.getEyeLocation().getDirection();
final double off = CheckUtils.directionCheck(loc, player.getEyeHeight(), direction, dLoc.getX(), dLoc.getY() + height / 2D, dLoc.getZ(), width, height, CheckUtils.DIRECTION_PRECISION);
if (off > 0.1) {
// Player failed the check. Let's try to guess how far he was from looking directly to the entity...
final Vector direction = player.getEyeLocation().getDirection();
final Vector blockEyes = new Location(player.getWorld(), dLoc.getX(), dLoc.getY() + height / 2D,
dLoc.getZ()).subtract(player.getEyeLocation()).toVector();
final Vector blockEyes = new Vector(dLoc.getX() - loc.getX(), dLoc.getY() + height / 2D - loc.getY() - player.getEyeHeight(), dLoc.getZ() - loc.getZ());
final double distance = blockEyes.crossProduct(direction).length() / direction.length();
// Add the overall violation level of the check.

View File

@ -1,6 +1,7 @@
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;
@ -20,6 +21,9 @@ import fr.neatmonster.nocheatplus.logging.LogUtil;
*/
public class CheckUtils {
/** 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).
@ -38,34 +42,86 @@ public class CheckUtils {
* the target height
* @param precision
* the precision
* @return the double
* @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)
public static double directionCheck2(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: optimize !
// TODO: rework / standardize.
double dirLength = Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ);
if (dirLength == 0.0) dirLength = 1.0; // ...
// Get the eye location of the player.
final Location eyes = player.getEyeLocation();
final double factor = Math.sqrt(Math.pow(eyes.getX() - targetX, 2) + Math.pow(eyes.getY() - targetY, 2) + Math.pow(eyes.getZ() - targetZ, 2));
// Get the view direction of the player.
final Vector direction = eyes.getDirection();
final double x = targetX - eyes.getX();
final double y = targetY - eyes.getY();
final double z = targetZ - eyes.getZ();
final double xPrediction = factor * direction.getX();
final double yPrediction = factor * direction.getY();
final double zPrediction = factor * direction.getZ();
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(x - xPrediction) - (targetWidth / 2 + precision), 0.0D);
off += Math.max(Math.abs(z - zPrediction) - (targetWidth / 2 + precision), 0.0D);
off += Math.max(Math.abs(y - yPrediction) - (targetHeight / 2 + precision), 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);
@ -86,6 +142,17 @@ public class CheckUtils {
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