[BLEEDING/INCOMPLETE] Attempt to fix issues with blockinteract.visible.

Done: Check if the end point of ray-tracing is passable.

Problem: Might lead to problems with non-full blocks squeezed between
full blocks.

Missing: Implement corrected outer bounds getting for use with this.
This commit is contained in:
asofold 2013-05-26 21:10:47 +02:00
parent 3b22ca2e6a
commit 430915e377
4 changed files with 106 additions and 10 deletions

View File

@ -11,10 +11,16 @@ import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.compat.MCAccess;
import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.utilities.BlockCache;
import fr.neatmonster.nocheatplus.utilities.BlockProperties;
import fr.neatmonster.nocheatplus.utilities.InteractRayTracing;
public class Visible extends Check {
/**
* Factor for the block-face mod.
*/
private static final double fModFull = 0.6;
private BlockCache blockCache;
private final InteractRayTracing rayTracing = new InteractRayTracing(false);
@ -34,6 +40,27 @@ public class Visible extends Check {
// Renew the BlockCache instance.
blockCache = mcAccess.getBlockCache(null);
}
private static final double getEnd(final double[] bounds, final int index, final int mod){
if (bounds == null){
return 0.5 + fModFull * mod;
}
if (mod == 0){
// TODO: Middle or middle of block ?
return (bounds[index] + bounds[index + 3]) / 2.0;
}
else if (mod == 1){
// TODO: Slightly outside or dependent on exact position (inside, exact edge, outside)?
return bounds[index + 3];
}
else if (mod == -1){
// TODO: Slightly outside or dependent on exact position (inside, exact edge, outside)?
return bounds[index];
}
else{
throw new IllegalArgumentException("BlockFace.getModX|Y|Z must be 0, 1 or -1.");
}
}
public boolean check(final Player player, final Location loc, final Block block, final BlockFace face, final Action action, final BlockInteractData data, final BlockInteractConfig cc) {
@ -46,12 +73,30 @@ public class Visible extends Check {
}
else{
blockCache.setAccess(loc.getWorld());
rayTracing.setBlockCache(blockCache);
rayTracing.set(loc.getX(), loc.getY() + eyeHeight, loc.getZ(), 0.5 + block.getX() + 0.6 * face.getModX(), 0.5 + block.getY() + 0.6 * face.getModY(), 0.5 + block.getZ() + 0.6 * face.getModZ());
rayTracing.loop();
collides = rayTracing.collides() || rayTracing.getStepsDone() >= rayTracing.getMaxSteps();
// Guess some end-coordinates.
@SuppressWarnings("deprecation")
final double[] bounds = BlockProperties.getCorrectedBounds(blockCache, block.getX(), block.getY(), block.getZ());
final int modX = face.getModX();
final int modY = face.getModY();
final int modZ = face.getModZ();
final double eX = (double) block.getX() + getEnd(bounds, 0, modX);
final double eY = (double) block.getY() + getEnd(bounds, 1, modY);
final double eZ = (double) block.getZ() + getEnd(bounds, 2, modZ);
if (BlockProperties.isPassable(blockCache, eX, eY, eZ, blockCache.getTypeId(eX, eY, eZ))){
// Perform ray-tracing.
rayTracing.setBlockCache(blockCache);
rayTracing.set(loc.getX(), loc.getY() + eyeHeight, loc.getZ(), eX, eY, eZ);
rayTracing.loop();
collides = rayTracing.collides() || rayTracing.getStepsDone() >= rayTracing.getMaxSteps();
rayTracing.cleanup();
}
else{
// Not passable = not possible.
collides = true;
}
blockCache.cleanup();
rayTracing.cleanup();
}
if (cc.debug && player.hasPermission(Permissions.ADMINISTRATION_DEBUG)){

View File

@ -2,6 +2,7 @@ package fr.neatmonster.nocheatplus.utilities;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import fr.neatmonster.nocheatplus.utilities.ds.CoordMap;
@ -127,6 +128,26 @@ public abstract class BlockCache {
boundsMap.clear();
}
/**
* (convenience method, uses cache).
* @param eX
* @param eY
* @param eZ
* @return
*/
public int getTypeId(double x, double y, double z) {
return getTypeId(Location.locToBlock(x), Location.locToBlock(y), Location.locToBlock(z));
}
/**
* (convenience method, uses cache).
* @param block
* @return
*/
public int getTypeId(final Block block) {
return getTypeId(block.getX(), block.getY(), block.getZ());
}
/**
* Get type id with cache access.
* @param x

View File

@ -1899,7 +1899,7 @@ public class BlockProperties {
* @return
*/
public static final boolean collidesBlock(final BlockCache access, final double minX, double minY, final double minZ, final double maxX, final double maxY, final double maxZ, final int x, final int y, final int z, final int id, final double[] bounds, final long flags){
final double bminX, bminZ, bminY;
final double bminX, bminZ, bminY;
final double bmaxX, bmaxY, bmaxZ;
// TODO: Consider a quick shortcut checks flags == F_NORMAL_GROUND
if ((flags & F_STAIRS) != 0){ // TODO: make this a full block flag ?
@ -1969,9 +1969,39 @@ public class BlockProperties {
else if (minY >= bmaxY + y || maxY < bminY + y) return false;
else if (minZ >= bmaxZ + z || maxZ < bminZ + z) return false;
else return true;
}
}
/**
* Attempt to return the exact outside bounds, corrected by flags and other.
* @deprecated Not yet for real (only used in certain checks/contexts).
* @param access
* @param x
* @param y
* @param z
* @return
*/
public static double[] getCorrectedBounds(final BlockCache access, final int x, final int y, final int z) {
return getCorrectedBounds(x, y, z, access.getTypeId(x, y, z), access.getBounds(x, y, z));
}
/**
* Attempt to return the exact outside bounds, corrected by flags and other.
* @deprecated Not yet for real (only used in certain checks/contexts).
* @param x
* @param y
* @param z
* @param typeId
* @param bounds
* @return
*/
public static double[] getCorrectedBounds(final int x, final int y, final int z, final int id, final double[] bounds) {
if (bounds == null) return null;
//final long flags = blockFlags[id];
// TODO: IMPLEMENT !
return null;
}
/**
* Similar to collides(... , F_GROUND), but also checks the block above (against spider).<br>
* NOTE: This does not return true if stuck, to check for that use collidesBlock for the players location.
* @param access
@ -1985,7 +2015,7 @@ public class BlockProperties {
*/
public static final boolean isOnGround(final BlockCache access, final double minX, double minY, final double minZ, final double maxX, final double maxY, final double maxZ){
return isOnGround(access, minX, minY, minZ, maxX, maxY, maxZ, 0L);
}
}
/**
* Similar to collides(... , F_GROUND), but also checks the block above (against spider).<br>

View File

@ -3,7 +3,7 @@ package fr.neatmonster.nocheatplus.utilities;
import org.bukkit.Location;
/**
* Rough ray-tracing for interaction with something.
* Rough ray-tracing for interaction with something. This does not do any smart end-point guessing.
* @author mc_dev
*
*/