mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2025-02-05 14:21:36 +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
@ -163,16 +163,17 @@ public class MovingCheck extends Check {
|
|||||||
// The location we'd use as a new setback if there are no violations
|
// The location we'd use as a new setback if there are no violations
|
||||||
Location newSetBack = null;
|
Location newSetBack = null;
|
||||||
|
|
||||||
final boolean onGroundFrom = playerIsOnGround(from, 0.0D);
|
final int onGroundFrom = playerIsOnGround(from, 0.0D);
|
||||||
|
|
||||||
double limit = calculateVerticalLimit(data, onGroundFrom);
|
double limit = calculateVerticalLimit(data, onGroundFrom);
|
||||||
|
|
||||||
// Handle 4 distinct cases: Walk, Jump, Land, Fly
|
// Handle 4 distinct cases: Walk, Jump, Land, Fly
|
||||||
|
|
||||||
// Walk or start Jump
|
// Walk or start Jump
|
||||||
if(onGroundFrom)
|
if(onGroundFrom != MovingData.NONSOLID)
|
||||||
{
|
{
|
||||||
limit += jumpHeight;
|
limit += jumpHeight;
|
||||||
|
|
||||||
final double distance = to.getY() - from.getY();
|
final double distance = to.getY() - from.getY();
|
||||||
|
|
||||||
violationLevelVertical = limitCheck(distance - limit);
|
violationLevelVertical = limitCheck(distance - limit);
|
||||||
@ -201,9 +202,9 @@ public class MovingCheck extends Check {
|
|||||||
limit += jumpHeight - (data.jumpPhase-jumpingLimit) * 0.2D;
|
limit += jumpHeight - (data.jumpPhase-jumpingLimit) * 0.2D;
|
||||||
else limit += jumpHeight;
|
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();
|
final double distance = to.getY() - l.getY();
|
||||||
|
|
||||||
@ -211,7 +212,7 @@ public class MovingCheck extends Check {
|
|||||||
violationLevelVertical = limitCheck(distance - limit);
|
violationLevelVertical = limitCheck(distance - limit);
|
||||||
|
|
||||||
if(violationLevelVertical < 0) {
|
if(violationLevelVertical < 0) {
|
||||||
if(onGroundTo) { // Land
|
if(onGroundTo != MovingData.NONSOLID) { // Land
|
||||||
data.jumpPhase = 0; // He is on ground now, so reset the jump
|
data.jumpPhase = 0; // He is on ground now, so reset the jump
|
||||||
newSetBack = to;
|
newSetBack = to;
|
||||||
}
|
}
|
||||||
@ -253,7 +254,7 @@ public class MovingCheck extends Check {
|
|||||||
statisticTotalEvents++;
|
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
|
// 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;
|
final double limit = data.vertFreedom;
|
||||||
|
|
||||||
// If the event counter has been consumed, remove the vertical movement limit increase when landing the next time
|
// 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;
|
data.vertFreedom = 0.0D;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,7 +478,7 @@ public class MovingCheck extends Check {
|
|||||||
double y = data.setBackPoint.getY();
|
double y = data.setBackPoint.getY();
|
||||||
// search for the first solid block up to 5 blocks below the setbackpoint and teleport the player there
|
// 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++) {
|
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;
|
y -= 0.5*i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -505,7 +506,7 @@ public class MovingCheck extends Check {
|
|||||||
* @param l The precise location that was used for calculation of "values"
|
* @param l The precise location that was used for calculation of "values"
|
||||||
* @return
|
* @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;
|
final int types[] = MovingData.types;
|
||||||
|
|
||||||
@ -518,49 +519,55 @@ public class MovingCheck extends Check {
|
|||||||
final int higherZ = upperBorder(l.getZ());
|
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
|
// 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 ||
|
result = types[w.getBlockTypeIdAt(lowerX, Y-1, lowerZ)] | types[w.getBlockTypeIdAt(upperX, Y-1, lowerZ)] |
|
||||||
types[w.getBlockTypeIdAt(upperX, Y-1, lowerZ)] != MovingData.NONSOLID ||
|
types[w.getBlockTypeIdAt(lowerX, Y-1, higherZ)] | types[w.getBlockTypeIdAt(upperX, Y-1, higherZ)];
|
||||||
types[w.getBlockTypeIdAt(lowerX, Y-1, higherZ)] != MovingData.NONSOLID ||
|
|
||||||
types[w.getBlockTypeIdAt(upperX, Y-1, higherZ)] != MovingData.NONSOLID )
|
if((result & MovingData.SOLID) != 0) {
|
||||||
return true;
|
// return standing
|
||||||
// Check if he is hanging onto a ladder
|
return MovingData.SOLID;
|
||||||
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)
|
// check if his head is "stuck" in an block
|
||||||
// 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)
|
result = types[w.getBlockTypeIdAt(lowerX, Y+1, lowerZ)] | types[w.getBlockTypeIdAt(upperX, Y+1, lowerZ)] |
|
||||||
else if(types[w.getBlockTypeIdAt(lowerX, Y, lowerZ)] != MovingData.NONSOLID ||
|
types[w.getBlockTypeIdAt(lowerX, Y+1, higherZ)] | types[w.getBlockTypeIdAt(upperX, Y+1, higherZ)];
|
||||||
types[w.getBlockTypeIdAt(upperX, Y, lowerZ)] != MovingData.NONSOLID||
|
|
||||||
types[w.getBlockTypeIdAt(lowerX, Y, higherZ)] != MovingData.NONSOLID ||
|
if((result & MovingData.SOLID) != 0) {
|
||||||
types[w.getBlockTypeIdAt(upperX, Y, higherZ)] != MovingData.NONSOLID)
|
// return standing
|
||||||
return true;
|
return MovingData.SOLID;
|
||||||
// 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((result & MovingData.LIQUID) != 0) {
|
||||||
else if(types[w.getBlockTypeIdAt(lowerX, Y+1, lowerZ)] != MovingData.NONSOLID ||
|
// return swimming
|
||||||
types[w.getBlockTypeIdAt(upperX, Y+1, lowerZ)] != MovingData.NONSOLID ||
|
return MovingData.LIQUID;
|
||||||
types[w.getBlockTypeIdAt(lowerX, Y+1, higherZ)] != MovingData.NONSOLID ||
|
}
|
||||||
types[w.getBlockTypeIdAt(upperX, Y+1, higherZ)] != MovingData.NONSOLID)
|
|
||||||
return true;
|
// Running on fences causes problems if not treated specially
|
||||||
// Allow using a bug called "water elevator" by checking northwest of the players location for liquids
|
result = types[w.getBlockTypeIdAt(lowerX, Y-2, lowerZ)] | types[w.getBlockTypeIdAt(upperX, Y-2, lowerZ)] |
|
||||||
else if(types[w.getBlockTypeIdAt(lowerX+1, Y-1, lowerZ+1)] == MovingData.LIQUID ||
|
types[w.getBlockTypeIdAt(lowerX, Y-2, higherZ)] | types[w.getBlockTypeIdAt(upperX, Y-2, higherZ)];
|
||||||
types[w.getBlockTypeIdAt(lowerX+1, Y, lowerZ+1)] == MovingData.LIQUID ||
|
|
||||||
types[w.getBlockTypeIdAt(lowerX+1, Y+1, lowerZ+1)] == MovingData.LIQUID ||
|
if((result & MovingData.FENCE) != 0) {
|
||||||
types[w.getBlockTypeIdAt(lowerX+1, Y-1, lowerZ)] == MovingData.LIQUID ||
|
// return standing
|
||||||
types[w.getBlockTypeIdAt(lowerX+1, Y, lowerZ)] == MovingData.LIQUID ||
|
return MovingData.SOLID;
|
||||||
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 ||
|
// If nothing matches, he is somewhere in the air
|
||||||
types[w.getBlockTypeIdAt(lowerX, Y+1, lowerZ+1)] == MovingData.LIQUID)
|
return MovingData.NONSOLID;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,13 +36,12 @@ public class MovingData {
|
|||||||
|
|
||||||
public Location teleportInitializedByMe = null;
|
public Location teleportInitializedByMe = null;
|
||||||
|
|
||||||
// Block types that may be treated specially
|
// Block types that may need to be treated specially
|
||||||
public static final int SOLID = 0;
|
public static final int NONSOLID = 0; // 0x00000000
|
||||||
public static final int NONSOLID = 1;
|
public static final int SOLID = 1; // 0x00000001
|
||||||
public static final int LADDER = 2;
|
public static final int LIQUID = 2; // 0x00000010
|
||||||
public static final int LIQUID = 3;
|
public static final int LADDER = 4; // 0x00000100
|
||||||
public static final int UNKNOWN = 4;
|
public static final int FENCE = 8; // 0x00001000
|
||||||
public static final int FENCE = 5;
|
|
||||||
|
|
||||||
|
|
||||||
// Until I can think of a better way to determine if a block is solid or not, this is what I'll do
|
// 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
|
// Find and define properties of all blocks
|
||||||
for(int i = 0; i < types.length; i++) {
|
for(int i = 0; i < types.length; i++) {
|
||||||
|
|
||||||
// Everything is unknown at first
|
// Everything is considered nonsolid at first
|
||||||
types[i] = UNKNOWN;
|
types[i] = NONSOLID;
|
||||||
|
|
||||||
if(Block.byId[i] != null) {
|
if(Block.byId[i] != null) {
|
||||||
if(Block.byId[i].material.isSolid()) {
|
if(Block.byId[i].material.isSolid()) {
|
||||||
@ -69,8 +68,8 @@ public class MovingData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Special types just for me
|
// Special types just for me
|
||||||
types[Material.LADDER.getId()]= LADDER;
|
types[Material.LADDER.getId()]= LADDER | SOLID;
|
||||||
types[Material.FENCE.getId()]= FENCE;
|
types[Material.FENCE.getId()]= FENCE | SOLID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MovingData get(final Player p) {
|
public static MovingData get(final Player p) {
|
||||||
|
Loading…
Reference in New Issue
Block a user