Skip to content

Commit

Permalink
Let blockinteract.direction check queued packets. Unify loop (visible).
Browse files Browse the repository at this point in the history
* Add a class to loop the flying queue with a block as target (look
only).
* Pass the flyingHandle to sub checks (doesn't necessarily make sense
with reach - should probably re-check reach with the used flying queue
state, but that's more complicated due to the possibility of split pos
vs. look).
* Use the loop class both for visible and direction (not reach).

Likely similar has to be done with BlockPlace and BlockBreak - would be
good to find a skipping heuristic for blockbreak.direction etc., so we
know we have successfully checked that block from that exact position
for this player and nothing has happened between (and so on, or a more
relaxed heuristic).
  • Loading branch information
asofold committed Apr 28, 2017
1 parent 970ed6b commit 180cf8a
Show file tree
Hide file tree
Showing 6 changed files with 263 additions and 59 deletions.
Expand Up @@ -33,6 +33,7 @@
import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.checks.moving.util.MovingUtil;
import fr.neatmonster.nocheatplus.checks.net.FlyingQueueHandle;
import fr.neatmonster.nocheatplus.checks.net.model.DataPacketFlying;
import fr.neatmonster.nocheatplus.compat.Bridge1_9;
import fr.neatmonster.nocheatplus.compat.BridgeHealth;
import fr.neatmonster.nocheatplus.compat.BridgeMisc;
Expand Down Expand Up @@ -185,10 +186,27 @@ else if (MovingUtil.hasScheduledPlayerSetBack(player)) {
}
else {
data.subsequentCancel = 0;
if (data.debug) {
if (flyingHandle.isFlyingQueueFetched()) {
// Log which entry was used.
logUsedFlyingPacket(player, flyingHandle);
}
}
}
useLoc.setWorld(null);
}

private void logUsedFlyingPacket(final Player player, final FlyingQueueHandle flyingHandle) {
final DataPacketFlying[] queue = flyingHandle.getHandle();
for (int i = 0; i < queue.length; i++) {
final DataPacketFlying packet = queue[i];
if (packet != null) {
debug(player, "Flying packet queue used at index " + i + ": pitch=" + packet.getPitch() + ",yaw=" + packet.getYaw());
return;
}
}
}

