mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-06-26 06:14:42 +02:00
Implement ignoreInitiallyColliding for (Passable) AxisTracing.
Not really adding general purpose implementations for BlockPositionContainer, likely good enough for what we need for the time being.
This commit is contained in:
parent
64dedf3434
commit
ec333fb432
|
@ -0,0 +1,38 @@
|
|||
package fr.neatmonster.nocheatplus.components.location;
|
||||
|
||||
/**
|
||||
* Simple immutable block position.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public class BlockPositionGet implements IGetBlockPosition {
|
||||
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
|
||||
public BlockPositionGet(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
// TODO: equals vs. IGetBlockPosition, Coord(Hash)Map compatible hashCode.
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package fr.neatmonster.nocheatplus.components.location;
|
||||
|
||||
/**
|
||||
* Minimal interface for adding block positions.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public interface IAddBlockPosition {
|
||||
|
||||
/** Add block coordinates. */
|
||||
public void addBlockPosition(int x, int y, int z);
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package fr.neatmonster.nocheatplus.components.location;
|
||||
|
||||
/**
|
||||
* Minimal interface for checking if a block positions is contained.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public interface IContainBlockPosition {
|
||||
|
||||
public boolean containsBlockPosition(int x, int y, int z);
|
||||
|
||||
public boolean containsBlockPosition(IGetBlockPosition blockPosition);
|
||||
|
||||
}
|
|
@ -48,6 +48,7 @@ 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.BlockPositionContainer;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.ICollidePassable;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.PassableAxisTracing;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.PassableRayTracing;
|
||||
|
@ -3153,6 +3154,43 @@ public class BlockProperties {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the block coordinates that are colliding via a isPassableBox check
|
||||
* for the given bounds to the given container.
|
||||
*
|
||||
* @param access
|
||||
* @param minX
|
||||
* @param minY
|
||||
* @param minZ
|
||||
* @param maxX
|
||||
* @param maxY
|
||||
* @param maxZ
|
||||
* @param results
|
||||
*/
|
||||
public static final int collectInitiallyCollidingBlocks(final BlockCache access,
|
||||
final double minX, final double minY, final double minZ,
|
||||
final double maxX, final double maxY, final double maxZ,
|
||||
final BlockPositionContainer results) {
|
||||
int added = 0;
|
||||
final int iMinX = Location.locToBlock(minX);
|
||||
final int iMaxX = Location.locToBlock(maxX);
|
||||
final int iMinY = Location.locToBlock(minY);
|
||||
final int iMaxY = Location.locToBlock(maxY);
|
||||
final int iMinZ = Location.locToBlock(minZ);
|
||||
final int iMaxZ = Location.locToBlock(maxZ);
|
||||
for (int x = iMinX; x <= iMaxX; x++) {
|
||||
for (int z = iMinZ; z <= iMaxZ; z++) {
|
||||
for (int y = iMinY; y <= iMaxY; y++) {
|
||||
if (!isPassableBox(access, x, y, z, minX, minY, minZ, maxX, maxY, maxZ)) {
|
||||
results.addBlockPosition(x, y, z);
|
||||
++added;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for special case activation: trap door is climbable above ladder
|
||||
* with distinct facing.
|
||||
|
|
|
@ -34,6 +34,11 @@ public abstract class AxisTracing implements ICollide, ISetMargins {
|
|||
*/
|
||||
private boolean cutOppositeDirectionMargin = false;
|
||||
|
||||
private boolean ignoreInitiallyColliding = false;
|
||||
|
||||
/** Blocks that are to be ignored. */
|
||||
private final BlockPositionContainer ignoredBlocks = new BlockPositionContainer();
|
||||
|
||||
/** Result returned with collides() and reset to false on set/loop. */
|
||||
protected boolean collides;
|
||||
|
||||
|
@ -77,6 +82,16 @@ public abstract class AxisTracing implements ICollide, ISetMargins {
|
|||
return axisStep;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIgnoreInitiallyColliding(boolean ignoreInitiallyColliding) {
|
||||
this.ignoreInitiallyColliding = ignoreInitiallyColliding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getIgnoreInitiallyColliding() {
|
||||
return ignoreInitiallyColliding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate if a collision appeared during loop().
|
||||
* @return
|
||||
|
@ -131,7 +146,10 @@ public abstract class AxisTracing implements ICollide, ISetMargins {
|
|||
double x = this.x0;
|
||||
double y = this.y0;
|
||||
double z = this.z0;
|
||||
// TODO: if (ignoreInitiallyColliding) -> fetch blocks, test in runAxis.
|
||||
if (ignoreInitiallyColliding) {
|
||||
collectInitiallyCollidingBlocks(x0 - marginXneg, y0 - marginYneg, z0 - marginZneg,
|
||||
x0 + marginXpos, y0 + marginYpos, z0 + marginZpos, ignoredBlocks);
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
final Axis axis = axisOrder[i];
|
||||
collidesAxis = axis; // Ensure here, to get it on max steps.
|
||||
|
@ -157,6 +175,9 @@ public abstract class AxisTracing implements ICollide, ISetMargins {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (ignoreInitiallyColliding) {
|
||||
ignoredBlocks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -197,10 +218,13 @@ public abstract class AxisTracing implements ICollide, ISetMargins {
|
|||
if (step > maxSteps) {
|
||||
return;
|
||||
}
|
||||
// TODO: Ignore first setting?
|
||||
final boolean checkInitiallyColliding = ignoreInitiallyColliding && !ignoredBlocks.isEmpty();
|
||||
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)) {
|
||||
if (checkInitiallyColliding && ignoredBlocks.containsBlockPosition(x, y, z)) {
|
||||
// Ignore.
|
||||
}
|
||||
else if (!step(x, y, z, xMin, increment == 1 ? yStart : yEnd, zMin, xMax, increment == 1 ? yEnd : yStart, zMax, Axis.Y_AXIS, increment)) {
|
||||
collides = true;
|
||||
return;
|
||||
}
|
||||
|
@ -248,10 +272,13 @@ public abstract class AxisTracing implements ICollide, ISetMargins {
|
|||
if (step > maxSteps) {
|
||||
return;
|
||||
}
|
||||
// TODO: Ignore first setting?
|
||||
final boolean checkInitiallyColliding = ignoreInitiallyColliding && !ignoredBlocks.isEmpty();
|
||||
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)) {
|
||||
if (checkInitiallyColliding && ignoredBlocks.containsBlockPosition(x, y, z)) {
|
||||
// Ignore.
|
||||
}
|
||||
else if (!step(x, y, z, increment == 1 ? xStart : xEnd, yMin, zMin, increment == 1 ? xEnd : xStart, yMax, zMax, Axis.X_AXIS, increment)) {
|
||||
collides = true;
|
||||
return;
|
||||
}
|
||||
|
@ -293,16 +320,19 @@ public abstract class AxisTracing implements ICollide, ISetMargins {
|
|||
final int iMaxX = Location.locToBlock(xMax);
|
||||
final int iStartZ = Location.locToBlock(zStart);
|
||||
axisStep = 0;
|
||||
final boolean checkInitiallyColliding = ignoreInitiallyColliding && !ignoredBlocks.isEmpty();
|
||||
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)) {
|
||||
if (checkInitiallyColliding && ignoredBlocks.containsBlockPosition(x, y, z)) {
|
||||
// Ignore.
|
||||
}
|
||||
else if (!step(x, y, z, xMin, yMin, increment == 1 ? zStart : zEnd, xMax, yMax, increment == 1 ? zEnd : zStart, Axis.Z_AXIS, increment)) {
|
||||
collides = true;
|
||||
return;
|
||||
}
|
||||
|
@ -313,6 +343,23 @@ public abstract class AxisTracing implements ICollide, ISetMargins {
|
|||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* In case ignoreInitiallyColliding is set, this will be called to do the
|
||||
* actual collision checking with the given initial margins.
|
||||
*
|
||||
* @param minX
|
||||
* @param minY
|
||||
* @param minZ
|
||||
* @param maxX
|
||||
* @param maxY
|
||||
* @param maxZ
|
||||
* @param results
|
||||
*/
|
||||
protected abstract void collectInitiallyCollidingBlocks(
|
||||
final double minX, final double minY, final double minZ,
|
||||
final double maxX, final double maxY, final double maxZ,
|
||||
final BlockPositionContainer results);
|
||||
|
||||
/**
|
||||
* Check a block position for collision with the ordered bounds of a move
|
||||
* along one axis.
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
package fr.neatmonster.nocheatplus.utilities.collision;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import fr.neatmonster.nocheatplus.components.location.BlockPositionGet;
|
||||
import fr.neatmonster.nocheatplus.components.location.IAddBlockPosition;
|
||||
import fr.neatmonster.nocheatplus.components.location.IContainBlockPosition;
|
||||
import fr.neatmonster.nocheatplus.components.location.IGetBlockPosition;
|
||||
|
||||
/**
|
||||
* A kept-simple container for block positions, meant to provide fast adding and
|
||||
* fast contains checks (and fast clear). Intended use is to add blocks first,
|
||||
* then query if blocks are contained with advancing coordinates like with
|
||||
* ray-tracing or axis-tracing. Currently adding blocks twice is not meant to
|
||||
* happen, and we assume blocks to be few.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public class BlockPositionContainer implements IAddBlockPosition, IContainBlockPosition {
|
||||
|
||||
// TODO: Not sure where to put this.
|
||||
// TODO: Future use / interfacing could involve collecting cuboids from block positions (mining/activity/areas).
|
||||
|
||||
// TODO: Consider switching to HashSet or CoordMap.
|
||||
private final LinkedList<BlockPositionGet> blocks = new LinkedList<BlockPositionGet>();
|
||||
|
||||
private int minX, minY, minZ, maxX, maxY, maxZ;
|
||||
|
||||
public BlockPositionContainer() {
|
||||
resetBoundaries();
|
||||
}
|
||||
|
||||
private void resetBoundaries() {
|
||||
minX = Integer.MAX_VALUE;
|
||||
minY = Integer.MAX_VALUE;
|
||||
minZ = Integer.MAX_VALUE;
|
||||
maxX = Integer.MIN_VALUE;
|
||||
maxY = Integer.MIN_VALUE;
|
||||
maxZ = Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
private void fitBoundaries(final int x, final int y, final int z) {
|
||||
minX = Math.min(x, minX);
|
||||
minY = Math.min(y, minY);
|
||||
minZ = Math.min(z, minZ);
|
||||
maxX = Math.max(x, maxX);
|
||||
maxY = Math.max(y, maxY);
|
||||
maxZ = Math.max(z, maxZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBlockPosition(final int x, final int y, final int z) {
|
||||
fitBoundaries(x, y, z);
|
||||
blocks.add(new BlockPositionGet(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsBlockPosition(final int x, final int y, final int z) {
|
||||
if (x < minX || y < minY || z < minZ || x > maxX || y > maxY || z > maxZ) {
|
||||
return false;
|
||||
}
|
||||
for (final BlockPositionGet pos : blocks) {
|
||||
if (x == pos.getBlockX() && z == pos.getBlockZ() && y == pos.getBlockY()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsBlockPosition(final IGetBlockPosition blockPosition) {
|
||||
return containsBlockPosition(blockPosition.getBlockX(), blockPosition.getBlockY(), blockPosition.getBlockZ());
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return blocks.isEmpty();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
if (!isEmpty()) {
|
||||
resetBoundaries();
|
||||
blocks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -24,7 +24,8 @@ public interface ICollide {
|
|||
|
||||
/**
|
||||
* Call before loop, in order to skip checking blocks that are found to be
|
||||
* colliding at the start of loop. May or may not have any effect.
|
||||
* colliding at the start of loop. May or may not have any effect. This must
|
||||
* not be called during processing of loop.
|
||||
*
|
||||
* @param ignoreInitiallyColliding
|
||||
*/
|
||||
|
|
|
@ -8,8 +8,6 @@ public class PassableAxisTracing extends AxisTracing implements ICollidePassable
|
|||
|
||||
private BlockCache blockCache;
|
||||
|
||||
private boolean ignoreInitiallyColliding = false;
|
||||
|
||||
// TODO: Might need another option for margins (option to skip margin for the axis-start point, or alter ignoreFirst behavior).
|
||||
// TODO: Consider an iteration margin as well (0.5 below for fences).
|
||||
|
||||
|
@ -21,15 +19,17 @@ public class PassableAxisTracing extends AxisTracing implements ICollidePassable
|
|||
this.blockCache = blockCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void collectInitiallyCollidingBlocks(double minX, double minY, double minZ, double maxX, double maxY,
|
||||
double maxZ, BlockPositionContainer results) {
|
||||
BlockProperties.collectInitiallyCollidingBlocks(blockCache, minX, minY, minZ, maxX, maxY, maxZ, results);
|
||||
}
|
||||
|
||||
@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) {
|
||||
// TODO: Ignore blocks by coordinates (handle before calling step).
|
||||
if (ignoreInitiallyColliding && step == 1) {
|
||||
return true;
|
||||
}
|
||||
if (BlockProperties.isPassableBox(blockCache, blockX, blockY, blockZ, minX, minY, minZ, maxX, maxY, maxZ)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -50,16 +50,6 @@ public class PassableAxisTracing extends AxisTracing implements ICollidePassable
|
|||
setBlockCache(from.getBlockCache());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIgnoreInitiallyColliding(boolean ignoreInitiallyColliding) {
|
||||
this.ignoreInitiallyColliding = ignoreInitiallyColliding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getIgnoreInitiallyColliding() {
|
||||
return ignoreInitiallyColliding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mightNeedSplitAxisHandling() {
|
||||
return false;
|
||||
|
|
Loading…
Reference in New Issue
Block a user