From 462aeed412df70cadd6e6c027b646b9f92a99cab Mon Sep 17 00:00:00 2001 From: asofold Date: Thu, 8 Nov 2012 06:02:22 +0100 Subject: [PATCH] Hot fix for bounding box problems. --- .../nocheatplus/checks/fight/Critical.java | 6 + .../checks/moving/MovingListener.java | 25 +- .../utilities/BlockProperties.java | 5 + .../nocheatplus/utilities/CheckUtils.java | 5 + .../nocheatplus/utilities/PlayerLocation.java | 789 +++++++++--------- 5 files changed, 447 insertions(+), 383 deletions(-) diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/Critical.java b/src/fr/neatmonster/nocheatplus/checks/fight/Critical.java index 110657d9..decc3d77 100644 --- a/src/fr/neatmonster/nocheatplus/checks/fight/Critical.java +++ b/src/fr/neatmonster/nocheatplus/checks/fight/Critical.java @@ -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). diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java b/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java index b33e6878..3e657a52 100644 --- a/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java +++ b/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java @@ -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; diff --git a/src/fr/neatmonster/nocheatplus/utilities/BlockProperties.java b/src/fr/neatmonster/nocheatplus/utilities/BlockProperties.java index 1674d973..13fa19bb 100644 --- a/src/fr/neatmonster/nocheatplus/utilities/BlockProperties.java +++ b/src/fr/neatmonster/nocheatplus/utilities/BlockProperties.java @@ -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; diff --git a/src/fr/neatmonster/nocheatplus/utilities/CheckUtils.java b/src/fr/neatmonster/nocheatplus/utilities/CheckUtils.java index cd2a610e..b14f9ac1 100644 --- a/src/fr/neatmonster/nocheatplus/utilities/CheckUtils.java +++ b/src/fr/neatmonster/nocheatplus/utilities/CheckUtils.java @@ -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!"); + } } diff --git a/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java b/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java index 188de7e4..8aacf42b 100644 --- a/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java +++ b/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java @@ -37,424 +37,431 @@ 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 { - + /** Box for one time use, no nesting, no extra storing this(!). */ protected static final AxisAlignedBB useBox = AxisAlignedBB.a(0, 0, 0, 0, 0, 0); - /** Type id of the block at the position. */ - private Integer typeId; - - /** Type id of the block below. */ - private Integer typeIdBelow; - - private Integer data; + /** Type id of the block at the position. */ + private Integer typeId; - /** Is the player above stairs? */ - private Boolean aboveStairs; + /** Type id of the block below. */ + private Integer typeIdBelow; - /** Is the player in lava? */ - private Boolean inLava; + private Integer data; - /** Is the player in water? */ - private Boolean inWater; + /** Is the player above stairs? */ + private Boolean aboveStairs; - /** Is the player is web? */ - private Boolean inWeb; + /** Is the player in lava? */ + private Boolean inLava; - /** Is the player on the ground? */ - private Boolean onGround; + /** Is the player in water? */ + private Boolean inWater; - /** Is the player on ice? */ - private Boolean onIce; + /** Is the player is web? */ + private Boolean inWeb; - /** Is the player on ladder? */ - private Boolean onLadder; - - /** Simple test if the exact position is passable. */ - private Boolean passable; - - /** Y parameter for growing the bounding box with the isOnGround check.*/ - private double yOnGround = 0.001; + /** Is the player on the ground? */ + private Boolean onGround; - /** The block coordinates. */ - private int blockX, blockY, blockZ; - - /** The exact coordinates. */ - private double x,y,z; - - private float yaw, pitch; - - // Members that need cleanup: - - /** The entityPlayer player. */ - private EntityPlayer entityPlayer; - - /** Bounding box of the player. */ - private double minX, maxX, minY, maxY, minZ, maxZ; + /** Is the player on ice? */ + private Boolean onIce; - /** Bukkit world. */ - private World world; - - /** The worldServer. */ - private WorldServer worldServer; - - /** Optional block property cache. */ - private BlockCache blockCache; + /** Is the player on ladder? */ + private Boolean onLadder; - /** - * Gets the location. - * - * @return the location - */ - public Location getLocation() { - return new Location(world, x, y, z); - } + /** Simple test if the exact position is passable. */ + private Boolean passable; - /** - * Gets the blockX. - * - * @return the blockX - */ - public double getX() { - return x; - } + /** Y parameter for growing the bounding box with the isOnGround check. */ + private double yOnGround = 0.001; - /** - * Gets the boundY. - * - * @return the boundY - */ - public double getY() { - return y; - } - - /** - * Gets the blockZ. - * - * @return the blockZ - */ - public double getZ() { - return z; - } + /** The block coordinates. */ + private int blockX, blockY, blockZ; - /** - * Gets the yaw. - * - * @return the yaw - */ - public float getYaw() { - return yaw; - } - - /** - * Gets the pitch. - * - * @return the pitch - */ - public float getPitch() { - return pitch; - } - - public Vector getVector() { - return new Vector(x, y, z); - } - - public double getWidth(){ - return entityPlayer.width; - } - - public int getBlockX(){ - return blockX; - } - - public int getBlockY(){ - return blockY; - } - - public int getBlockZ(){ - return blockZ; - } - - /** - * Compares block coordinates (not the world). - * @param other - * @return - */ - public final boolean isSameBlock(final PlayerLocation other) { - return blockX == other.getBlockX() && blockZ == other.getBlockZ() && blockY == other.getBlockY(); - } - - /** - * Compares exact coordinates (not the world). - * @param loc - * @return - */ - public boolean isSamePos(final PlayerLocation loc) { - return x == loc.getX() && z == loc.getZ() && y == loc.getY(); - } - - /** - * Compares exact coordinates (not the world). - * @param loc - * @return - */ - public boolean isSamePos(final Location loc) { - return x == loc.getX() && z == loc.getZ() && y == loc.getY(); - } + /** The exact coordinates. */ + private double x, y, z; - /** - * Checks if the player is above stairs. - * - * @return true, if the player above on stairs - */ - public boolean isAboveStairs() { - 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); - } - return aboveStairs; - } + private float yaw, pitch; - /** - * Checks if the player is in lava. - * - * @return true, if the player is in lava - */ - public boolean isInLava() { - if (inLava == null) { - final double dX = -0.10000000149011612D; - final double dY = -0.40000000596046448D; - final double dZ = dX; - inLava = BlockProperties.collides(getBlockAccess(), minX - dX, minY - dY, minZ - dZ, maxX + dX, maxY + dY, maxZ + dZ, BlockProperties.F_LAVA); - } - return inLava; - } - - /** - * Checks if the player is in water. - * - * @return true, if the player is in water - */ - public boolean isInWater() { - if (inWater == null) { - final double dX = -0.001D; - final double dY = -0.40000000596046448D - 0.001D; - final double dZ = -0.001D; - inWater = BlockProperties.collides(getBlockAccess(), minX - dX, minY - dY, minZ - dZ, maxX + dX, maxY + dY, maxZ + dZ, BlockProperties.F_WATER); - } - return inWater; - } + // Members that need cleanup: - /** - * Checks if the player is in a liquid. - * - * @return true, if the player is in a liquid - */ - public boolean isInLiquid() { - // TODO: optimize (check liquid first and only if liquid check further) - return isInLava() || isInWater(); - } - + /** The entityPlayer player. */ + private EntityPlayer entityPlayer; - /** - * Checks if the player is on ice. - * - * @return true, if the player is on ice - */ - public boolean isOnIce() { - 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(); - } - return onIce; - } + /** Bounding box of the player. */ + private double minX, maxX, minY, maxY, minZ, maxZ; - /** - * Checks if the player is on a ladder or vine. - * - * @return If so. - */ - public boolean isOnLadder() { - if (onLadder == null){ - final int typeId = getTypeId(); - onLadder = typeId == Material.LADDER.getId() || typeId == Material.VINE.getId(); - } - return onLadder; - } - - /** - * Checks if the player is above a ladder or vine.
- * Does not save back value to field. - * - * @return If so. - */ - public boolean isAboveLadder() { - final int typeId = getTypeIdBelow(); - return typeId == Material.LADDER.getId() || typeId == Material.VINE.getId(); - } + /** Bukkit world. */ + private World world; - /** - * Checks if the player is in web. - * - * @return true, if the player is in web - */ - 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){ - inWeb = true; - return true; - } - } - } - } - inWeb = false; - } - return inWeb; - } + /** The worldServer. */ + private WorldServer worldServer; - /** - * Checks if the player is on ground. - * - * @return true, if the player is on ground - */ - public boolean isOnGround() { - 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){ - // 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); - @SuppressWarnings("rawtypes") - final List list = worldServer.getEntities(entityPlayer, box); - @SuppressWarnings("rawtypes") - Iterator iterator = list.iterator(); - while (iterator.hasNext()) { - final Entity entity = (Entity) iterator.next(); - final EntityType type = entity.getBukkitEntity().getType(); - if (type != EntityType.BOAT && type != EntityType.MINECART) continue; - final AxisAlignedBB otherBox = entity.boundingBox; - if (box.a > otherBox.d || box.d < otherBox.a || box.b > otherBox.e || box.e < otherBox.b || box.c > otherBox.f || box.f < otherBox.c) continue; - else { - onGround = true; - break; - } - } - } - } - return onGround; - } + /** Optional block property cache. */ + private BlockCache blockCache; + + /** + * Gets the location. + * + * @return the location + */ + public Location getLocation() { + return new Location(world, x, y, z); + } + + /** + * Gets the blockX. + * + * @return the blockX + */ + public double getX() { + return x; + } + + /** + * Gets the boundY. + * + * @return the boundY + */ + public double getY() { + return y; + } + + /** + * Gets the blockZ. + * + * @return the blockZ + */ + public double getZ() { + return z; + } + + /** + * Gets the yaw. + * + * @return the yaw + */ + public float getYaw() { + return yaw; + } + + /** + * Gets the pitch. + * + * @return the pitch + */ + public float getPitch() { + return pitch; + } + + public Vector getVector() { + return new Vector(x, y, z); + } + + public double getWidth() { + return entityPlayer.width; + } + + public int getBlockX() { + return blockX; + } + + public int getBlockY() { + return blockY; + } + + public int getBlockZ() { + return blockZ; + } + + /** + * Compares block coordinates (not the world). + * + * @param other + * @return + */ + public final boolean isSameBlock(final PlayerLocation other) { + return blockX == other.getBlockX() && blockZ == other.getBlockZ() && blockY == other.getBlockY(); + } + + /** + * Compares exact coordinates (not the world). + * + * @param loc + * @return + */ + public boolean isSamePos(final PlayerLocation loc) { + return x == loc.getX() && z == loc.getZ() && y == loc.getY(); + } + + /** + * Compares exact coordinates (not the world). + * + * @param loc + * @return + */ + public boolean isSamePos(final Location loc) { + return x == loc.getX() && z == loc.getZ() && y == loc.getY(); + } + + /** + * Checks if the player is above stairs. + * + * @return true, if the player above on stairs + */ + public boolean isAboveStairs() { + 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); + } + return aboveStairs; + } + + /** + * Checks if the player is in lava. + * + * @return true, if the player is in lava + */ + public boolean isInLava() { + if (inLava == null) { + final double dX = -0.10000000149011612D; + final double dY = -0.40000000596046448D; + final double dZ = dX; + inLava = BlockProperties.collides(getBlockAccess(), minX - dX, minY - dY, minZ - dZ, maxX + dX, maxY + dY, maxZ + dZ, BlockProperties.F_LAVA); + } + return inLava; + } + + /** + * Checks if the player is in water. + * + * @return true, if the player is in water + */ + public boolean isInWater() { + if (inWater == null) { + final double dX = -0.001D; + final double dY = -0.40000000596046448D - 0.001D; + final double dZ = -0.001D; + inWater = BlockProperties.collides(getBlockAccess(), minX - dX, minY - dY, minZ - dZ, maxX + dX, maxY + dY, maxZ + dZ, BlockProperties.F_WATER); + } + return inWater; + } + + /** + * Checks if the player is in a liquid. + * + * @return true, if the player is in a liquid + */ + public boolean isInLiquid() { + // TODO: optimize (check liquid first and only if liquid check further) + return isInLava() || isInWater(); + } + + /** + * Checks if the player is on ice. + * + * @return true, if the player is on ice + */ + public boolean isOnIce() { + 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(); + } + return onIce; + } + + /** + * Checks if the player is on a ladder or vine. + * + * @return If so. + */ + public boolean isOnLadder() { + if (onLadder == null) { + final int typeId = getTypeId(); + onLadder = typeId == Material.LADDER.getId() || typeId == Material.VINE.getId(); + } + return onLadder; + } + + /** + * Checks if the player is above a ladder or vine.
+ * Does not save back value to field. + * + * @return If so. + */ + public boolean isAboveLadder() { + final int typeId = getTypeIdBelow(); + return typeId == Material.LADDER.getId() || typeId == Material.VINE.getId(); + } + + /** + * Checks if the player is in web. + * + * @return true, if the player is in web + */ + 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) { + inWeb = true; + return true; + } + } + } + } + inWeb = false; + } + return inWeb; + } + + /** + * Checks if the player is on ground. + * + * @return true, if the player is on ground + */ + public boolean isOnGround() { + 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) { + // 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); + @SuppressWarnings("rawtypes") + final List list = worldServer.getEntities(entityPlayer, box); + @SuppressWarnings("rawtypes") + Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + final Entity entity = (Entity) iterator.next(); + final EntityType type = entity.getBukkitEntity().getType(); + if (type != EntityType.BOAT && type != EntityType.MINECART) continue; + final AxisAlignedBB otherBox = entity.boundingBox; + if (box.a > otherBox.d || box.d < otherBox.a || box.b > otherBox.e || box.e < otherBox.b || box.c > otherBox.f || box.f < otherBox.c) continue; + else { + onGround = true; + break; + } + } + } + } + return onGround; + } public double getyOnGround() { - return yOnGround; - } + return yOnGround; + } - public void setyOnGround(final double yOnGround) { - this.yOnGround = yOnGround; - this.onGround = null; - } - - /** - * Simple at the spot passability test, no bounding boxes. - * @return - */ - 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){ - return BlockProperties.isDownStream(getBlockAccess(), blockX, blockY, blockZ, getData(), xDistance, zDistance); - } + public void setyOnGround(final double yOnGround) { + this.yOnGround = yOnGround; + this.onGround = null; + } + + /** + * Simple at the spot passability test, no bounding boxes. + * + * @return + */ + 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) + { + return BlockProperties.isDownStream(getBlockAccess(), blockX, blockY, blockZ, getData(), xDistance, zDistance); + } public Integer getTypeId() { if (typeId == null) typeId = getTypeId(blockX, blockY, blockZ); return typeId; } - public Integer getTypeIdBelow() { if (typeIdBelow == null) typeIdBelow = getTypeId(blockX, blockY - 1, blockZ); return typeIdBelow; } - - 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){ - return blockCache == null ? worldServer.getTypeId(x, y, z) : blockCache.getTypeId(x, y, z); + + 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 getData(final int x, final int y, final int z){ - return blockCache == null ? worldServer.getData(x, y, z) : blockCache.getData(x, y, z); - } - - public WorldServer getWorldServer() { - return worldServer; - } - - /** - * Set the id cache for faster id getting. - * @param cache - */ - public void setBlockCache(final BlockCache cache) { - this.blockCache = cache; - } - - /** - * - * @return - */ - public final IBlockAccess getBlockAccess() { - return blockCache == null ? worldServer : blockCache; - } - - /** - * Sets the player location object. - * - * @param location - * the location - * @param player - * the player - */ - public void set(final Location location, final Player player){ - set(location, player, 0.001); - } - + 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) { + return blockCache == null ? worldServer.getData(x, y, z) : blockCache.getData(x, y, z); + } + + public WorldServer getWorldServer() { + return worldServer; + } + + /** + * Set the id cache for faster id getting. + * + * @param cache + */ + public void setBlockCache(final BlockCache cache) { + this.blockCache = cache; + } + + /** + * + * @return + */ + public final IBlockAccess getBlockAccess() { + return blockCache == null ? worldServer : blockCache; + } + + /** + * Sets the player location object. + * + * @param location + * the location + * @param player + * the player + */ + public void set(final Location location, final Player player) { + set(location, player, 0.001); + } + /** * Sets the player location object. Does not set or reset blockCache. * @@ -498,19 +505,37 @@ 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); } - - /** - * Set some references to null. - */ - public void cleanup(){ - entityPlayer = null; - world = null; - worldServer = null; - blockCache = null; // No reset here. - } + + /** + * Set some references to null. + */ + 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; + } }