private void onCancelInteract(final Player player, final Block block, final BlockFace face,
final PlayerInteractEvent event, final int previousLastTick, final boolean preventUseItem,
final BlockInteractData data, final BlockInteractConfig cc) {
Expand Down
Expand Up @@ -22,6 +22,7 @@
import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.net.FlyingQueueHandle;
import fr.neatmonster.nocheatplus.checks.net.FlyingQueueLookBlockChecker;
import fr.neatmonster.nocheatplus.utilities.collision.CollideRayVsAABB;
import fr.neatmonster.nocheatplus.utilities.collision.ICollideRayVsAABB;
import fr.neatmonster.nocheatplus.utilities.location.LocUtil;
Expand All @@ -31,7 +32,43 @@
*/
public class Direction 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.
Expand All @@ -53,20 +90,27 @@ public boolean check(final Player player, final Location loc, final Block block,
final FlyingQueueHandle flyingHandle, final BlockInteractData data, final BlockInteractConfig cc) {

boolean cancel = false;

// How far "off" is the player with their aim.
final Vector direction = loc.getDirection();
// Initialize fully each time.
boulder.setFindNearestPointIfNotCollide(true)
.setRay(loc.getX(), loc.getY() + player.getEyeHeight(), loc.getZ(),
direction.getX(), direction.getY(), direction.getZ())
.setAABB(block.getX(), block.getY(), block.getZ(), 0.1)
.loop();
// TODO: if (boulder.collides()) { // Check flying queue.

if (!boulder.collides()) {
final double distance = Math.sqrt(boulder.getClosestDistanceSquared());
final double x = loc.getX();
final double y = loc.getY() + player.getEyeHeight();
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 = checkBoulder(x, y, z, loc.getYaw(), loc.getPitch(), blockX, blockY, blockZ);
if (distance != Double.MAX_VALUE) {
if (checker.checkFlyingQueue(x, y, z, loc.getYaw(), loc.getPitch(),
blockX, blockY, blockZ, flyingHandle)) {
distance = Double.MAX_VALUE;
}
else {
distance = Math.min(distance, checker.getMinDistance());
}
}

if (distance != Double.MAX_VALUE) {
distance = Math.sqrt(distance);
if (data.debug) {
outputDebugFail(player, boulder, distance);
}
Expand All @@ -83,10 +127,46 @@ public boolean check(final Player player, final Location loc, final Block block,
// Player did likely nothing wrong, reduce violation counter to reward them.
data.directionVL *= 0.9D;
}

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));
}
Expand Down
Expand Up @@ -62,6 +62,7 @@ public boolean check(final Player player, final Location loc, final Block block,

// Distance is calculated from eye location to center of targeted block. If the player is further away from their
// target than allowed, the difference will be assigned to "distance".
// TODO: On failure loop through flying queue, and do set not working entries to null (!).
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) {
Expand Down
Expand Up @@ -28,23 +28,78 @@
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.ViolationData;
import fr.neatmonster.nocheatplus.checks.net.FlyingQueueHandle;
import fr.neatmonster.nocheatplus.checks.net.model.DataPacketFlying;
import fr.neatmonster.nocheatplus.checks.net.FlyingQueueLookBlockChecker;
import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.utilities.collision.InteractRayTracing;
import fr.neatmonster.nocheatplus.utilities.location.LocUtil;
import fr.neatmonster.nocheatplus.utilities.location.TrigUtil;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
import fr.neatmonster.nocheatplus.utilities.map.WrapBlockCache;

public class Visible extends Check {

private final class RayChecker extends FlyingQueueLookBlockChecker {

private BlockFace face;
private List<String> tags;
private boolean debug;
private Player player;

@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) {
// Run ray-tracing again with updated pitch and yaw.
useLoc.setPitch(pitch);
useLoc.setYaw(yaw);
final Vector direction = useLoc.getDirection(); // TODO: Better.
tags.clear();
if (checkRayTracing(x, y, z, direction.getX(), direction.getY(), direction.getZ(), blockX, blockY, blockZ, face, tags, debug)) {
// Collision still.
if (debug) {
debug(player, "pitch=" + pitch + ",yaw=" + yaw + " tags=" + StringUtil.join(tags, "+"));
}
return false;
}
else {
return true;
}

}

public boolean checkFlyingQueue(double x, double y, double z, float oldYaw, float oldPitch, int blockX,
int blockY, int blockZ, FlyingQueueHandle flyingHandle,
BlockFace face, List<String> tags, boolean debug, Player player) {
this.face = face;
this.tags = tags;
this.debug = debug;
this.player = player;
return super.checkFlyingQueue(x, y, z, oldYaw, oldPitch, blockX, blockY, blockZ, flyingHandle);
}

@Override
public boolean checkFlyingQueue(double x, double y, double z, float oldYaw, float oldPitch, int blockX,
int blockY, int blockZ, FlyingQueueHandle flyingHandle) {
throw new UnsupportedOperationException("Use the other method.");
}

public void cleanup () {
this.player = null;
this.face = null;
this.debug = false;
this.tags = null;
}

}

private final WrapBlockCache wrapBlockCache;

/**
* Strict set to false, due to false positives.
*/
private final InteractRayTracing rayTracing = new InteractRayTracing(false);

private final RayChecker checker = new RayChecker();

private final List<String> tags = new ArrayList<String>();

/** For temporary use, no nested use, setWorld(null) after use, etc. */
Expand Down Expand Up @@ -86,52 +141,15 @@ public boolean check(final Player player, final Location loc, final Block block,
if (collides) {
// Debug output.
if (data.debug) {
debug(player, "pitch=" + loc.getPitch() + " yaw=" + loc.getYaw() + " tags=" + StringUtil.join(tags, "+"));
debug(player, "pitch=" + loc.getPitch() + ",yaw=" + loc.getYaw() + " tags=" + StringUtil.join(tags, "+"));
}
// Re-check with flying packets.
final DataPacketFlying[] flyingQueue = flyingHandle.getHandle();
// TODO: Maybe just the latest one does (!).+
LocUtil.set(useLoc, loc);
final float oldPitch = useLoc.getPitch();
final float oldYaw = useLoc.getYaw();
// TODO: Specific max-recheck-count (likely doesn't equal packet count).
for (int i = 0; i < flyingQueue.length; i++) {
final DataPacketFlying packetData = flyingQueue[i];
if (packetData == null) {
// Other checks have pre-selected.
continue;
}
// TODO: Allow if within threshold(s) of last move.
// TODO: Confine by distance.
// Abort/skipping conditions.
// if (packetData.hasPos) {
// break;
// }
if (!packetData.hasLook) {
flyingQueue[i] = null;
continue;
}
// TODO: Might skip last pitch+yaw as well.
if (packetData.getPitch() == oldPitch && packetData.getYaw() == oldYaw) {
flyingQueue[i] = null;
continue;
}
// Run ray-tracing again with updated pitch and yaw.
useLoc.setPitch(packetData.getPitch());
useLoc.setYaw(packetData.getYaw());
direction = useLoc.getDirection(); // TODO: Better.
tags.clear();
tags.add("flying(" + i + ")"); // Interesting if this gets through.
collides = checkRayTracing(eyeX, eyeY, eyeZ, direction.getX(), direction.getY(), direction.getZ(), blockX, blockY, blockZ, face, tags, data.debug);
if (!collides) {
break;
}
flyingQueue[i] = null;
// Debug output.
if (data.debug) {
debug(player, "pitch=" + loc.getPitch() + " yaw=" + loc.getYaw() + " tags=" + StringUtil.join(tags, "+"));
}
if (checker.checkFlyingQueue(eyeX, eyeY, eyeZ, useLoc.getYaw(), useLoc.getPitch(),
blockX, blockY, blockZ, flyingHandle, face, tags, data.debug, player)) {
// Check passed.
collides = false;
}
checker.cleanup();
useLoc.setWorld(null);
}
// Cleanup.
Expand All @@ -155,7 +173,7 @@ public boolean check(final Player player, final Location loc, final Block block,
else {
data.visibleVL *= 0.99;
if (data.debug) {
debug(player, "pitch=" + loc.getPitch() + " yaw=" + loc.getYaw() + " tags=" + StringUtil.join(tags, "+"));
debug(player, "pitch=" + loc.getPitch() + ",yaw=" + loc.getYaw() + " tags=" + StringUtil.join(tags, "+"));
}
}

Expand Down
Expand Up @@ -31,4 +31,8 @@ public DataPacketFlying[] getHandle() {
return queue;
}

public boolean isFlyingQueueFetched() {
return queue != null;
}

}

0 comments on commit 180cf8a

Please sign in to comment.