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.Check;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.LagMeasureTask; import fr.neatmonster.nocheatplus.utilities.LagMeasureTask;
import fr.neatmonster.nocheatplus.utilities.PlayerLocation; 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. // We'll need the PlayerLocation to know some important stuff.
final PlayerLocation location = new PlayerLocation(); final PlayerLocation location = new PlayerLocation();
location.set(player.getLocation(), player); 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 // 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). // 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.permissions.Permissions;
import fr.neatmonster.nocheatplus.utilities.BlockCache; import fr.neatmonster.nocheatplus.utilities.BlockCache;
import fr.neatmonster.nocheatplus.utilities.BlockProperties; import fr.neatmonster.nocheatplus.utilities.BlockProperties;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.PlayerLocation; import fr.neatmonster.nocheatplus.utilities.PlayerLocation;
/* /*
@ -355,8 +356,30 @@ public class MovingListener implements Listener {
final MovingConfig cc = MovingConfig.getConfig(player); final MovingConfig cc = MovingConfig.getConfig(player);
moveInfo.set(player, from, to, cc.yOnGround); moveInfo.set(player, from, to, cc.yOnGround);
final MovingData data = MovingData.getData(player); 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.noFallAssumeGround = false;
data.teleported = null; data.teleported = null;

View File

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

View File

@ -328,4 +328,9 @@ public class CheckUtils {
return Math.max(((LivingEntity) entity).getEyeHeight(), entityHeight); return Math.max(((LivingEntity) entity).getEyeHeight(), entityHeight);
} else return mcEntity.height; } 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,424 +37,431 @@ import org.bukkit.util.Vector;
* MMMMMMMMMMM * 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 { public class PlayerLocation {
/** Box for one time use, no nesting, no extra storing this(!). */ /** Box for one time use, no nesting, no extra storing this(!). */
protected static final AxisAlignedBB useBox = AxisAlignedBB.a(0, 0, 0, 0, 0, 0); protected static final AxisAlignedBB useBox = AxisAlignedBB.a(0, 0, 0, 0, 0, 0);
/** Type id of the block at the position. */ /** Type id of the block at the position. */
private Integer typeId; private Integer typeId;
/** Type id of the block below. */
private Integer typeIdBelow;
private Integer data;
/** Is the player above stairs? */ /** Type id of the block below. */
private Boolean aboveStairs; private Integer typeIdBelow;
/** Is the player in lava? */ private Integer data;
private Boolean inLava;
/** Is the player in water? */ /** Is the player above stairs? */
private Boolean inWater; private Boolean aboveStairs;
/** Is the player is web? */ /** Is the player in lava? */
private Boolean inWeb; private Boolean inLava;
/** Is the player on the ground? */ /** Is the player in water? */
private Boolean onGround; private Boolean inWater;
/** Is the player on ice? */ /** Is the player is web? */
private Boolean onIce; private Boolean inWeb;
/** Is the player on ladder? */ /** Is the player on the ground? */
private Boolean onLadder; private Boolean onGround;
/** 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;
/** The block coordinates. */ /** Is the player on ice? */
private int blockX, blockY, blockZ; private Boolean onIce;
/** 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;
/** Bukkit world. */ /** Is the player on ladder? */
private World world; private Boolean onLadder;
/** The worldServer. */
private WorldServer worldServer;
/** Optional block property cache. */
private BlockCache blockCache;
/** /** Simple test if the exact position is passable. */
* Gets the location. private Boolean passable;
*
* @return the location
*/
public Location getLocation() {
return new Location(world, x, y, z);
}
/** /** Y parameter for growing the bounding box with the isOnGround check. */
* Gets the blockX. private double yOnGround = 0.001;
*
* @return the blockX
*/
public double getX() {
return x;
}
/** /** The block coordinates. */
* Gets the boundY. private int blockX, blockY, blockZ;
*
* @return the boundY
*/
public double getY() {
return y;
}
/**
* Gets the blockZ.
*
* @return the blockZ
*/
public double getZ() {
return z;
}
/** /** The exact coordinates. */
* Gets the yaw. private double x, y, z;
*
* @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();
}
/** private float yaw, pitch;
* 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;
}
/** // Members that need cleanup:
* 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;
}
/** /** The entityPlayer player. */
* Checks if the player is in a liquid. private EntityPlayer entityPlayer;
*
* @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();
}
/** /** Bounding box of the player. */
* Checks if the player is on ice. private double minX, maxX, minY, maxY, minZ, maxZ;
*
* @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;
}
/** /** Bukkit world. */
* Checks if the player is on a ladder or vine. private World world;
*
* @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.<br>
* 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();
}
/** /** The worldServer. */
* Checks if the player is in web. private WorldServer worldServer;
*
* @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;
}
/** /** Optional block property cache. */
* Checks if the player is on ground. private BlockCache blockCache;
*
* @return true, if the player is on ground /**
*/ * Gets the location.
public boolean isOnGround() { *
if (onGround == null) { * @return the location
final double d0 = 0.01D; */
onGround = BlockProperties.isOnGround(getBlockAccess(), minX - d0, minY - yOnGround, minZ - d0, maxX + d0, minY + 0.25, maxZ + d0); public Location getLocation() {
if (!onGround){ return new Location(world, x, y, z);
// 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") * Gets the blockX.
final List list = worldServer.getEntities(entityPlayer, box); *
@SuppressWarnings("rawtypes") * @return the blockX
Iterator iterator = list.iterator(); */
while (iterator.hasNext()) { public double getX() {
final Entity entity = (Entity) iterator.next(); return x;
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; * Gets the boundY.
else { *
onGround = true; * @return the boundY
break; */
} public double getY() {
} return y;
} }
}
return onGround; /**
} * 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.<br>
* 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() { public double getyOnGround() {
return yOnGround; return yOnGround;
} }
public void setyOnGround(final double yOnGround) { public void setyOnGround(final double yOnGround) {
this.yOnGround = yOnGround; this.yOnGround = yOnGround;
this.onGround = null; this.onGround = null;
} }
/** /**
* Simple at the spot passability test, no bounding boxes. * Simple at the spot passability test, no bounding boxes.
* @return *
*/ * @return
public boolean isPassable(){ */
if (passable == null) passable = BlockProperties.isPassable(getBlockAccess(), x, y, z, getTypeId()); public boolean isPassable() {
return passable; if (passable == null) passable = BlockProperties.isPassable(getBlockAccess(), x, y, z, getTypeId());
} return passable;
}
/**
* Convenience method: delegate to BlockProperties.isDoppwnStream . /**
* @param xDistance * Convenience method: delegate to BlockProperties.isDoppwnStream .
* @param zDistance *
* @return * @param xDistance
*/ * @param zDistance
public boolean isDownStream(final double xDistance, final double zDistance){ * @return
return BlockProperties.isDownStream(getBlockAccess(), blockX, blockY, blockZ, getData(), xDistance, zDistance); */
} public boolean isDownStream(final double xDistance, final double zDistance)
{
return BlockProperties.isDownStream(getBlockAccess(), blockX, blockY, blockZ, getData(), xDistance, zDistance);
}
public Integer getTypeId() { public Integer getTypeId() {
if (typeId == null) typeId = getTypeId(blockX, blockY, blockZ); if (typeId == null) typeId = getTypeId(blockX, blockY, blockZ);
return typeId; return typeId;
} }
public Integer getTypeIdBelow() { public Integer getTypeIdBelow() {
if (typeIdBelow == null) typeIdBelow = getTypeId(blockX, blockY - 1, blockZ); if (typeIdBelow == null) typeIdBelow = getTypeId(blockX, blockY - 1, blockZ);
return typeIdBelow; return typeIdBelow;
} }
public Integer getData(){ public Integer getData() {
if (data == null) data = getData(blockX, blockY, blockZ); if (data == null) data = getData(blockX, blockY, blockZ);
return data; 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);
} }
/** /**
* Uses id cache if present. * Uses id cache if present.
*
* @param x * @param x
* @param y * @param y
* @param z * @param z
* @return * @return
*/ */
public final int getData(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.getData(x, y, z) : blockCache.getData(x, y, z); return blockCache == null ? worldServer.getTypeId(x, y, z) : blockCache.getTypeId(x, y, z);
} }
public WorldServer getWorldServer() { /**
return worldServer; * Uses id cache if present.
} *
* @param x
/** * @param y
* Set the id cache for faster id getting. * @param z
* @param cache * @return
*/ */
public void setBlockCache(final BlockCache cache) { public final int getData(final int x, final int y, final int z) {
this.blockCache = cache; return blockCache == null ? worldServer.getData(x, y, z) : blockCache.getData(x, y, z);
} }
/** public WorldServer getWorldServer() {
* return worldServer;
* @return }
*/
public final IBlockAccess getBlockAccess() { /**
return blockCache == null ? worldServer : blockCache; * Set the id cache for faster id getting.
} *
* @param cache
/** */
* Sets the player location object. public void setBlockCache(final BlockCache cache) {
* this.blockCache = cache;
* @param location }
* the location
* @param player /**
* the player *
*/ * @return
public void set(final Location location, final Player player){ */
set(location, player, 0.001); 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. * Sets the player location object. Does not set or reset blockCache.
* *
@ -498,19 +505,37 @@ public class PlayerLocation {
typeId = typeIdBelow = data = null; typeId = typeIdBelow = data = null;
aboveStairs = inLava = inWater = inWeb = onGround = onIce = onLadder = passable = 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); this.setyOnGround(yFreedom);
} }
/** /**
* Set some references to null. * Set some references to null.
*/ */
public void cleanup(){ public void cleanup() {
entityPlayer = null; entityPlayer = null;
world = null; world = null;
worldServer = null; worldServer = null;
blockCache = null; // No reset here. 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;
}
} }