Decouple legacy code.

Easier to make configurable, easier to remove.
This commit is contained in:
asofold 2016-06-11 20:21:24 +02:00
parent fec027d41d
commit da8b056a69

View File

@ -40,6 +40,7 @@ public class Passable extends Check {
// TODO: Configuration.
// TODO: Test cases.
private static boolean rt_legacy = false;
// TODO: Should keep an eye on passable vs. on-ground, when checking with reduced margins.
// TODO: rt_xzFactor = 1.0; // Problems: Doors, fences.
private static double rt_xzFactor = 0.98;
// TODO: Test bumping head into things.
@ -57,126 +58,71 @@ public class Passable extends Check {
}
// TODO: Store both and select on check (with config then).
private final ICollidePassable rayTracing = rt_legacy ? new PassableRayTracing() : new PassableAxisTracing();
private final ICollidePassable rayTracingLegacy = new PassableRayTracing();
private final ICollidePassable rayTracingActual = new PassableAxisTracing();
public Passable() {
super(CheckType.MOVING_PASSABLE);
rayTracing.setMaxSteps(60); // TODO: Configurable ?
// TODO: Configurable maxSteps?
rayTracingLegacy.setMaxSteps(60);
rayTracingActual.setMaxSteps(60);
}
public Location check(final Player player, final PlayerLocation from, final PlayerLocation to, final MovingData data, final MovingConfig cc)
{
// TODO: WAT: if (!from.isSameCoords(loc)) {...check passable for loc -> from !?... + sf etc too?}
public Location check(final Player player, final PlayerLocation from, final PlayerLocation to,
final MovingData data, final MovingConfig cc) {
if (rt_legacy) {
return checkLegacy(player, from, to, data, cc);
}
else {
return checkActual(player, from, to, data, cc);
}
}
private Location checkActual(final Player player, final PlayerLocation from, final PlayerLocation to,
final MovingData data, final MovingConfig cc) {
// TODO: Distinguish feet vs. box.
String tags = "";
// Block distances (sum, max) for from-to (not for loc!).
final int manhattan = from.manhattan(to);
if (rt_legacy) {
// Skip moves inside of ignored blocks right away [works as long as we only check between foot-locations].
if (manhattan <= 1 && BlockProperties.isPassable(from.getTypeId())) {
// TODO: Monitor: BlockProperties.isPassable checks slightly different than before.
if (manhattan == 0){
return null;
} else {
// manhattan == 1
if (BlockProperties.isPassable(to.getTypeId())) {
return null;
}
}
}
}
boolean toPassable = to.isPassable();
// General condition check for using ray-tracing.
if ((!rt_legacy || toPassable) && cc.passableRayTracingCheck
&& (!cc.passableRayTracingBlockChangeOnly || manhattan > 0)) {
final String newTag;
if (rt_legacy) {
newTag = checkRayTracingLegacy(player, from, to, manhattan, data, cc);
if (newTag != null) {
toPassable = false;
tags = newTag;
}
}
else {
newTag = checkRayTracing(player, from, to, manhattan, data, cc);
if (newTag != null) {
// Direct return.
return potentialViolation(player, from, to, manhattan, tags, data, cc);
}
if (cc.passableRayTracingCheck && (!cc.passableRayTracingBlockChangeOnly || manhattan > 0)) {
final String newTag = checkRayTracing(player, from, to, manhattan, data, cc);
if (newTag != null) {
// Direct return.
return potentialViolation(player, from, to, manhattan, newTag, data, cc);
}
}
// TODO: Checking order: If loc is not the same as from, a quick return here might not be wanted.
if (toPassable) {
if (to.isPassable()) {
// Quick return.
// (Might consider if vl>=1: only decrease if from and loc are passable too, though micro...)
data.passableVL *= 0.99;
return null;
} else {
return potentialViolationLegacy(player, from, to, manhattan, tags, data, cc);
return potentialViolationLegacy(player, from, to, manhattan, "", data, cc);
}
}
private String checkRayTracing(final Player player, final PlayerLocation from, final PlayerLocation to,
final int manhattan, final MovingData data, final MovingConfig cc) {
String tags = null;
setNormalMargins(rayTracing, from);
rayTracing.set(from, to);
rayTracing.setIgnoreInitiallyColliding(true);
setNormalMargins(rayTracingActual, from);
rayTracingActual.set(from, to);
rayTracingActual.setIgnoreInitiallyColliding(true);
//rayTracing.setCutOppositeDirectionMargin(true);
rayTracing.loop();
rayTracing.setIgnoreInitiallyColliding(false);
rayTracingActual.loop();
rayTracingActual.setIgnoreInitiallyColliding(false);
//rayTracing.setCutOppositeDirectionMargin(false);
if (rayTracing.collides()) {
if (rayTracingActual.collides()) {
tags = "raytracing_collide_";
}
else if (rayTracing.getStepsDone() >= rayTracing.getMaxSteps()) {
else if (rayTracingActual.getStepsDone() >= rayTracingActual.getMaxSteps()) {
tags = "raytracing_maxsteps_";
}
if (data.debug) {
debugExtraCollisionDetails(player, rayTracing, "std");
debugExtraCollisionDetails(player, rayTracingActual, "std");
}
rayTracing.cleanup();
return tags;
}
private String checkRayTracingLegacy(final Player player, final PlayerLocation from, final PlayerLocation to,
final int manhattan, final MovingData data, final MovingConfig cc) {
setNormalMargins(rayTracing, from);
rayTracing.set(from, to);
rayTracing.loop();
String tags = null;
if (rayTracing.collides() || rayTracing.getStepsDone() >= rayTracing.getMaxSteps()) {
if (data.debug) {
debugExtraCollisionDetails(player, rayTracing, "legacy");
}
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.
if (collidesIgnoreFirst(from, to)) {
tags = "raytracing_2x_";
if (data.debug) {
debugExtraCollisionDetails(player, rayTracing, "ingoreFirst");
}
}
else if (data.debug) {
debug(player, "Allow moving out of a block.");
}
}
else{
if (!allowsSplitMove(from, to, manhattan, data)) {
tags = "raytracing_";
}
}
}
// TODO: Future: If accuracy is demanded, also check the head position (or bounding box right away).
rayTracing.cleanup();
rayTracingActual.cleanup();
return tags;
}
@ -210,6 +156,146 @@ public class Passable extends Check {
return actualViolation(player, from, to, tags, data, cc);
}
private Location actualViolation(final Player player, final PlayerLocation from, final PlayerLocation to,
final String tags, final MovingData data, final MovingConfig cc) {
Location setBackLoc = null; // Alternative to from.getLocation().
// Prefer the set-back location from the data.
if (data.hasSetBack()) {
setBackLoc = data.getSetBack(to);;
if (data.debug) {
debug(player, "Using set-back location for passable.");
}
}
// Return the reset position.
data.passableVL += 1d;
final ViolationData vd = new ViolationData(this, player, data.passableVL, 1, cc.passableActions);
if (data.debug || vd.needsParameters()) {
vd.setParameter(ParameterName.LOCATION_FROM, String.format(Locale.US, "%.2f, %.2f, %.2f", from.getX(), from.getY(), from.getZ()));
vd.setParameter(ParameterName.LOCATION_TO, String.format(Locale.US, "%.2f, %.2f, %.2f", to.getX(), to.getY(), to.getZ()));
vd.setParameter(ParameterName.DISTANCE, String.format(Locale.US, "%.2f", TrigUtil.distance(from, to)));
// TODO: Consider adding from.getTypeId() too, if blocks differ and non-air.
vd.setParameter(ParameterName.BLOCK_ID, "" + to.getTypeId());
if (!tags.isEmpty()) {
vd.setParameter(ParameterName.TAGS, tags);
}
}
if (executeActions(vd).willCancel()) {
// TODO: Consider another set back position for this, also keeping track of players moving around in blocks.
final Location newTo;
if (setBackLoc != null) {
// Ensure the given location is cloned.
newTo = LocUtil.clone(setBackLoc);
} else {
newTo = from.getLocation();
if (data.debug) {
debug(player, "Using from location for passable.");
}
}
newTo.setYaw(to.getYaw());
newTo.setPitch(to.getPitch());
return newTo;
}
else{
// No cancel action set.
return null;
}
}
/**
* Debug only if colliding.
*
* @param player
* @param rayTracing
* @param tag
*/
private void debugExtraCollisionDetails(Player player, ICollidePassable rayTracing, String tag) {
if (rayTracing.collides()) {
debug(player, "Raytracing collision (" + tag + "): " + rayTracing.getCollidingAxis());
}
else if (rayTracing.getStepsDone() >= rayTracing.getMaxSteps()) {
debug(player, "Raytracing max steps exceeded (" + tag + "): "+ rayTracing.getCollidingAxis());
}
}
private Location checkLegacy(final Player player, final PlayerLocation from, final PlayerLocation to,
final MovingData data, final MovingConfig cc) {
// TODO: Distinguish feet vs. box.
String tags = "";
// Block distances (sum, max) for from-to (not for loc!).
final int manhattan = from.manhattan(to);
// Skip moves inside of ignored blocks right away [works as long as we only check between foot-locations].
if (manhattan <= 1 && BlockProperties.isPassable(from.getTypeId())) {
// TODO: Monitor: BlockProperties.isPassable checks slightly different than before.
if (manhattan == 0){
return null;
} else {
// manhattan == 1
if (BlockProperties.isPassable(to.getTypeId())) {
return null;
}
}
}
boolean toPassable = to.isPassable();
// General condition check for using ray-tracing.
if (toPassable && cc.passableRayTracingCheck
&& (!cc.passableRayTracingBlockChangeOnly || manhattan > 0)) {
final String newTag = checkRayTracingLegacy(player, from, to, manhattan, data, cc);
if (newTag != null) {
toPassable = false;
tags = newTag;
}
}
// TODO: Checking order: If loc is not the same as from, a quick return here might not be wanted.
if (toPassable) {
// Quick return.
// (Might consider if vl>=1: only decrease if from and loc are passable too, though micro...)
data.passableVL *= 0.99;
return null;
} else {
return potentialViolationLegacy(player, from, to, manhattan, tags, data, cc);
}
}
private String checkRayTracingLegacy(final Player player, final PlayerLocation from, final PlayerLocation to,
final int manhattan, final MovingData data, final MovingConfig cc) {
setNormalMargins(rayTracingLegacy, from);
rayTracingLegacy.set(from, to);
rayTracingLegacy.loop();
String tags = null;
if (rayTracingLegacy.collides() || rayTracingLegacy.getStepsDone() >= rayTracingLegacy.getMaxSteps()) {
if (data.debug) {
debugExtraCollisionDetails(player, rayTracingLegacy, "legacy");
}
final int maxBlockDist = manhattan <= 1 ? manhattan : from.maxBlockDist(to);
if (maxBlockDist <= 1 && rayTracingLegacy.getStepsDone() == 1 && !from.isPassable()) {
// Redo ray-tracing for moving out of blocks.
if (collidesIgnoreFirst(from, to)) {
tags = "raytracing_2x_";
if (data.debug) {
debugExtraCollisionDetails(player, rayTracingLegacy, "ingoreFirst");
}
}
else if (data.debug) {
debug(player, "Allow moving out of a block.");
}
}
else{
if (!allowsSplitMove(from, to, manhattan, data)) {
tags = "raytracing_";
}
}
}
// TODO: Future: If accuracy is demanded, also check the head position (or bounding box right away).
rayTracingLegacy.cleanup();
return tags;
}
/**
* Legacy skipping conditions, before triggering an actual violation.
*
@ -266,53 +352,6 @@ public class Passable extends Check {
return actualViolation(player, from, to, tags, data, cc);
}
private Location actualViolation(final Player player, final PlayerLocation from, final PlayerLocation to,
final String tags, final MovingData data, final MovingConfig cc) {
Location setBackLoc = null; // Alternative to from.getLocation().
// Prefer the set-back location from the data.
if (data.hasSetBack()) {
setBackLoc = data.getSetBack(to);;
if (data.debug) {
debug(player, "Using set-back location for passable.");
}
}
// Return the reset position.
data.passableVL += 1d;
final ViolationData vd = new ViolationData(this, player, data.passableVL, 1, cc.passableActions);
if (data.debug || vd.needsParameters()) {
vd.setParameter(ParameterName.LOCATION_FROM, String.format(Locale.US, "%.2f, %.2f, %.2f", from.getX(), from.getY(), from.getZ()));
vd.setParameter(ParameterName.LOCATION_TO, String.format(Locale.US, "%.2f, %.2f, %.2f", to.getX(), to.getY(), to.getZ()));
vd.setParameter(ParameterName.DISTANCE, String.format(Locale.US, "%.2f", TrigUtil.distance(from, to)));
// TODO: Consider adding from.getTypeId() too, if blocks differ and non-air.
vd.setParameter(ParameterName.BLOCK_ID, "" + to.getTypeId());
if (!tags.isEmpty()) {
vd.setParameter(ParameterName.TAGS, tags);
}
}
if (executeActions(vd).willCancel()) {
// TODO: Consider another set back position for this, also keeping track of players moving around in blocks.
final Location newTo;
if (setBackLoc != null) {
// Ensure the given location is cloned.
newTo = LocUtil.clone(setBackLoc);
} else {
newTo = from.getLocation();
if (data.debug) {
debug(player, "Using from location for passable.");
}
}
newTo.setYaw(to.getYaw());
newTo.setPitch(to.getPitch());
return newTo;
}
else{
// No cancel action set.
return null;
}
}
/**
* Test collision with ignoring the first block.
* @param from
@ -320,15 +359,13 @@ public class Passable extends Check {
* @return
*/
private boolean collidesIgnoreFirst(PlayerLocation from, PlayerLocation to) {
// TODO: Set (and reset?) margins?
// TODO: rayTracing.setIgnoreInitiallyColliding(true);
rayTracing.set(from, to);
rayTracing.setIgnoreInitiallyColliding(true);
rayTracing.setCutOppositeDirectionMargin(true);
rayTracing.loop();
rayTracing.setIgnoreInitiallyColliding(false);
rayTracing.setCutOppositeDirectionMargin(false);
return rayTracing.collides() || rayTracing.getStepsDone() >= rayTracing.getMaxSteps();
rayTracingLegacy.set(from, to);
rayTracingLegacy.setIgnoreInitiallyColliding(true);
rayTracingLegacy.setCutOppositeDirectionMargin(true);
rayTracingLegacy.loop();
rayTracingLegacy.setIgnoreInitiallyColliding(false);
rayTracingLegacy.setCutOppositeDirectionMargin(false);
return rayTracingLegacy.collides() || rayTracingLegacy.getStepsDone() >= rayTracingLegacy.getMaxSteps();
}
/**
@ -339,17 +376,17 @@ public class Passable extends Check {
* @return
*/
private boolean allowsSplitMove(final PlayerLocation from, final PlayerLocation to, final int manhattan, final MovingData data) {
if (!rayTracing.mightNeedSplitAxisHandling()) {
if (!rayTracingLegacy.mightNeedSplitAxisHandling()) {
return false;
}
// Always check y first.
rayTracing.set(from.getX(), from.getY(), from.getZ(), from.getX(), to.getY(), from.getZ());
rayTracing.loop();
if (!rayTracing.collides() && rayTracing.getStepsDone() < rayTracing.getMaxSteps()) {
rayTracingLegacy.set(from.getX(), from.getY(), from.getZ(), from.getX(), to.getY(), from.getZ());
rayTracingLegacy.loop();
if (!rayTracingLegacy.collides() && rayTracingLegacy.getStepsDone() < rayTracingLegacy.getMaxSteps()) {
// horizontal second.
rayTracing.set(from.getX(), to.getY(), from.getZ(), to.getX(), to.getY(), to.getZ());
rayTracing.loop();
if (!rayTracing.collides() && rayTracing.getStepsDone() < rayTracing.getMaxSteps()) {
rayTracingLegacy.set(from.getX(), to.getY(), from.getZ(), to.getX(), to.getY(), to.getZ());
rayTracingLegacy.loop();
if (!rayTracingLegacy.collides() && rayTracingLegacy.getStepsDone() < rayTracingLegacy.getMaxSteps()) {
return true;
}
}
@ -361,13 +398,13 @@ public class Passable extends Check {
// if (data.debug) {
// DebugUtil.debug(from.getPlayer().getName() + " passable - Test horizontal move first.");
// }
// rayTracing.set(from.getX(), from.getY(), from.getZ(), to.getX(), from.getY(), to.getZ());
// rayTracing.loop();
// if (!rayTracing.collides() && rayTracing.getStepsDone() < rayTracing.getMaxSteps()) {
// rayTracingLegacy.set(from.getX(), from.getY(), from.getZ(), to.getX(), from.getY(), to.getZ());
// rayTracingLegacy.loop();
// if (!rayTracingLegacy.collides() && rayTracingLegacy.getStepsDone() < rayTracingLegacy.getMaxSteps()) {
// // y second.
// rayTracing.set(to.getX(), from.getY(), to.getZ(), to.getX(), to.getY(), to.getZ());
// rayTracing.loop();
// if (!rayTracing.collides() && rayTracing.getStepsDone() < rayTracing.getMaxSteps()) {
// rayTracingLegacy.set(to.getX(), from.getY(), to.getZ(), to.getX(), to.getY(), to.getZ());
// rayTracingLegacy.loop();
// if (!rayTracingLegacy.collides() && rayTracingLegacy.getStepsDone() < rayTracingLegacy.getMaxSteps()) {
// return true;
// }
// }
@ -378,20 +415,4 @@ public class Passable extends Check {
return false;
}
/**
* Debug only if colliding.
*
* @param player
* @param rayTracing
* @param tag
*/
private void debugExtraCollisionDetails(Player player, ICollidePassable rayTracing, String tag) {
if (rayTracing.collides()) {
debug(player, "Raytracing collision (" + tag + "): " + rayTracing.getCollidingAxis());
}
else if (rayTracing.getStepsDone() >= rayTracing.getMaxSteps()) {
debug(player, "Raytracing max steps exceeded (" + tag + "): "+ rayTracing.getCollidingAxis());
}
}
}