mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-11-03 01:00:20 +01:00
Differentiate between LIQUID and SOLID blocks when determining if a
player is on ground or in the air.
This commit is contained in:
parent
eac9f4d10a
commit
81b4d7160e
@ -99,7 +99,7 @@ public class MovingCheck extends Check {
|
||||
// actually was - choose appropriately
|
||||
Location from = data.teleportTo != null ? data.teleportTo : event.getFrom();
|
||||
data.teleportTo = null;
|
||||
|
||||
|
||||
if(shouldBeIgnored(player, data, from, to)) {
|
||||
statisticElapsedTimeNano += System.nanoTime() - startTime;
|
||||
statisticTotalEvents++;
|
||||
@ -162,17 +162,18 @@ public class MovingCheck extends Check {
|
||||
|
||||
// The location we'd use as a new setback if there are no violations
|
||||
Location newSetBack = null;
|
||||
|
||||
final boolean onGroundFrom = playerIsOnGround(from, 0.0D);
|
||||
|
||||
final int onGroundFrom = playerIsOnGround(from, 0.0D);
|
||||
|
||||
double limit = calculateVerticalLimit(data, onGroundFrom);
|
||||
|
||||
// Handle 4 distinct cases: Walk, Jump, Land, Fly
|
||||
|
||||
// Walk or start Jump
|
||||
if(onGroundFrom)
|
||||
if(onGroundFrom != MovingData.NONSOLID)
|
||||
{
|
||||
limit += jumpHeight;
|
||||
|
||||
final double distance = to.getY() - from.getY();
|
||||
|
||||
violationLevelVertical = limitCheck(distance - limit);
|
||||
@ -189,7 +190,7 @@ public class MovingCheck extends Check {
|
||||
else
|
||||
{
|
||||
final Location l;
|
||||
|
||||
|
||||
final boolean canFly = allowFlying || plugin.hasPermission(player, PermissionData.PERMISSION_FLYING);
|
||||
|
||||
if(data.setBackPoint == null || canFly)
|
||||
@ -201,9 +202,9 @@ public class MovingCheck extends Check {
|
||||
limit += jumpHeight - (data.jumpPhase-jumpingLimit) * 0.2D;
|
||||
else limit += jumpHeight;
|
||||
|
||||
final boolean onGroundTo = playerIsOnGround(to, 0.5D);
|
||||
final int onGroundTo = playerIsOnGround(to, 0.5D);
|
||||
|
||||
if(onGroundTo) limit += stepHeight;
|
||||
if(onGroundTo != MovingData.NONSOLID) limit += stepHeight;
|
||||
|
||||
final double distance = to.getY() - l.getY();
|
||||
|
||||
@ -211,7 +212,7 @@ public class MovingCheck extends Check {
|
||||
violationLevelVertical = limitCheck(distance - limit);
|
||||
|
||||
if(violationLevelVertical < 0) {
|
||||
if(onGroundTo) { // Land
|
||||
if(onGroundTo != MovingData.NONSOLID) { // Land
|
||||
data.jumpPhase = 0; // He is on ground now, so reset the jump
|
||||
newSetBack = to;
|
||||
}
|
||||
@ -253,7 +254,7 @@ public class MovingCheck extends Check {
|
||||
statisticTotalEvents++;
|
||||
}
|
||||
|
||||
private double calculateVerticalLimit(final MovingData data, final boolean onGroundFrom) {
|
||||
private double calculateVerticalLimit(final MovingData data, final int onGroundFrom) {
|
||||
|
||||
// A halfway lag-resistant method of allowing vertical acceleration without allowing blatant cheating
|
||||
|
||||
@ -281,7 +282,7 @@ public class MovingCheck extends Check {
|
||||
final double limit = data.vertFreedom;
|
||||
|
||||
// If the event counter has been consumed, remove the vertical movement limit increase when landing the next time
|
||||
if(onGroundFrom && data.vertFreedomCounter <= 0) {
|
||||
if(onGroundFrom != MovingData.NONSOLID && data.vertFreedomCounter <= 0) {
|
||||
data.vertFreedom = 0.0D;
|
||||
}
|
||||
|
||||
@ -375,7 +376,7 @@ public class MovingCheck extends Check {
|
||||
data.teleportTo = event.getTo();
|
||||
data.jumpPhase = 0;
|
||||
data.setBackPoint = event.getTo();
|
||||
|
||||
|
||||
if(!event.getFrom().getWorld().getName().equals(event.getTo().getWorld().getName())) {
|
||||
data.worldChanged = 2; // ignore two events, because teleporting through nether portals is really weird -.-
|
||||
}
|
||||
@ -420,7 +421,7 @@ public class MovingCheck extends Check {
|
||||
if(actions == null) return;
|
||||
boolean cancelled = false;
|
||||
|
||||
|
||||
|
||||
for(Action a : actions) {
|
||||
if(a.firstAfter <= violations) {
|
||||
if(a.firstAfter == violations || a.repeat) {
|
||||
@ -429,7 +430,7 @@ public class MovingCheck extends Check {
|
||||
String log = String.format(logMessage, player.getName(), from.getWorld().getName(), to.getWorld().getName(), from.getX(), from.getY(), from.getZ(), to.getX(), to.getY(), to.getZ());
|
||||
|
||||
plugin.log(((LogAction)a).level, log);
|
||||
|
||||
|
||||
// Remember the highest log level we encountered to determine what level the summary log message should have
|
||||
if(data.highestLogLevel == null) data.highestLogLevel = Level.ALL;
|
||||
if(data.highestLogLevel.intValue() < ((LogAction)a).level.intValue()) data.highestLogLevel = ((LogAction)a).level;
|
||||
@ -473,16 +474,16 @@ public class MovingCheck extends Check {
|
||||
|
||||
// Make a modified copy of the setBackPoint to prevent other plugins from accidentally modifying it
|
||||
// and keep the current pitch and yaw (setbacks "feel" better that way).
|
||||
|
||||
|
||||
double y = data.setBackPoint.getY();
|
||||
// search for the first solid block up to 5 blocks below the setbackpoint and teleport the player there
|
||||
for(int i = 0; i < 20; i++) {
|
||||
if(playerIsOnGround(data.setBackPoint, -0.5*i)) {
|
||||
if(playerIsOnGround(data.setBackPoint, -0.5*i) != MovingData.NONSOLID) {
|
||||
y -= 0.5*i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Location t = new Location(data.setBackPoint.getWorld(), data.setBackPoint.getX(), y, data.setBackPoint.getZ(), event.getTo().getYaw(), event.getTo().getPitch());
|
||||
|
||||
// Only reset player and cancel event if teleport is successful
|
||||
@ -505,7 +506,7 @@ public class MovingCheck extends Check {
|
||||
* @param l The precise location that was used for calculation of "values"
|
||||
* @return
|
||||
*/
|
||||
private static boolean playerIsOnGround(final Location l, final double ymod) {
|
||||
private static int playerIsOnGround(final Location l, final double ymod) {
|
||||
|
||||
final int types[] = MovingData.types;
|
||||
|
||||
@ -518,49 +519,55 @@ public class MovingCheck extends Check {
|
||||
final int higherZ = upperBorder(l.getZ());
|
||||
|
||||
|
||||
int result;
|
||||
|
||||
// check in what kind of block the player is standing "in"
|
||||
result = types[w.getBlockTypeIdAt(lowerX, Y, lowerZ)] | types[w.getBlockTypeIdAt(upperX, Y, lowerZ)] |
|
||||
types[w.getBlockTypeIdAt(lowerX, Y, higherZ)] | types[w.getBlockTypeIdAt(upperX, Y, higherZ)];
|
||||
|
||||
if((result & MovingData.SOLID) != 0) {
|
||||
// return standing
|
||||
return MovingData.SOLID;
|
||||
}
|
||||
else if((result & MovingData.LIQUID) != 0) {
|
||||
// return swimming
|
||||
return MovingData.LIQUID;
|
||||
}
|
||||
|
||||
// Check the four borders of the players hitbox for something he could be standing on
|
||||
if(types[w.getBlockTypeIdAt(lowerX, Y-1, lowerZ)] != MovingData.NONSOLID ||
|
||||
types[w.getBlockTypeIdAt(upperX, Y-1, lowerZ)] != MovingData.NONSOLID ||
|
||||
types[w.getBlockTypeIdAt(lowerX, Y-1, higherZ)] != MovingData.NONSOLID ||
|
||||
types[w.getBlockTypeIdAt(upperX, Y-1, higherZ)] != MovingData.NONSOLID )
|
||||
return true;
|
||||
// Check if he is hanging onto a ladder
|
||||
else if(types[w.getBlockTypeIdAt(l.getBlockX(), Y, l.getBlockZ())] == MovingData.LADDER ||
|
||||
types[w.getBlockTypeIdAt(l.getBlockX(), Y+1, l.getBlockZ())] == MovingData.LADDER)
|
||||
return true;
|
||||
// check if he is standing "in" a block that's potentially solid (we give him the benefit of a doubt and see that as a legit move)
|
||||
// If it is not legit, the MC server already has a safeguard against that (You'll get "xy moved wrongly" on the console in that case)
|
||||
else if(types[w.getBlockTypeIdAt(lowerX, Y, lowerZ)] != MovingData.NONSOLID ||
|
||||
types[w.getBlockTypeIdAt(upperX, Y, lowerZ)] != MovingData.NONSOLID||
|
||||
types[w.getBlockTypeIdAt(lowerX, Y, higherZ)] != MovingData.NONSOLID ||
|
||||
types[w.getBlockTypeIdAt(upperX, Y, higherZ)] != MovingData.NONSOLID)
|
||||
return true;
|
||||
// check if his head is "stuck" in an block that's potentially solid (we give him the benefit of a doubt and see that as a legit move)
|
||||
// If it is not legit, the MC server already has a safeguard against that (You'll get "xy moved wrongly" on the console in that case)
|
||||
else if(types[w.getBlockTypeIdAt(lowerX, Y+1, lowerZ)] != MovingData.NONSOLID ||
|
||||
types[w.getBlockTypeIdAt(upperX, Y+1, lowerZ)] != MovingData.NONSOLID ||
|
||||
types[w.getBlockTypeIdAt(lowerX, Y+1, higherZ)] != MovingData.NONSOLID ||
|
||||
types[w.getBlockTypeIdAt(upperX, Y+1, higherZ)] != MovingData.NONSOLID)
|
||||
return true;
|
||||
// Allow using a bug called "water elevator" by checking northwest of the players location for liquids
|
||||
else if(types[w.getBlockTypeIdAt(lowerX+1, Y-1, lowerZ+1)] == MovingData.LIQUID ||
|
||||
types[w.getBlockTypeIdAt(lowerX+1, Y, lowerZ+1)] == MovingData.LIQUID ||
|
||||
types[w.getBlockTypeIdAt(lowerX+1, Y+1, lowerZ+1)] == MovingData.LIQUID ||
|
||||
types[w.getBlockTypeIdAt(lowerX+1, Y-1, lowerZ)] == MovingData.LIQUID ||
|
||||
types[w.getBlockTypeIdAt(lowerX+1, Y, lowerZ)] == MovingData.LIQUID ||
|
||||
types[w.getBlockTypeIdAt(lowerX+1, Y+1, lowerZ)] == MovingData.LIQUID ||
|
||||
types[w.getBlockTypeIdAt(lowerX, Y-1, lowerZ+1)] == MovingData.LIQUID ||
|
||||
types[w.getBlockTypeIdAt(lowerX, Y, lowerZ+1)] == MovingData.LIQUID ||
|
||||
types[w.getBlockTypeIdAt(lowerX, Y+1, lowerZ+1)] == MovingData.LIQUID)
|
||||
return true;
|
||||
// Running on fences
|
||||
else if(types[w.getBlockTypeIdAt(lowerX, Y-2, lowerZ)] == MovingData.FENCE ||
|
||||
types[w.getBlockTypeIdAt(upperX, Y-2, lowerZ)] == MovingData.FENCE ||
|
||||
types[w.getBlockTypeIdAt(lowerX, Y-2, higherZ)] == MovingData.FENCE ||
|
||||
types[w.getBlockTypeIdAt(upperX, Y-2, higherZ)] == MovingData.FENCE )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
result = types[w.getBlockTypeIdAt(lowerX, Y-1, lowerZ)] | types[w.getBlockTypeIdAt(upperX, Y-1, lowerZ)] |
|
||||
types[w.getBlockTypeIdAt(lowerX, Y-1, higherZ)] | types[w.getBlockTypeIdAt(upperX, Y-1, higherZ)];
|
||||
|
||||
if((result & MovingData.SOLID) != 0) {
|
||||
// return standing
|
||||
return MovingData.SOLID;
|
||||
}
|
||||
|
||||
|
||||
// check if his head is "stuck" in an block
|
||||
result = types[w.getBlockTypeIdAt(lowerX, Y+1, lowerZ)] | types[w.getBlockTypeIdAt(upperX, Y+1, lowerZ)] |
|
||||
types[w.getBlockTypeIdAt(lowerX, Y+1, higherZ)] | types[w.getBlockTypeIdAt(upperX, Y+1, higherZ)];
|
||||
|
||||
if((result & MovingData.SOLID) != 0) {
|
||||
// return standing
|
||||
return MovingData.SOLID;
|
||||
}
|
||||
else if((result & MovingData.LIQUID) != 0) {
|
||||
// return swimming
|
||||
return MovingData.LIQUID;
|
||||
}
|
||||
|
||||
// Running on fences causes problems if not treated specially
|
||||
result = types[w.getBlockTypeIdAt(lowerX, Y-2, lowerZ)] | types[w.getBlockTypeIdAt(upperX, Y-2, lowerZ)] |
|
||||
types[w.getBlockTypeIdAt(lowerX, Y-2, higherZ)] | types[w.getBlockTypeIdAt(upperX, Y-2, higherZ)];
|
||||
|
||||
if((result & MovingData.FENCE) != 0) {
|
||||
// return standing
|
||||
return MovingData.SOLID;
|
||||
}
|
||||
|
||||
// If nothing matches, he is somewhere in the air
|
||||
return MovingData.NONSOLID;
|
||||
}
|
||||
|
||||
|
||||
@ -611,11 +618,11 @@ public class MovingCheck extends Check {
|
||||
summaryMessage = config.getStringValue("moving.summarymessage");
|
||||
|
||||
actions = new Action[3][];
|
||||
|
||||
|
||||
actions[0] = config.getActionValue("moving.action.low");
|
||||
actions[1] = config.getActionValue("moving.action.med");
|
||||
actions[2] = config.getActionValue("moving.action.high");
|
||||
|
||||
|
||||
setActive(config.getBooleanValue("active.moving"));
|
||||
} catch (ConfigurationException e) {
|
||||
setActive(false);
|
||||
|
@ -36,13 +36,12 @@ public class MovingData {
|
||||
|
||||
public Location teleportInitializedByMe = null;
|
||||
|
||||
// Block types that may be treated specially
|
||||
public static final int SOLID = 0;
|
||||
public static final int NONSOLID = 1;
|
||||
public static final int LADDER = 2;
|
||||
public static final int LIQUID = 3;
|
||||
public static final int UNKNOWN = 4;
|
||||
public static final int FENCE = 5;
|
||||
// Block types that may need to be treated specially
|
||||
public static final int NONSOLID = 0; // 0x00000000
|
||||
public static final int SOLID = 1; // 0x00000001
|
||||
public static final int LIQUID = 2; // 0x00000010
|
||||
public static final int LADDER = 4; // 0x00000100
|
||||
public static final int FENCE = 8; // 0x00001000
|
||||
|
||||
|
||||
// Until I can think of a better way to determine if a block is solid or not, this is what I'll do
|
||||
@ -53,8 +52,8 @@ public class MovingData {
|
||||
// Find and define properties of all blocks
|
||||
for(int i = 0; i < types.length; i++) {
|
||||
|
||||
// Everything is unknown at first
|
||||
types[i] = UNKNOWN;
|
||||
// Everything is considered nonsolid at first
|
||||
types[i] = NONSOLID;
|
||||
|
||||
if(Block.byId[i] != null) {
|
||||
if(Block.byId[i].material.isSolid()) {
|
||||
@ -69,8 +68,8 @@ public class MovingData {
|
||||
}
|
||||
|
||||
// Special types just for me
|
||||
types[Material.LADDER.getId()]= LADDER;
|
||||
types[Material.FENCE.getId()]= FENCE;
|
||||
types[Material.LADDER.getId()]= LADDER | SOLID;
|
||||
types[Material.FENCE.getId()]= FENCE | SOLID;
|
||||
}
|
||||
|
||||
public static MovingData get(final Player p) {
|
||||
|
Loading…
Reference in New Issue
Block a user