mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-12-27 02:48:04 +01:00
Add heuristic InteractRayTracing.
This commit is contained in:
parent
89cbbfdddb
commit
3f7e2d44f1
@ -0,0 +1,149 @@
|
||||
package fr.neatmonster.nocheatplus.utilities;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
/**
|
||||
* Rough ray-tracing for interaction with something.
|
||||
* @author mc_dev
|
||||
*
|
||||
*/
|
||||
public class InteractRayTracing extends RayTracing {
|
||||
|
||||
private static final int[][] incr = new int[][]{
|
||||
{1, 0, 0},
|
||||
{0, 1, 0},
|
||||
{0, 0, 1},
|
||||
{-1, 0, 0},
|
||||
{0, -1, 0},
|
||||
{0, 0, -1},
|
||||
};
|
||||
|
||||
protected BlockCache blockCache = null;
|
||||
|
||||
protected boolean collides = false;
|
||||
|
||||
protected boolean strict = false;
|
||||
|
||||
protected int lastBx, lastBy, lastBz;
|
||||
|
||||
protected int targetBx, targetBy, targetBz;
|
||||
|
||||
public InteractRayTracing(){
|
||||
super();
|
||||
}
|
||||
|
||||
public InteractRayTracing(boolean strict){
|
||||
super();
|
||||
this.strict = strict;
|
||||
}
|
||||
|
||||
public BlockCache getBlockCache() {
|
||||
return blockCache;
|
||||
}
|
||||
|
||||
public void setBlockCache(BlockCache blockCache) {
|
||||
this.blockCache = blockCache;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.neatmonster.nocheatplus.utilities.RayTracing#set(double, double, double, double, double, double)
|
||||
*/
|
||||
@Override
|
||||
public void set(double x0, double y0, double z0, double x1, double y1, double z1) {
|
||||
super.set(x0, y0, z0, x1, y1, z1);
|
||||
collides = false;
|
||||
lastBx = blockX;
|
||||
lastBy = blockY;
|
||||
lastBz = blockZ;
|
||||
targetBx = Location.locToBlock(x1);
|
||||
targetBy = Location.locToBlock(y1);
|
||||
targetBz = Location.locToBlock(z1);
|
||||
}
|
||||
|
||||
public boolean collides(){
|
||||
return collides;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove reference to BlockCache.
|
||||
*/
|
||||
public void cleanup(){
|
||||
if (blockCache != null){
|
||||
blockCache = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplistic collision check (can interact through this block).
|
||||
* @param blockX
|
||||
* @param blockY
|
||||
* @param blockZ
|
||||
* @return
|
||||
*/
|
||||
private final boolean doesCollide(int blockX, int blockY, int blockZ){
|
||||
final int id = blockCache.getTypeId(blockX, blockY, blockZ);
|
||||
final long flags = BlockProperties.getBlockFlags(id);
|
||||
if ((flags & BlockProperties.F_SOLID) == 0){
|
||||
// Ignore non solid blocks anyway.
|
||||
return false;
|
||||
}
|
||||
if ((flags & (BlockProperties.F_LIQUID | BlockProperties.F_IGN_PASSABLE | BlockProperties.F_STAIRS | BlockProperties.F_VARIABLE)) != 0){
|
||||
// Special cases.
|
||||
// TODO: F_VARIABLE: Bounding boxes are roughly right ?
|
||||
return false;
|
||||
}
|
||||
if (!blockCache.isFullBounds(blockX, blockY, blockZ)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the block may be interacted through by use of some workaround.
|
||||
* @param blockX
|
||||
* @param blockY
|
||||
* @param blockZ
|
||||
* @return
|
||||
*/
|
||||
private final boolean allowsWorkaround(final int blockX, final int blockY, final int blockZ) {
|
||||
// TODO: This allows some bypasses for "strange" setups.
|
||||
for (int i = 0; i < 6; i++){
|
||||
final int[] dir = incr[i];
|
||||
final int rX = lastBx + dir[0];
|
||||
if (Math.abs(blockX - rX) > 1) continue;
|
||||
final int rY = lastBy + dir[1];
|
||||
if (Math.abs(blockY - rY) > 1) continue;
|
||||
final int rZ = lastBz + dir[2];
|
||||
if (Math.abs(blockZ - rZ) > 1) continue;
|
||||
if (!doesCollide(rX, rY, rZ)){
|
||||
// NOTE: Don't check "rX == targetBx && rZ == targetBz && rY == targetBy".
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean step(int blockX, int blockY, int blockZ, double oX, double oY, double oZ, double dT) {
|
||||
// TODO: Make an optional, more precise check (like passable) ?
|
||||
if (blockX == targetBx && blockZ == targetBz && blockY == targetBy || !doesCollide(blockX, blockY, blockZ)){
|
||||
lastBx = blockX;
|
||||
lastBy = blockY;
|
||||
lastBz = blockZ;
|
||||
return true;
|
||||
}
|
||||
if (strict || blockX == lastBx && blockZ == lastBz && blockY == lastBy){
|
||||
collides = true;
|
||||
return false;
|
||||
}
|
||||
// Check workarounds...
|
||||
if (allowsWorkaround(blockX, blockY, blockZ)){
|
||||
lastBx = blockX;
|
||||
lastBy = blockY;
|
||||
lastBz = blockZ;
|
||||
return true;
|
||||
}
|
||||
// No workaround found.
|
||||
collides = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user