[BLEEDING] Fixes for passable/rt preventing moving out of blocks.

Passable/ray-tracing might disallow players moving out of blocks which
they are stuck in on some occasions.
In order to allow moving out of a block, ray tracing is repeated
with the first block ignored for some cases.
This commit is contained in:
asofold 2013-07-12 19:25:19 +02:00
parent ee0ca14cef
commit d7ca742c57
4 changed files with 100 additions and 14 deletions

View File

@ -26,19 +26,36 @@ public class Passable extends Check {
{
// Simple check (only from, to, player.getLocation).
// TODO: account for actual bounding box.
// TODO: Future: Account for the players bounding box? [test very-strict setting for at least the end points...]
String tags = "";
// Block distances (sum, max) for from-to (not for loc!).
final int manhattan = from.manhattan(to);
boolean toPassable = to.isPassable();
// TODO: Config settings, extra flag for further processing.
if (toPassable && cc.passableRayTracingCheck && (!cc.passableRayTracingVclipOnly || from.getY() > to.getY()) && (!cc.passableRayTracingBlockChangeOnly || from.getBlockX() != to.getBlockX() || from.getBlockY() != to.getBlockY() || from.getBlockZ() != to.getBlockZ())){
// General condition check for using ray-tracing.
if (toPassable && cc.passableRayTracingCheck && (!cc.passableRayTracingVclipOnly || from.getY() > to.getY()) && (!cc.passableRayTracingBlockChangeOnly || manhattan > 0)){
rayTracing.set(from, to);
rayTracing.loop();
if (rayTracing.collides() || rayTracing.getStepsDone() >= rayTracing.getMaxSteps()){
toPassable = false;
tags = "raytracing";
final int maxBlockDist = manhattan <= 1 ? manhattan : from.maxBlockDist(to);
if (maxBlockDist <= 1 && rayTracing.getStepsDone() == 1 && !from.isPassable()){
// Redo ray-tracing for moving out of blocks.
rayTracing.set(from, to);
rayTracing.setIgnorefirst();
rayTracing.loop();
if (rayTracing.collides() || rayTracing.getStepsDone() >= rayTracing.getMaxSteps()){
toPassable = false;
tags = "raytracing_2x_";
}
else if (cc.debug){
System.out.println(player.getName() + " passable: allow moving out of a block.");
}
}
else{
toPassable = false;
tags = "raytracing_";
}
}
// TODO: If accuracy is set, also check the head position (or bounding box right away).
// TODO: Future: If accuracy is demanded, also check the head position (or bounding box right away).
rayTracing.cleanup();
}
@ -53,7 +70,6 @@ public class Passable extends Check {
// Check the players location if different from others.
// (It provides a better set-back for some exploits.)
// Location loc = player.getLocation();
final int lbX = loc.getBlockX();
final int lbY = loc.getBlockY();
final int lbZ = loc.getBlockZ();
@ -62,25 +78,27 @@ public class Passable extends Check {
if (from.isPassable()){
// From should be the set-back.
loc = null;
tags = "into";
tags += "into";
} else if (BlockProperties.isPassable(from.getBlockCache(), loc.getX(), loc.getY(), loc.getZ(), from.getTypeId(lbX, lbY, lbZ))){
tags += "into_shift";
}
// } else if (BlockProperties.isPassableExact(from.getBlockCache(), loc.getX(), loc.getY(), loc.getZ(), from.getTypeId(lbX, lbY, lbZ))){
// (Mind that this can be the case on the same block theoretically.)
// Keep loc as set-back.
}
// }
else if (!from.isSameBlock(lbX, lbY, lbZ)){
// Otherwise keep loc as set-back.
tags = "cross_shift";
tags += "cross_shift";
}
else if (to.isBlockAbove(from) && BlockProperties.isPassable(from.getBlockCache(), from.getX(), from.getY() + player.getEyeHeight(), from.getZ(), from.getTypeId(from.getBlockX(), Location.locToBlock(from.getY() + player.getEyeHeight()), from.getBlockZ()))){
else if (manhattan == 1 && to.isBlockAbove(from) && BlockProperties.isPassable(from.getBlockCache(), from.getX(), from.getY() + player.getEyeHeight(), from.getZ(), from.getTypeId(from.getBlockX(), Location.locToBlock(from.getY() + player.getEyeHeight()), from.getBlockZ()))){
// else if (to.isBlockAbove(from) && BlockProperties.isPassableExact(from.getBlockCache(), from.getX(), from.getY() + player.getEyeHeight(), from.getZ(), from.getTypeId(from.getBlockX(), Location.locToBlock(from.getY() + player.getEyeHeight()), from.getBlockZ()))){
// Allow the move up if the head is free.
return null;
}
else if (!from.isSameBlock(to)){
else if (manhattan > 0){
// Otherwise keep from as set-back.
loc = null;
tags = "cross";
tags += "cross";
}
else{
// All blocks are the same, allow the move.

View File

@ -5,6 +5,8 @@ public class PassableRayTracing extends RayTracing{
protected BlockCache blockCache = null;
protected boolean collides = false;
protected boolean ignorefirst = false;
public BlockCache getBlockCache() {
return blockCache;
@ -31,12 +33,27 @@ public class PassableRayTracing extends RayTracing{
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;
ignorefirst = false;
}
public boolean collides(){
return collides;
}
/**
* Ignore the first block. Must be called after set, because set will override this with false.
*/
public void setIgnorefirst(){
this.ignorefirst = true;
}
/**
* Test if the first block is set to be ignored (resets to false with set).
* @return
*/
public boolean getIgnoreFirst(){
return ignorefirst;
}
/**
* Remove reference to BlockCache.
@ -50,6 +67,9 @@ public class PassableRayTracing extends RayTracing{
@Override
protected boolean step(final int blockX, final int blockY, final int blockZ, final double oX, final double oY, final double oZ, final double dT) {
// Just delegate.
if (step == 1 && ignorefirst){
return true;
}
if (BlockProperties.isPassableRay(blockCache, blockX, blockY, blockZ, oX, oY, oZ, dX, dY, dZ, dT)){
return true;
}

View File

@ -268,6 +268,26 @@ public class PlayerLocation {
public boolean isSamePos(final Location loc) {
return x == loc.getX() && z == loc.getZ() && y == loc.getY();
}
/**
* Manhattan distance, see Trigutil.
* @param other
* @return
*/
public int manhattan(final PlayerLocation other){
// TODO: Consider using direct field access from other methods as well.
return TrigUtil.manhattan(this.blockX, this.blockY, this.blockZ, other.blockX, other.blockY, other.blockZ);
}
/**
* Maximum block distance comparing dx, dy, dz.
* @param other
* @return
*/
public int maxBlockDist(final PlayerLocation other){
// TODO: Consider using direct field access from other methods as well.
return TrigUtil.maxDistance(this.blockX, this.blockY, this.blockZ, other.blockX, other.blockY, other.blockZ);
}
/**
* Checks if the player is above stairs.

View File

@ -331,5 +331,33 @@ public class TrigUtil {
else if (yawDiff > 180f) yawDiff -= 360f;
return yawDiff;
}
/**
* Manhattan distance (steps along the sides of an orthogonal grid).
* @param x1
* @param y1
* @param z1
* @param x2
* @param y2
* @param z2
* @return
*/
public static int manhattan(final int x1, final int y1, final int z1, final int x2, final int y2, final int z2){
return Math.abs(x1 - x2) + Math.abs(y1 - y2) + Math.abs(z1 - z2);
}
/**
* Maximum distance comparing dx, dy, dz.
* @param x1
* @param y1
* @param z1
* @param x2
* @param y2
* @param z2
* @return
*/
public static int maxDistance(final int x1, final int y1, final int z1, final int x2, final int y2, final int z2){
return Math.max(Math.max(Math.abs(x1 - x2), Math.abs(y1 - y2)), Math.abs(z1 - z2));
}
}