[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:
asofold 2016-06-09 23:54:45 +02:00
parent f18e7e46d1
commit 19312bdbfa
16 changed files with 658 additions and 58 deletions

View File

@ -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 {

View File

@ -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);
}

View File

@ -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();

View File

@ -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

View File

@ -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.

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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;
/**

View File

@ -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;
}
}

View File

@ -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.)
}
}

View File

@ -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;
}

View File

@ -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 {

View File

@ -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

View File

@ -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 {