Hot fix for bounding box problems.

This commit is contained in:
asofold 2012-11-08 06:02:22 +01:00
parent 22f2a5c248
commit 462aeed412
5 changed files with 447 additions and 383 deletions

View File

@ -5,6 +5,7 @@ import org.bukkit.potion.PotionEffectType;
import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.LagMeasureTask;
import fr.neatmonster.nocheatplus.utilities.PlayerLocation;
@ -45,6 +46,11 @@ public class Critical extends Check {
// We'll need the PlayerLocation to know some important stuff.
final PlayerLocation location = new PlayerLocation();
location.set(player.getLocation(), player);
if (location.isIllegal()) {
location.cleanup();
CheckUtils.onIllegalMove(player);
return true;
}
// Check if the hit was a critical hit (positive fall distance, entity in the air, not on ladder, not in liquid
// and without blindness effect).

View File

@ -45,6 +45,7 @@ import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager;
import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.utilities.BlockCache;
import fr.neatmonster.nocheatplus.utilities.BlockProperties;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.PlayerLocation;
/*
@ -355,8 +356,30 @@ public class MovingListener implements Listener {
final MovingConfig cc = MovingConfig.getConfig(player);
moveInfo.set(player, from, to, cc.yOnGround);
final MovingData data = MovingData.getData(player);
if (pFrom.isIllegal() || pTo.isIllegal()) {
moveInfo.cleanup();
parkedInfo.add(moveInfo);
CheckUtils.onIllegalMove(player);
if (data.setBack != null){
event.setFrom(data.setBack);
event.setTo(data.setBack);
}
else{
pFrom.set(player.getLocation(), player);
if (!pFrom.isIllegal()){
event.setFrom(pFrom.getLocation());
event.setTo(pFrom.getLocation());
}
else{
NoCheatPlus.denyLogin(player.getName(), 24L*60L*60L*1000L);
CheckUtils.logSevere("[NCP] could not restore location for " + player.getName() + " deny login for 24 hours");
}
pFrom.cleanup();
}
return;
}
data.noFallAssumeGround = false;
data.teleported = null;

View File

@ -863,6 +863,11 @@ public class BlockProperties {
// return blockId != 0 && net.minecraft.server.Block.byId[blockId].//.c();// d();
// Bit fat workaround, maybe put the object through from check listener ?
pLoc.set(location, player, 0.3);
if (pLoc.isIllegal()) {
pLoc.cleanup();
CheckUtils.onIllegalMove(player);
return false;
}
final boolean onGround = pLoc.isOnGround();
pLoc.cleanup();
return onGround;

View File

@ -328,4 +328,9 @@ public class CheckUtils {
return Math.max(((LivingEntity) entity).getEyeHeight(), entityHeight);
} else return mcEntity.height;
}
public static void onIllegalMove(final Player player){
player.kickPlayer("Illegal move.");
logWarning("[NCP] Disconnect " + player.getName() + " due to illegal move!");
}
}

View File

@ -37,7 +37,8 @@ import org.bukkit.util.Vector;
* MMMMMMMMMMM
*/
/**
* An utility class used to know a lot of things for a player and a location given.
* An utility class used to know a lot of things for a player and a location
* given.
*/
public class PlayerLocation {
@ -76,14 +77,14 @@ public class PlayerLocation {
/** Simple test if the exact position is passable. */
private Boolean passable;
/** Y parameter for growing the bounding box with the isOnGround check.*/
/** Y parameter for growing the bounding box with the isOnGround check. */
private double yOnGround = 0.001;
/** The block coordinates. */
private int blockX, blockY, blockZ;
/** The exact coordinates. */
private double x,y,z;
private double x, y, z;
private float yaw, pitch;
@ -162,24 +163,25 @@ public class PlayerLocation {
return new Vector(x, y, z);
}
public double getWidth(){
public double getWidth() {
return entityPlayer.width;
}
public int getBlockX(){
public int getBlockX() {
return blockX;
}
public int getBlockY(){
public int getBlockY() {
return blockY;
}
public int getBlockZ(){
public int getBlockZ() {
return blockZ;
}
/**
* Compares block coordinates (not the world).
*
* @param other
* @return
*/
@ -189,6 +191,7 @@ public class PlayerLocation {
/**
* Compares exact coordinates (not the world).
*
* @param loc
* @return
*/
@ -198,6 +201,7 @@ public class PlayerLocation {
/**
* Compares exact coordinates (not the world).
*
* @param loc
* @return
*/
@ -211,8 +215,9 @@ public class PlayerLocation {
* @return true, if the player above on stairs
*/
public boolean isAboveStairs() {
if (aboveStairs == null){
// aboveStairs = BlockProperties.isStairs(getTypeIdBelow().intValue());
if (aboveStairs == null) {
// aboveStairs =
// BlockProperties.isStairs(getTypeIdBelow().intValue());
// TODO: maybe distinguish upside down stairs and normal stairs !
final double diff = getWidth() + 0.001;
aboveStairs = BlockProperties.collides(getBlockAccess(), x - diff, y + 0.25, z - diff, x + diff, y - 1.0, z + diff, BlockProperties.F_STAIRS);
@ -260,19 +265,16 @@ public class PlayerLocation {
return isInLava() || isInWater();
}
/**
* Checks if the player is on ice.
*
* @return true, if the player is on ice
*/
public boolean isOnIce() {
if (onIce == null){
if (onIce == null) {
final org.bukkit.entity.Player entity = this.entityPlayer.getBukkitEntity();
if (entity.isSneaking() || entity.isBlocking())
onIce = getTypeId(blockX, Location.locToBlock(minY - 0.1D), blockZ) == Material.ICE.getId();
else
onIce = getTypeIdBelow().intValue() == Material.ICE.getId();
if (entity.isSneaking() || entity.isBlocking()) onIce = getTypeId(blockX, Location.locToBlock(minY - 0.1D), blockZ) == Material.ICE.getId();
else onIce = getTypeIdBelow().intValue() == Material.ICE.getId();
}
return onIce;
}
@ -283,7 +285,7 @@ public class PlayerLocation {
* @return If so.
*/
public boolean isOnLadder() {
if (onLadder == null){
if (onLadder == null) {
final int typeId = getTypeId();
onLadder = typeId == Material.LADDER.getId() || typeId == Material.VINE.getId();
}
@ -309,10 +311,10 @@ public class PlayerLocation {
public boolean isInWeb() {
final int webId = Material.WEB.getId();
if (inWeb == null) {
for (int blockX = Location.locToBlock(minX + 0.001D); blockX <= Location.locToBlock(maxX - 0.001D); blockX++){
for (int blockY = Location.locToBlock(minY + 0.001D); blockY <= Location.locToBlock(maxY - 0.001D); blockY++){
for (int blockZ = Location.locToBlock(minZ + 0.001D); blockZ <= Location.locToBlock(maxZ - 0.001D); blockZ++){
if (getTypeId(blockX, blockY, blockZ) == webId){
for (int blockX = Location.locToBlock(minX + 0.001D); blockX <= Location.locToBlock(maxX - 0.001D); blockX++) {
for (int blockY = Location.locToBlock(minY + 0.001D); blockY <= Location.locToBlock(maxY - 0.001D); blockY++) {
for (int blockZ = Location.locToBlock(minZ + 0.001D); blockZ <= Location.locToBlock(maxZ - 0.001D); blockZ++) {
if (getTypeId(blockX, blockY, blockZ) == webId) {
inWeb = true;
return true;
}
@ -333,7 +335,7 @@ public class PlayerLocation {
if (onGround == null) {
final double d0 = 0.01D;
onGround = BlockProperties.isOnGround(getBlockAccess(), minX - d0, minY - yOnGround, minZ - d0, maxX + d0, minY + 0.25, maxZ + d0);
if (!onGround){
if (!onGround) {
// TODO: Probably check other ids too before doing this ?
final double d1 = 0.25D;
final AxisAlignedBB box = useBox.b(minX - d1, minY - getyOnGround() - d1, minZ - d1, maxX + d1, minY + 0.25 + d1, maxZ + d1);
@ -368,20 +370,23 @@ public class PlayerLocation {
/**
* Simple at the spot passability test, no bounding boxes.
*
* @return
*/
public boolean isPassable(){
public boolean isPassable() {
if (passable == null) passable = BlockProperties.isPassable(getBlockAccess(), x, y, z, getTypeId());
return passable;
}
/**
* Convenience method: delegate to BlockProperties.isDoppwnStream .
*
* @param xDistance
* @param zDistance
* @return
*/
public boolean isDownStream(final double xDistance, final double zDistance){
public boolean isDownStream(final double xDistance, final double zDistance)
{
return BlockProperties.isDownStream(getBlockAccess(), blockX, blockY, blockZ, getData(), xDistance, zDistance);
}
@ -390,36 +395,37 @@ public class PlayerLocation {
return typeId;
}
public Integer getTypeIdBelow() {
if (typeIdBelow == null) typeIdBelow = getTypeId(blockX, blockY - 1, blockZ);
return typeIdBelow;
}
public Integer getData(){
public Integer getData() {
if (data == null) data = getData(blockX, blockY, blockZ);
return data;
}
/**
* Uses id cache if present.
*
* @param x
* @param y
* @param z
* @return
*/
public final int getTypeId(final int x, final int y, final int z){
public final int getTypeId(final int x, final int y, final int z) {
return blockCache == null ? worldServer.getTypeId(x, y, z) : blockCache.getTypeId(x, y, z);
}
/**
* Uses id cache if present.
*
* @param x
* @param y
* @param z
* @return
*/
public final int getData(final int x, final int y, final int z){
public final int getData(final int x, final int y, final int z) {
return blockCache == null ? worldServer.getData(x, y, z) : blockCache.getData(x, y, z);
}
@ -429,6 +435,7 @@ public class PlayerLocation {
/**
* Set the id cache for faster id getting.
*
* @param cache
*/
public void setBlockCache(final BlockCache cache) {
@ -451,7 +458,7 @@ public class PlayerLocation {
* @param player
* the player
*/
public void set(final Location location, final Player player){
public void set(final Location location, final Player player) {
set(location, player, 0.001);
}
@ -498,7 +505,8 @@ public class PlayerLocation {
typeId = typeIdBelow = data = null;
aboveStairs = inLava = inWater = inWeb = onGround = onIce = onLadder = passable = null;
// TODO: Consider blockCache.setAccess? <- currently rather not, because it might be anything.
// TODO: Consider blockCache.setAccess? <- currently rather not, because
// it might be anything.
this.setyOnGround(yFreedom);
}
@ -506,11 +514,28 @@ public class PlayerLocation {
/**
* Set some references to null.
*/
public void cleanup(){
public void cleanup() {
entityPlayer = null;
world = null;
worldServer = null;
blockCache = null; // No reset here.
}
/**
* Attempt to check for some exploits (!).
*
* @return
*/
public boolean isIllegal() {
if (entityPlayer.dead) return false;
if (!entityPlayer.isSleeping()){
// This can not really test stance but height of bounding box.
final double dY = Math.abs(maxY - minY);
if (dY > 1.8) return true; // dY > 1.65D ||
if (dY < 0.1D) return true;
}
if (Math.abs(minX) > 3.2E7D || Math.abs(maxX) > 3.2E7D || Math.abs(minZ) > 3.2E7D || Math.abs(maxZ) > 3.2E7D) return true;
return false;
}
}