218 lines
7.5 KiB
Java
218 lines
7.5 KiB
Java
/*
|
|
* 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.generic.block;
|
|
|
|
import org.bukkit.Location;
|
|
import org.bukkit.block.Block;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.util.Vector;
|
|
|
|
import fr.neatmonster.nocheatplus.actions.ActionList;
|
|
import fr.neatmonster.nocheatplus.checks.Check;
|
|
import fr.neatmonster.nocheatplus.checks.CheckType;
|
|
import fr.neatmonster.nocheatplus.checks.access.ICheckConfig;
|
|
import fr.neatmonster.nocheatplus.checks.access.ICheckData;
|
|
import fr.neatmonster.nocheatplus.checks.net.FlyingQueueHandle;
|
|
import fr.neatmonster.nocheatplus.checks.net.FlyingQueueLookBlockChecker;
|
|
import fr.neatmonster.nocheatplus.players.IPlayerData;
|
|
import fr.neatmonster.nocheatplus.utilities.collision.CollideRayVsAABB;
|
|
import fr.neatmonster.nocheatplus.utilities.collision.ICollideRayVsAABB;
|
|
import fr.neatmonster.nocheatplus.utilities.location.LocUtil;
|
|
|
|
/**
|
|
* A first made-abstract version of a direction-towards-a-block-check.
|
|
*
|
|
* @author asofold
|
|
*
|
|
* @param <D>
|
|
* @param <C>
|
|
*/
|
|
public abstract class AbstractBlockDirectionCheck<D extends ICheckData, C extends ICheckConfig> extends Check {
|
|
|
|
private final class BoulderChecker extends FlyingQueueLookBlockChecker {
|
|
// (Not static for convenience.)
|
|
|
|
private double minDistance;
|
|
|
|
@Override
|
|
protected boolean check(final double x, final double y, final double z,
|
|
final float yaw, final float pitch,
|
|
final int blockX, final int blockY, final int blockZ) {
|
|
final double distance = checkBoulder(x, y, z, yaw, pitch, blockX, blockY, blockZ);
|
|
if (distance == Double.MAX_VALUE) {
|
|
// minDistance is not updated, in case the information is interesting ever.
|
|
return true;
|
|
}
|
|
else {
|
|
minDistance = Math.min(minDistance, distance);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean checkFlyingQueue(double x, double y, double z, float oldYaw, float oldPitch, int blockX,
|
|
int blockY, int blockZ, FlyingQueueHandle flyingHandle) {
|
|
minDistance = Double.MAX_VALUE;
|
|
return super.checkFlyingQueue(x, y, z, oldYaw, oldPitch, blockX, blockY, blockZ, flyingHandle);
|
|
}
|
|
|
|
public double getMinDistance() {
|
|
return minDistance;
|
|
}
|
|
|
|
}
|
|
|
|
private final ICollideRayVsAABB boulder = new CollideRayVsAABB();
|
|
private final Location useLoc = new Location(null, 0, 0, 0);
|
|
|
|
private final BoulderChecker checker = new BoulderChecker();
|
|
|
|
/**
|
|
* Instantiates a new direction check.
|
|
*/
|
|
public AbstractBlockDirectionCheck(CheckType checkType) {
|
|
super(checkType);
|
|
}
|
|
|
|
/**
|
|
* Add the distance to the VL, return the resulting violation level.
|
|
*
|
|
* @param distance
|
|
* @param data
|
|
* @return
|
|
*/
|
|
protected abstract double addVL(Player player, double distance, D data, C cc);
|
|
|
|
/**
|
|
* Fetch the actions from the config.
|
|
* @param cc
|
|
* @return
|
|
*/
|
|
protected abstract ActionList getActions(C cc);
|
|
|
|
|
|
/**
|
|
* Called on passing the check (cooldown vl, debug log, ...).
|
|
*
|
|
* @param player
|
|
* @param datam
|
|
* @param cc
|
|
*/
|
|
protected abstract void cooldown(Player player, D data, C cc);
|
|
|
|
/**
|
|
* The actual checking method.
|
|
*
|
|
* @param player
|
|
* @param loc
|
|
* Foot location to use as base for checking, with looking
|
|
* direction set.
|
|
* @param eyeHeight
|
|
* The eye height above the foot location.
|
|
* @param block
|
|
* The block the player is supposed to be looking at.
|
|
* @param flyingHandle
|
|
* @param data
|
|
* @param cc
|
|
* @return True, if the check has been failed.
|
|
*/
|
|
public boolean check(final Player player, final Location loc, final double eyeHeight,
|
|
final Block block, final FlyingQueueHandle flyingHandle,
|
|
final D data, final C cc, final IPlayerData pData) {
|
|
|
|
boolean cancel = false;
|
|
// How far "off" is the player with their aim.
|
|
final double x = loc.getX();
|
|
final double y = loc.getY() + eyeHeight;
|
|
final double z = loc.getZ();
|
|
final int blockX = block.getX();
|
|
final int blockY = block.getY();
|
|
final int blockZ = block.getZ();
|
|
// The distance is squared initially.
|
|
double distance;
|
|
if (checker.checkFlyingQueue(x, y, z, loc.getYaw(), loc.getPitch(),
|
|
blockX, blockY, blockZ, flyingHandle)) {
|
|
distance = Double.MAX_VALUE;
|
|
}
|
|
else {
|
|
distance = checker.getMinDistance();
|
|
}
|
|
|
|
// TODO: Consider a protected field with a tolerance value.
|
|
if (distance != Double.MAX_VALUE) {
|
|
distance = Math.sqrt(distance);
|
|
if (pData.isDebugActive(type)) {
|
|
outputDebugFail(player, boulder, distance);
|
|
}
|
|
|
|
// Add the overall violation level of the check.
|
|
final double vl = addVL(player, distance, data, cc);
|
|
|
|
// TODO: Set distance parameter.
|
|
|
|
// Execute whatever actions are associated with this check and the violation level and find out if we should
|
|
// cancel the event.
|
|
cancel = executeActions(player, vl, distance, getActions(cc)).willCancel();
|
|
} else {
|
|
// Player did likely nothing wrong, reduce violation counter to reward them.
|
|
cooldown(player, data, cc);
|
|
}
|
|
return cancel;
|
|
}
|
|
|
|
/**
|
|
* Check one configuration.
|
|
*
|
|
* @param x
|
|
* @param y
|
|
* @param z
|
|
* @param yaw
|
|
* @param pitch
|
|
* @param blockX
|
|
* @param blockY
|
|
* @param blockZ
|
|
* @return Double.MAX_VALUE if this passes the check, otherwise the squared
|
|
* violation distance (some measure).
|
|
*/
|
|
private double checkBoulder(final double x, final double y, final double z,
|
|
final float yaw, final float pitch,
|
|
final int blockX, final int blockY, final int blockZ) {
|
|
useLoc.setYaw(yaw);
|
|
useLoc.setPitch(pitch);
|
|
final Vector dir = useLoc.getDirection(); // TODO: More efficient.
|
|
final double dirX = dir.getX();
|
|
final double dirY = dir.getY();
|
|
final double dirZ = dir.getZ();
|
|
// Initialize fully each time.
|
|
boulder.setFindNearestPointIfNotCollide(true)
|
|
.setRay(x, y, z, dirX, dirY, dirZ)
|
|
.setAABB(blockX, blockY, blockZ, 0.1)
|
|
.loop();
|
|
// Interpret result.
|
|
if (boulder.collides()) {
|
|
return Double.MAX_VALUE;
|
|
}
|
|
else {
|
|
return boulder.getClosestDistanceSquared();
|
|
}
|
|
}
|
|
|
|
private void outputDebugFail(Player player, ICollideRayVsAABB boulder, double distance) {
|
|
debug(player, "Failed: collides: " + boulder.collides() + " , dist: " + distance + " , pos: " + LocUtil.simpleFormat(boulder));
|
|
}
|
|
|
|
|
|
}
|