mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-09-27 14:13:11 +02:00
Decouple legacy code.
Easier to make configurable, easier to remove.
This commit is contained in:
parent
fec027d41d
commit
da8b056a69
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user