/** * Check if the location is on ground and if it is hitting the bounding box of a block with the * given id. Currently this is coarse (not checking if it is really possible to stand on such a * block). * * @param id * @return */ public boolean standsOnBlock(final int id) { if (!isOnGround()) { return false; } return BlockProperties.collidesBlock( this.blockCache, minX, minY - yOnGround, minZ, maxX, minY, maxZ, id); }
/** * Checks if the player is on ground, including entities such as Minecart, Boat. * * @return true, if the player is on ground */ public boolean isOnGround() { if (onGround != null) { return onGround; } // Check cached values and simplifications. if (notOnGroundMaxY >= yOnGround) onGround = false; else if (onGroundMinY <= yOnGround) onGround = true; else { // Shortcut check (currently needed for being stuck + sf). if (blockFlags == null || (blockFlags.longValue() & BlockProperties.F_GROUND) != 0) { // TODO: Consider dropping this shortcut. final int bY = Location.locToBlock(y - yOnGround); final int id = bY == blockY ? getTypeId() : (bY == blockY - 1 ? getTypeIdBelow() : blockCache.getTypeId(blockX, bY, blockZ)); final long flags = BlockProperties.getBlockFlags(id); // TODO: Might remove check for variable ? if ((flags & BlockProperties.F_GROUND) != 0 && (flags & BlockProperties.F_VARIABLE) == 0) { final double[] bounds = blockCache.getBounds(blockX, bY, blockZ); // Check collision if not inside of the block. [Might be a problem for cauldron or similar // + something solid above.] // TODO: Might need more refinement. if (bounds != null && y - bY >= bounds[4] && BlockProperties.collidesBlock( blockCache, x, minY - yOnGround, z, x, minY, z, blockX, bY, blockZ, id, bounds, flags)) { // TODO: BlockHeight is needed for fences, use right away (above)? if (!BlockProperties.isPassableWorkaround( blockCache, blockX, bY, blockZ, minX - blockX, minY - yOnGround - bY, minZ - blockZ, id, maxX - minX, yOnGround, maxZ - minZ, 1.0) || (flags & BlockProperties.F_GROUND_HEIGHT) != 0 && BlockProperties.getGroundMinHeight( blockCache, blockX, bY, blockZ, id, bounds, flags) <= y - bY) { // // NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "*** // onground SHORTCUT"); onGround = true; } } } if (onGround == null) { // // NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "*** fetch // onground std"); // Full on-ground check (blocks). // Note: Might check for half-block height too (getTypeId), but that is much more seldom. onGround = BlockProperties.isOnGround( blockCache, minX, minY - yOnGround, minZ, maxX, minY, maxZ, 0L); } } else onGround = false; } if (onGround) onGroundMinY = Math.min(onGroundMinY, yOnGround); else { // NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "*** // onground check entities"); // TODO: further confine this ? notOnGroundMaxY = Math.max(notOnGroundMaxY, yOnGround); final double d1 = 0.25D; onGround = blockCache.standsOnEntity( player, minX - d1, minY - yOnGround - d1, minZ - d1, maxX + d1, minY + 0.25 + d1, maxZ + d1); } return onGround; }