Differentiate between LIQUID and SOLID blocks when determining if a

player is on ground or in the air.
This commit is contained in:
Evenprime 2011-06-06 17:04:20 +02:00
parent eac9f4d10a
commit 81b4d7160e
2 changed files with 78 additions and 72 deletions

View File

@ -163,16 +163,17 @@ 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);
@ -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;
}
@ -477,7 +478,7 @@ public class MovingCheck extends Check {
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;
}
@ -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;
}

View File

@ -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) {