mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-09-28 22:47:32 +02:00
[BREAKING] More on passable and ray tracing.
* Make RayTracing and PassableRayTracing implement interfaces. (rough, not used in tests yet etc.). * Optimize ray tracing use in BlockProperties. * Add an axis-wise implementation (buggy, hardly tested, thus not used yet).
This commit is contained in:
parent
f18e7e46d1
commit
19312bdbfa
@ -32,9 +32,9 @@ import fr.neatmonster.nocheatplus.checks.net.NetData;
|
||||
import fr.neatmonster.nocheatplus.checks.net.model.DataPacketFlying;
|
||||
import fr.neatmonster.nocheatplus.compat.MCAccess;
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.InteractRayTracing;
|
||||
import fr.neatmonster.nocheatplus.utilities.StringUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.InteractRayTracing;
|
||||
|
||||
public class Visible extends Check {
|
||||
|
||||
|
@ -24,6 +24,7 @@ import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.MovingData;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.model.LiftOffEnvelope;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.player.Passable;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.util.MovingUtil;
|
||||
import fr.neatmonster.nocheatplus.compat.MCAccess;
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockCache;
|
||||
@ -272,7 +273,7 @@ public class LostGround {
|
||||
// TODO: Full bounds check (!).
|
||||
final Location ref = from.getLocation();
|
||||
ref.setY(to.getY());
|
||||
if (BlockProperties.isPassable(from.getLocation(), ref)) {
|
||||
if (Passable.isPassable(from.getLocation(), ref)) {
|
||||
// TODO: Needs new model (store detailed on-ground properties).
|
||||
return applyLostGround(player, from, false, thisMove, data, "vcollide", tags);
|
||||
}
|
||||
|
@ -27,13 +27,27 @@ import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.MovingData;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.location.LocUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockProperties;
|
||||
import fr.neatmonster.nocheatplus.utilities.PassableRayTracing;
|
||||
import fr.neatmonster.nocheatplus.utilities.PlayerLocation;
|
||||
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.ICollidePassable;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.PassableRayTracing;
|
||||
|
||||
public class Passable extends Check {
|
||||
|
||||
private final PassableRayTracing rayTracing = new PassableRayTracing();
|
||||
/**
|
||||
* Convenience for player moving, to keep a better overview.
|
||||
*
|
||||
* @param from
|
||||
* @param to
|
||||
* @return
|
||||
*/
|
||||
public static boolean isPassable(Location from, Location to) {
|
||||
return BlockProperties.isPassable(from, to);
|
||||
//return BlockProperties.isPassableAxisWise(from, to);
|
||||
}
|
||||
|
||||
private final ICollidePassable rayTracing = new PassableRayTracing();
|
||||
//private final ICollidePassable rayTracing = new PassableAxisTracing();
|
||||
|
||||
public Passable() {
|
||||
super(CheckType.MOVING_PASSABLE);
|
||||
@ -62,6 +76,7 @@ public class Passable extends Check {
|
||||
boolean toPassable = to.isPassable();
|
||||
// General condition check for using ray-tracing.
|
||||
if (toPassable && cc.passableRayTracingCheck && (!cc.passableRayTracingBlockChangeOnly || manhattan > 0)) {
|
||||
rayTracing.setMargins(from.getEyeHeight(), from.getWidth() / 2.0); // max from/to + resolution ?
|
||||
rayTracing.set(from, to);
|
||||
rayTracing.loop();
|
||||
if (rayTracing.collides() || rayTracing.getStepsDone() >= rayTracing.getMaxSteps()) {
|
||||
@ -191,7 +206,7 @@ public class Passable extends Check {
|
||||
*/
|
||||
private boolean collidesIgnoreFirst(PlayerLocation from, PlayerLocation to) {
|
||||
rayTracing.set(from, to);
|
||||
rayTracing.setIgnorefirst();
|
||||
rayTracing.setIgnoreFirst();
|
||||
rayTracing.loop();
|
||||
return rayTracing.collides() || rayTracing.getStepsDone() >= rayTracing.getMaxSteps();
|
||||
}
|
||||
@ -204,6 +219,9 @@ public class Passable extends Check {
|
||||
* @return
|
||||
*/
|
||||
private boolean allowsSplitMove(final PlayerLocation from, final PlayerLocation to, final int manhattan) {
|
||||
if (!rayTracing.mightNeedSplitAxisHandling()) {
|
||||
return false;
|
||||
}
|
||||
// Always check y first.
|
||||
rayTracing.set(from.getX(), from.getY(), from.getZ(), from.getX(), to.getY(), from.getZ());
|
||||
rayTracing.loop();
|
||||
|
@ -16,7 +16,7 @@ package fr.neatmonster.nocheatplus.logging.debug;
|
||||
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.FakeBlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.RayTracing;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.RayTracing;
|
||||
|
||||
/**
|
||||
* Record blocks along a ray (and potentially other). Changes to blocks are not
|
||||
|
@ -48,6 +48,9 @@ import fr.neatmonster.nocheatplus.config.WorldConfigProvider;
|
||||
import fr.neatmonster.nocheatplus.logging.LogManager;
|
||||
import fr.neatmonster.nocheatplus.logging.StaticLog;
|
||||
import fr.neatmonster.nocheatplus.logging.Streams;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.ICollidePassable;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.PassableAxisTracing;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.PassableRayTracing;
|
||||
|
||||
/**
|
||||
* Properties of blocks.
|
||||
@ -308,6 +311,8 @@ public class BlockProperties {
|
||||
Material.POTATO,
|
||||
};
|
||||
|
||||
private static ICollidePassable rtRay = null;
|
||||
private static ICollidePassable rtAxis = null;
|
||||
private static BlockCache blockCache = null;
|
||||
private static PlayerLocation pLoc = null;
|
||||
|
||||
@ -450,6 +455,8 @@ public class BlockProperties {
|
||||
*/
|
||||
public static void init(final MCAccess mcAccess, final WorldConfigProvider<?> worldConfigProvider) {
|
||||
blockCache = mcAccess.getBlockCache(null);
|
||||
rtRay = new PassableRayTracing();
|
||||
rtAxis = new PassableAxisTracing();
|
||||
pLoc = new PlayerLocation(mcAccess, null);
|
||||
final Set<String> blocksFeatures = new LinkedHashSet<String>(); // getClass().getName() or some abstract.
|
||||
try{
|
||||
@ -2126,8 +2133,22 @@ public class BlockProperties {
|
||||
* @return
|
||||
*/
|
||||
public static final boolean isPassable(final Location from, final Location to) {
|
||||
return isPassable(rtRay, from, to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Axis-wise checking, like the client does.
|
||||
*
|
||||
* @param from
|
||||
* @param to
|
||||
* @return
|
||||
*/
|
||||
public static final boolean isPassableAxisWise(final Location from, final Location to) {
|
||||
return isPassable(rtAxis, from, to);
|
||||
}
|
||||
|
||||
private static boolean isPassable(final ICollidePassable rt, final Location from, final Location to) {
|
||||
blockCache.setAccess(from.getWorld());
|
||||
final PassableRayTracing rt = new PassableRayTracing();
|
||||
rt.setMaxSteps(60); // TODO: Configurable ?
|
||||
rt.setBlockCache(blockCache);
|
||||
rt.set(from.getX(), from.getY(), from.getZ(), to.getX(), to.getY(), to.getZ());
|
||||
@ -3066,7 +3087,6 @@ public class BlockProperties {
|
||||
}
|
||||
|
||||
// TODO: Actual ray-collision checking?
|
||||
// TODO: Heuristic workaround for certain situations [might be better outside of this, probably a simplified version ofr the normal case]?
|
||||
|
||||
// Check for workarounds.
|
||||
// TODO: check f_itchy once exists.
|
||||
@ -3074,13 +3094,53 @@ public class BlockProperties {
|
||||
return true;
|
||||
}
|
||||
// Does collide (most likely).
|
||||
// TODO: This is not entirely accurate.
|
||||
// TODO: Moving such that the full move rect overlaps, but no real collision (diagonal moves).
|
||||
// TODO: "Wrong" moves through edges of blocks (not sure, needs reproducing).
|
||||
// (Could allow start-end if passable + check first collision time or some estimate.)
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check passability with an arbitrary bounding box vs. a block.
|
||||
*
|
||||
* @param access
|
||||
* @param blockX
|
||||
* @param blockY
|
||||
* @param blockZ
|
||||
* @param minX
|
||||
* @param minY
|
||||
* @param minZ
|
||||
* @param maxX
|
||||
* @param maxY
|
||||
* @param maxZ
|
||||
* @return
|
||||
*/
|
||||
public static final boolean isPassableBox(final BlockCache access,
|
||||
final int blockX, final int blockY, final int blockZ,
|
||||
final double minX, final double minY, final double minZ,
|
||||
final double maxX, final double maxY, final double maxZ) {
|
||||
// TODO: This mostly is copy and paste from isPassableRay.
|
||||
final int id = access.getTypeId(blockX, blockY, blockZ);
|
||||
if (BlockProperties.isPassable(id)) {
|
||||
return true;
|
||||
}
|
||||
double[] bounds = access.getBounds(blockX, blockY, blockZ);
|
||||
if (bounds == null) {
|
||||
return true;
|
||||
}
|
||||
// (Coordinates are already passed in an ordered form.)
|
||||
if (!collidesBlock(access, minX, minY, minZ, maxX, maxY, maxZ, blockX, blockY, blockZ, id, bounds, blockFlags[id] | F_COLLIDE_EDGES)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for workarounds.
|
||||
// TODO: Adapted to use the version initially intended for ray-tracing. Should have an explicit thing for the box, and let the current ray-tracing variant use that, until THEY implement something real.
|
||||
// TODO: check f_itchy once exists.
|
||||
if (BlockProperties.isPassableWorkaround(access, blockX, blockY, blockZ, minX - blockX, minY - blockY, minZ - blockZ, id, maxX - minX, maxY - minY, maxZ - minZ, 1.0)) {
|
||||
return true;
|
||||
}
|
||||
// Does collide (most likely).
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for special case activation: trap door is climbable above ladder
|
||||
* with distinct facing.
|
||||
|
@ -0,0 +1,328 @@
|
||||
package fr.neatmonster.nocheatplus.utilities.collision;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
/**
|
||||
* Similar to ray-tracing, attempt to model how the client processes move vs.
|
||||
* block collision via y-x-z or similar (TODO: xz vs zx). Rough orientation is
|
||||
* the RayTracing classes or a thinkable interface, to be able to use similar
|
||||
* test cases later on.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public abstract class AxisTracing implements ICollide, ISetMargins {
|
||||
|
||||
// TODO: Consider an extra loop(coordinates + margins...) for convenience.
|
||||
|
||||
public static enum Axis {
|
||||
X_AXIS,
|
||||
Y_AXIS,
|
||||
Z_AXIS,
|
||||
NONE;
|
||||
}
|
||||
|
||||
/** The order of axis to be checked. */
|
||||
private final Axis[] axisOrder = new Axis[3];
|
||||
|
||||
/** Start coordinates (center). */
|
||||
private double x0, y0, z0;
|
||||
/** End coordinates (center). */
|
||||
private double x1, y1, z1;
|
||||
/** Margins for the bounding box, seen from center / start coordinates. Positive values. */
|
||||
private double marginXpos, marginXneg, marginYpos, marginYneg, marginZpos, marginZneg;
|
||||
|
||||
/** Result returned with collides() and reset to false on set/loop. */
|
||||
protected boolean collides;
|
||||
|
||||
/**
|
||||
* Number of steps, counting advancing on one axis for all axes. Does not
|
||||
* count the number of processed blocks. The step is increased before
|
||||
* calling step.
|
||||
*/
|
||||
protected int step = 0;
|
||||
|
||||
/**
|
||||
* Number of steps along one axis. Resets with each axis. Incremented before
|
||||
* calling step.
|
||||
*/
|
||||
protected int axisStep = 0;
|
||||
|
||||
private int maxSteps = 0;
|
||||
|
||||
// TODO: maxBlocks (...).
|
||||
|
||||
// TODO: ignoreFirst -> Should be ignore a specific block or blocks within the initial bounds or ...?
|
||||
|
||||
// TODO: Margin only for iteration, not for the bounds (for use-cases like fences).
|
||||
|
||||
public AxisTracing() {
|
||||
setDefaultAxisOrder();
|
||||
}
|
||||
|
||||
public int getMaxSteps() {
|
||||
return maxSteps;
|
||||
}
|
||||
|
||||
public void setMaxSteps(int maxSteps) {
|
||||
this.maxSteps = maxSteps;
|
||||
}
|
||||
|
||||
public int getStepsDone() {
|
||||
return step;
|
||||
}
|
||||
|
||||
public int getAxisStepsDone() {
|
||||
return axisStep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate if a collision appeared during loop().
|
||||
* @return
|
||||
*/
|
||||
public boolean collides() {
|
||||
return collides;
|
||||
}
|
||||
|
||||
public void setDefaultAxisOrder() {
|
||||
setAxisOrder(Axis.Y_AXIS, Axis.X_AXIS, Axis.Z_AXIS);
|
||||
}
|
||||
|
||||
public void setAxisOrder(Axis first, Axis second, Axis third) {
|
||||
axisOrder[0] = first;
|
||||
axisOrder[1] = second;
|
||||
axisOrder[2] = third;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMargins(final double height, final double xzMargin) {
|
||||
this.marginXneg = this.marginXpos = this.marginZneg = this.marginZpos = xzMargin;
|
||||
this.marginYneg = 0.0;
|
||||
this.marginYpos = height;
|
||||
}
|
||||
|
||||
public void set(double x0, double y0, double z0, double x1, double y1, double z1) {
|
||||
collides = false;
|
||||
step = 0;
|
||||
this.x0 = x0;
|
||||
this.y0 = y0;
|
||||
this.z0 = z0;
|
||||
this.x1 = x1;
|
||||
this.y1 = y1;
|
||||
this.z1 = z1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loop through blocks.
|
||||
*/
|
||||
public void loop() {
|
||||
// Current start coordinates.
|
||||
double x = this.x0;
|
||||
double y = this.y0;
|
||||
double z = this.z0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
switch (axisOrder[i]) {
|
||||
case Y_AXIS: {
|
||||
runAxisY(x, y, z);
|
||||
y = this.y1;
|
||||
break;
|
||||
}
|
||||
case X_AXIS: {
|
||||
runAxisX(x, y, z);
|
||||
x = this.x1;
|
||||
break;
|
||||
}
|
||||
case Z_AXIS: {
|
||||
runAxisZ(x, y, z);
|
||||
z = this.z1;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Just skip.
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (collides) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void runAxisY(final double xIn, final double yIn, final double zIn) {
|
||||
// Skip if there is nothing to iterate.
|
||||
if (yIn == this.y1) {
|
||||
return;
|
||||
}
|
||||
// Iterate over axis, applying margins.
|
||||
final int increment;
|
||||
final double xMin = xIn - marginXneg;
|
||||
final double xMax = xIn + marginXpos;
|
||||
final double zMin = zIn - marginZneg;
|
||||
final double zMax = zIn + marginZpos;
|
||||
final double yStart, yEnd;
|
||||
if (yIn < this.y1) {
|
||||
increment = 1;
|
||||
yStart = yIn - marginYneg;
|
||||
yEnd = this.y1 + marginYpos;
|
||||
}
|
||||
else {
|
||||
increment = -1;
|
||||
yStart = yIn + marginYpos;
|
||||
yEnd = this.y1 - marginYneg;
|
||||
}
|
||||
final int iMinX = Location.locToBlock(xMin);
|
||||
final int iMaxX = Location.locToBlock(xMax);
|
||||
final int iMinZ = Location.locToBlock(zMin);
|
||||
final int iMaxZ = Location.locToBlock(zMax);
|
||||
final int iStartY = Location.locToBlock(yStart);
|
||||
final int iEndY = Location.locToBlock(yEnd);
|
||||
axisStep = 0;
|
||||
for (int y = iStartY; y <= iEndY; y += increment) {
|
||||
++step;
|
||||
++axisStep;
|
||||
if (step > maxSteps) {
|
||||
return;
|
||||
}
|
||||
// TODO: Ignore first setting?
|
||||
for (int x = iMinX; x <= iMaxX; x++) {
|
||||
for (int z = iMinZ; z <= iMaxZ; z++) {
|
||||
if (!step(x, y, z, xMin, increment == 1 ? yStart : yEnd, zMin, xMax, increment == 1 ? yEnd : yStart, zMax, Axis.Y_AXIS, increment)) {
|
||||
collides = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// No collision.
|
||||
return;
|
||||
}
|
||||
|
||||
private void runAxisX(final double xIn, final double yIn, final double zIn) {
|
||||
// Skip if there is nothing to iterate.
|
||||
if (xIn == this.x1) {
|
||||
return;
|
||||
}
|
||||
// Iterate over axis, applying margins.
|
||||
final int increment;
|
||||
final double yMin = yIn - marginYneg;
|
||||
final double yMax = yIn + marginYpos;
|
||||
final double zMin = zIn - marginZneg;
|
||||
final double zMax = zIn + marginZpos;
|
||||
final double xStart, xEnd;
|
||||
if (xIn < this.x1) {
|
||||
increment = 1;
|
||||
xStart = xIn - marginXneg;
|
||||
xEnd = this.x1 + marginXpos;
|
||||
}
|
||||
else {
|
||||
increment = -1;
|
||||
xStart = xIn + marginXpos;
|
||||
xEnd = this.x1 - marginXneg;
|
||||
}
|
||||
final int iMinY = Location.locToBlock(yMin);
|
||||
final int iMaxY = Location.locToBlock(yMax);
|
||||
final int iMinZ = Location.locToBlock(zMin);
|
||||
final int iMaxZ = Location.locToBlock(zMax);
|
||||
final int iStartX = Location.locToBlock(xStart);
|
||||
final int iEndX = Location.locToBlock(xEnd);
|
||||
axisStep = 0;
|
||||
for (int x = iStartX; x <= iEndX; x += increment) {
|
||||
++step;
|
||||
++axisStep;
|
||||
if (step > maxSteps) {
|
||||
return;
|
||||
}
|
||||
// TODO: Ignore first setting?
|
||||
for (int y = iMinY; y <= iMaxY; y++) {
|
||||
for (int z = iMinZ; z <= iMaxZ; z++) {
|
||||
if (!step(x, y, z, increment == 1 ? xStart : xEnd, yMin, zMin, increment == 1 ? xEnd : xStart, yMax, zMax, Axis.X_AXIS, increment)) {
|
||||
collides = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// No collision.
|
||||
return;
|
||||
}
|
||||
|
||||
private void runAxisZ(final double xIn, final double yIn, final double zIn) {
|
||||
// Skip if there is nothing to iterate.
|
||||
if (zIn == this.z1) {
|
||||
return;
|
||||
}
|
||||
// Iterate over axis, applying margins.
|
||||
final int increment;
|
||||
final double yMin = yIn - marginYneg;
|
||||
final double yMax = yIn + marginYpos;
|
||||
final double xMin = xIn - marginXneg;
|
||||
final double xMax = xIn + marginXpos;
|
||||
final double zStart, zEnd;
|
||||
if (zIn < this.z1) {
|
||||
increment = 1;
|
||||
zStart = zIn - marginZneg;
|
||||
zEnd = this.z1 + marginZpos;
|
||||
}
|
||||
else {
|
||||
increment = -1;
|
||||
zStart = zIn + marginZpos;
|
||||
zEnd = this.z1 - marginZneg;
|
||||
}
|
||||
final int iMinY = Location.locToBlock(yMin);
|
||||
final int iMaxY = Location.locToBlock(yMax);
|
||||
final int iMinX = Location.locToBlock(xMin);
|
||||
final int iMaxX = Location.locToBlock(xMax);
|
||||
final int iStartZ = Location.locToBlock(zStart);
|
||||
final int iEndZ = Location.locToBlock(zEnd);
|
||||
axisStep = 0;
|
||||
for (int z = iStartZ; z <= iEndZ; z += increment) {
|
||||
++step;
|
||||
++axisStep;
|
||||
if (step > maxSteps) {
|
||||
return;
|
||||
}
|
||||
// TODO: Ignore first setting?
|
||||
for (int y = iMinY; y <= iMaxY; y++) {
|
||||
for (int x = iMinX; x <= iMaxX; x++) {
|
||||
if (!step(x, y, z, xMin, yMin, increment == 1 ? zStart : zEnd, xMax, yMax, increment == 1 ? zEnd : zStart, Axis.Z_AXIS, increment)) {
|
||||
collides = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// No collision.
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a block position for collision with the ordered bounds of a move
|
||||
* along one axis.
|
||||
*
|
||||
* @param blockX
|
||||
* Position of the block that might be colliding.
|
||||
* @param blockY
|
||||
* @param blockZ
|
||||
* @param minX
|
||||
* Minimum coordinates of the move along one axis, including
|
||||
* bounds.
|
||||
* @param minY
|
||||
* @param minZ
|
||||
* @param maxX
|
||||
* Maximum coordinates of the move along one axis, including
|
||||
* bounds.
|
||||
* @param maxY
|
||||
* @param maxZ
|
||||
* @param axis
|
||||
* The axis along which the bounds are stretched.
|
||||
* @param increment
|
||||
* Direction of the move concerning the given axis (1 means from
|
||||
* min to max, -1 means from max to min).
|
||||
* @return
|
||||
*/
|
||||
protected abstract boolean step(int blockX, int blockY, int blockZ,
|
||||
double minX, double minY, double minZ, double maxX, double maxY, double maxZ,
|
||||
Axis axis, int increment);
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package fr.neatmonster.nocheatplus.utilities.collision;
|
||||
|
||||
/**
|
||||
* A collision checker much like RayTracing or AxisTracing.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public interface ICollide {
|
||||
|
||||
/**
|
||||
* Set the maximum steps to be done during loop(). Setting to 0 should
|
||||
* disable the upper limit. (Integer.MAX_VALUE will be on the safe side as
|
||||
* well.)
|
||||
*
|
||||
* @param maxSteps
|
||||
*/
|
||||
public void setMaxSteps(int maxSteps);
|
||||
public int getMaxSteps();
|
||||
|
||||
/**
|
||||
* Call before loop to set the coordinates of a move.
|
||||
*
|
||||
* @param x0
|
||||
* @param y0
|
||||
* @param z0
|
||||
* @param x1
|
||||
* @param y1
|
||||
* @param z1
|
||||
*/
|
||||
public void set(double x0, double y0, double z0, double x1, double y1, double z1);
|
||||
|
||||
/**
|
||||
* Run the collision checking.
|
||||
*/
|
||||
public void loop();
|
||||
|
||||
/**
|
||||
* Get the (primary) steps done during loop(). In case of aborting due to
|
||||
* the max steps limit, the result should be greater or equal to
|
||||
* getMaxSteps().
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getStepsDone();
|
||||
|
||||
/**
|
||||
* Test if the testing found a collision during loop().
|
||||
* @return
|
||||
*/
|
||||
public boolean collides();
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package fr.neatmonster.nocheatplus.utilities.collision;
|
||||
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.PlayerLocation;
|
||||
|
||||
/**
|
||||
* Test for collision testing for passing through blocks.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public interface ICollidePassable extends ICollide, ISetMargins {
|
||||
|
||||
// TODO: IRayTracing
|
||||
|
||||
public void setBlockCache(BlockCache blockCache);
|
||||
public BlockCache getBlockCache();
|
||||
|
||||
/**
|
||||
* Set from PlayerLocation instances. May use the BlockCache from the
|
||||
* from-location internally.
|
||||
*
|
||||
* @param from
|
||||
* @param to
|
||||
*/
|
||||
public void set(final PlayerLocation from, final PlayerLocation to);
|
||||
|
||||
/**
|
||||
* Ignore the first block. Must be called after set, because set should
|
||||
* override internal state with false.
|
||||
*/
|
||||
// TODO: Switch to ignoreBlock(int, int, int) rather.
|
||||
public void setIgnoreFirst();
|
||||
|
||||
/**
|
||||
* Test if the first block is set to be ignored (resets to false with set).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean getIgnoreFirst();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Return false in order to prevent workarounds with split by axis
|
||||
* checking.
|
||||
*/
|
||||
public boolean mightNeedSplitAxisHandling();
|
||||
|
||||
/**
|
||||
* Remove reference to objects passed from outside (BlockCache, but not
|
||||
* calling their cleanup methods).
|
||||
*/
|
||||
public void cleanup();
|
||||
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package fr.neatmonster.nocheatplus.utilities.collision;
|
||||
|
||||
public interface ISetMargins {
|
||||
|
||||
/**
|
||||
* Typical player specific margins (none below feet, eye height, same
|
||||
* xzMargin to all sides from the center). Calling this may or may not have
|
||||
* effect.
|
||||
*
|
||||
* @param height
|
||||
* @param xzMargin
|
||||
*/
|
||||
public void setMargins(final double height, final double xzMargin);
|
||||
|
||||
}
|
@ -12,10 +12,14 @@
|
||||
* 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.utilities;
|
||||
package fr.neatmonster.nocheatplus.utilities.collision;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockProperties;
|
||||
import fr.neatmonster.nocheatplus.utilities.FakeBlockCache;
|
||||
|
||||
|
||||
|
||||
/**
|
@ -0,0 +1,73 @@
|
||||
package fr.neatmonster.nocheatplus.utilities.collision;
|
||||
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockProperties;
|
||||
import fr.neatmonster.nocheatplus.utilities.PlayerLocation;
|
||||
|
||||
public class PassableAxisTracing extends AxisTracing implements ICollidePassable {
|
||||
|
||||
private BlockCache blockCache;
|
||||
|
||||
private boolean ignoreFirst = false;
|
||||
|
||||
// TODO: Consider an iteration margin as well (0.5 below for fences).
|
||||
|
||||
public BlockCache getBlockCache() {
|
||||
return blockCache;
|
||||
}
|
||||
|
||||
public void setBlockCache(BlockCache blockCache) {
|
||||
this.blockCache = blockCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean step(final int blockX, final int blockY, final int blockZ,
|
||||
final double minX, final double minY, final double minZ,
|
||||
final double maxX, final double maxY, final double maxZ,
|
||||
final Axis axis, final int increment) {
|
||||
if (ignoreFirst && step == 1) {
|
||||
return true;
|
||||
}
|
||||
if (BlockProperties.isPassableBox(blockCache, blockX, blockY, blockZ, minX, minY, minZ, maxX, maxY, maxZ)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
collides = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(double x0, double y0, double z0, double x1, double y1, double z1) {
|
||||
super.set(x0, y0, z0, x1, y1, z1);
|
||||
ignoreFirst = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(PlayerLocation from, PlayerLocation to) {
|
||||
set(from.getX(), from.getY(), from.getZ(), to.getX(), to.getY(), to.getZ());
|
||||
setBlockCache(from.getBlockCache());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIgnoreFirst() {
|
||||
// TODO: ignoreBlock rather.
|
||||
ignoreFirst = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getIgnoreFirst() {
|
||||
return ignoreFirst;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mightNeedSplitAxisHandling() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
blockCache = null;
|
||||
}
|
||||
|
||||
}
|
@ -12,9 +12,13 @@
|
||||
* 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.utilities;
|
||||
package fr.neatmonster.nocheatplus.utilities.collision;
|
||||
|
||||
public class PassableRayTracing extends RayTracing{
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockProperties;
|
||||
import fr.neatmonster.nocheatplus.utilities.PlayerLocation;
|
||||
|
||||
public class PassableRayTracing extends RayTracing implements ICollidePassable {
|
||||
|
||||
protected BlockCache blockCache = null;
|
||||
|
||||
@ -22,19 +26,17 @@ public class PassableRayTracing extends RayTracing{
|
||||
|
||||
protected boolean ignorefirst = false;
|
||||
|
||||
@Override
|
||||
public BlockCache getBlockCache() {
|
||||
return blockCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockCache(BlockCache blockCache) {
|
||||
this.blockCache = blockCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set from PlayerLocation instances. Currently takes BlockCache from the from-location.
|
||||
* @param from
|
||||
* @param to
|
||||
*/
|
||||
@Override
|
||||
public void set(final PlayerLocation from, final PlayerLocation to){
|
||||
set(from.getX(), from.getY(), from.getZ(), to.getX(), to.getY(), to.getZ());
|
||||
setBlockCache(from.getBlockCache()); // TODO: This might better be done extra.
|
||||
@ -50,32 +52,24 @@ public class PassableRayTracing extends RayTracing{
|
||||
ignorefirst = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean collides(){
|
||||
return collides;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ignore the first block. Must be called after set, because set will override this with false.
|
||||
*/
|
||||
public void setIgnorefirst(){
|
||||
@Override
|
||||
public void setIgnoreFirst(){
|
||||
this.ignorefirst = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the first block is set to be ignored (resets to false with set).
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean getIgnoreFirst(){
|
||||
return ignorefirst;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove reference to BlockCache.
|
||||
*/
|
||||
@Override
|
||||
public void cleanup(){
|
||||
if (blockCache != null){
|
||||
blockCache = null;
|
||||
}
|
||||
blockCache = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -93,4 +87,14 @@ public class PassableRayTracing extends RayTracing{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mightNeedSplitAxisHandling() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMargins(double height, double xzMargin) {
|
||||
// (No effect.)
|
||||
}
|
||||
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
* 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.utilities;
|
||||
package fr.neatmonster.nocheatplus.utilities.collision;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
@ -21,7 +21,7 @@ import org.bukkit.Location;
|
||||
* @author mc_dev
|
||||
*
|
||||
*/
|
||||
public abstract class RayTracing {
|
||||
public abstract class RayTracing implements ICollide {
|
||||
|
||||
// /** End point coordinates (from, to) */
|
||||
protected double x0, y0, z0; // x1, y1, z1;
|
||||
@ -72,15 +72,7 @@ public abstract class RayTracing {
|
||||
set(0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* After this calling loop is possible.
|
||||
* @param x0
|
||||
* @param y0
|
||||
* @param z0
|
||||
* @param x1
|
||||
* @param y1
|
||||
* @param z1
|
||||
*/
|
||||
@Override
|
||||
public void set(double x0, double y0, double z0, double x1, double y1, double z1) {
|
||||
this.x0 = x0;
|
||||
this.y0 = y0;
|
||||
@ -135,9 +127,7 @@ public abstract class RayTracing {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loop through blocks.
|
||||
*/
|
||||
@Override
|
||||
public void loop() {
|
||||
|
||||
// Time to block edge.
|
||||
@ -367,7 +357,9 @@ public abstract class RayTracing {
|
||||
* Indicate if a collision appeared during loop(). This must be overridden to return a result other than false.
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean collides() {
|
||||
// TODO: Switch to using a protected flag right away.
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -387,22 +379,17 @@ public abstract class RayTracing {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int getStepsDone() {
|
||||
return step;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximal number of steps that loop will do.
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int getMaxSteps() {
|
||||
return maxSteps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximal number of steps that loop will do.
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public void setMaxSteps(int maxSteps) {
|
||||
this.maxSteps = maxSteps;
|
||||
}
|
@ -19,8 +19,8 @@ import org.junit.Test;
|
||||
|
||||
import fr.neatmonster.nocheatplus.logging.StaticLog;
|
||||
import fr.neatmonster.nocheatplus.utilities.FakeBlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.InteractRayTracing;
|
||||
import fr.neatmonster.nocheatplus.utilities.build.BuildParameters;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.InteractRayTracing;
|
||||
|
||||
public class TestInteractRayTracing {
|
||||
|
||||
|
@ -19,10 +19,12 @@ import org.junit.Test;
|
||||
|
||||
import fr.neatmonster.nocheatplus.logging.StaticLog;
|
||||
import fr.neatmonster.nocheatplus.utilities.FakeBlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.PassableRayTracing;
|
||||
import fr.neatmonster.nocheatplus.utilities.build.BuildParameters;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.PassableRayTracing;
|
||||
|
||||
public class TestPassableRayTracing {
|
||||
|
||||
// TODO: Which tests to run on ICollidePassable with PassableAxisRayTracing as well...
|
||||
|
||||
// TODO: Moving into a block,
|
||||
// TODO: Moving out of a block
|
||||
|
@ -22,10 +22,10 @@ import org.bukkit.Location;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.junit.Test;
|
||||
|
||||
import fr.neatmonster.nocheatplus.utilities.RayTracing;
|
||||
import fr.neatmonster.nocheatplus.utilities.StringUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.build.BuildParameters;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.RayTracing;
|
||||
|
||||
public class TestRayTracing {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user