/** * Check if a player may climb upwards (isOnClimbable returned true, player does not move from/to * ground).<br> * Having checked the other stuff is prerequisite for calling this (!). * * @param jumpHeigth Height the player is allowed to have jumped. * @return */ public boolean canClimbUp(double jumpHeigth) { // TODO: distinguish vines. if (BlockProperties.isAttachedClimbable(getTypeId())) { // Check if vine is attached to something solid if (BlockProperties.canClimbUp(blockCache, blockX, blockY, blockZ)) { return true; } // Check the block at head height. final int headY = Location.locToBlock(y + eyeHeight); if (headY > blockY) { for (int cy = blockY + 1; cy <= headY; cy++) { if (BlockProperties.canClimbUp(blockCache, blockX, cy, blockZ)) { return true; } } } // Finally check possible jump height. // TODO: This too is inaccurate. if (isOnGround(jumpHeigth)) { // Here ladders are ok. return true; } return false; } return true; }
/** * Simple block-on-ground check for given margin (no entities). Meant for checking bigger margin * than the normal yOnGround. * * @param yOnGround Margin below the player. * @param xzMargin * @param yMargin Extra margin added below and above. * @param ignoreFlags Flags to not regard as ground. * @return */ public boolean isOnGround( final double yOnGround, final double xzMargin, final double yMargin, final long ignoreFlags) { if (ignoreFlags == 0) { if (xzMargin >= 0 && onGroundMinY <= yOnGround) return true; if (xzMargin <= 0 && yMargin == 0) { if (notOnGroundMaxY >= yOnGround) return false; } } // NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "*** Fetch // on-ground: yOnGround=" + yOnGround + " xzM=" + xzMargin + " yM=" + yMargin + " ign=" + // ignoreFlags); final boolean onGround = BlockProperties.isOnGround( blockCache, minX - xzMargin, minY - yOnGround - yMargin, minZ - xzMargin, maxX + xzMargin, minY + yMargin, maxZ + xzMargin, ignoreFlags); if (ignoreFlags == 0) { if (onGround) { if (xzMargin <= 0 && yMargin == 0) { onGroundMinY = Math.min(onGroundMinY, yOnGround); } } else { if (xzMargin >= 0) { notOnGroundMaxY = Math.max(notOnGroundMaxY, yOnGround); } } } return onGround; }
/** * 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); }
/** * Test if the foot location is passable (not the bounding box). <br> * The result is cached. * * @return */ public boolean isPassable() { if (passable == null) { passable = BlockProperties.isPassable(blockCache, x, y, z, getTypeId()); // passable = BlockProperties.isPassableExact(blockCache, x, y, z, getTypeId()); } return passable; }
/** * Test if something solid/ground-like collides within the given margin above the height of the * player. * * @param marginAboveHeight * @return */ public boolean isHeadObstructed(double marginAboveHeight) { return BlockProperties.collides( blockCache, x - width, y + eyeHeight, z - width, x + width, y + eyeHeight + marginAboveHeight, z + width, BlockProperties.F_GROUND | BlockProperties.F_SOLID); }
/** * Check if solid blocks hit the box. * * @param xzMargin * @param yMargin * @return */ public boolean isNextToGround(final double xzMargin, final double yMargin) { // TODO: Adjust to check block flags ? return BlockProperties.collides( blockCache, minX - xzMargin, minY - yMargin, minZ - xzMargin, maxX + xzMargin, maxY + yMargin, maxZ + xzMargin, BlockProperties.F_GROUND); }
/** * Checks if the player is on a ladder or vine. * * @return If so. */ public boolean isOnClimbable() { if (onClimbable == null) { // Climbable blocks. if (blockFlags != null && (blockFlags.longValue() & BlockProperties.F_CLIMBABLE) == 0) { onClimbable = false; return false; } onClimbable = (BlockProperties.getBlockFlags(getTypeId()) & BlockProperties.F_CLIMBABLE) != 0; // TODO: maybe use specialized bounding box. // final double d = 0.1d; // onClimbable = BlockProperties.collides(getBlockAccess(), minX - d, minY - d, minZ // - d, maxX + d, minY + 1.0, maxZ + d, BlockProperties.F_CLIMBABLE); } return onClimbable; }
/** * 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; }
/** * Check the maximally used bounds for the block checking, to have flags ready for faster denial. * * @param maxYonGround */ public void collectBlockFlags(double maxYonGround) { maxYonGround = Math.max(yOnGround, maxYonGround); // TODO: Clearly refine this for 1.5 high blocks. // TODO: Check which checks need blocks below. final double yExtra = 0.6; // y - blockY - maxYonGround > 0.5 ? 0.5 : 1.0; // TODO: xz margin still needed ? final double xzM = 0; // 0.001; blockFlags = BlockProperties.collectFlagsSimple( blockCache, minX - xzM, minY - yExtra - maxYonGround, minZ - xzM, maxX + xzM, Math.max(maxY, minY + 1.5), maxZ + xzM); }
/** * Checks if the player is in web. * * @return true, if the player is in web */ public boolean isInWeb() { if (inWeb == null) { // TODO: inset still needed ? final double inset = 0.001d; inWeb = BlockProperties.collidesId( blockCache, minX + inset, minY + inset, minZ + inset, maxX - inset, maxY - inset, maxZ - inset, Material.WEB); } return inWeb; }
/** * 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 lava. * * @return true, if the player is in lava */ public boolean isInLava() { if (inLava == null) { if (blockFlags != null && (blockFlags.longValue() & BlockProperties.F_LAVA) == 0) { inLava = false; return false; } // TODO: ... // final double dX = -0.10000000149011612D; // final double dY = -0.40000000596046448D; // final double dZ = dX; // inLava = BlockProperties.collides(blockCache, minX - dX, minY - dY, minZ - dZ, // maxX + dX, maxY + dY, maxZ + dZ, BlockProperties.F_LAVA); inLava = BlockProperties.collides( blockCache, minX, minY, minZ, maxX, maxY, maxZ, 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) { if (blockFlags != null && (blockFlags.longValue() & BlockProperties.F_WATER) == 0) { inWater = false; return false; } // TODO: ... // final double dX = -0.001D; // final double dY = -0.40000000596046448D - 0.001D; // final double dZ = dX; // inWater = BlockProperties.collides(blockCache, minX - dX, minY - dY, minZ - dZ, // maxX + dX, maxY + dY, maxZ + dZ, BlockProperties.F_WATER); inWater = BlockProperties.collides( blockCache, minX, minY, minZ, maxX, maxY, maxZ, BlockProperties.F_WATER); } return inWater; }
/** * 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 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 on ice. * * @return true, if the player is on ice */ public boolean isOnIce() { if (onIce == null) { // TODO: Use a box here too ? // TODO: check if player is really sneaking (refactor from survivalfly to static access in // Combined ?)! if (blockFlags != null && (blockFlags.longValue() & BlockProperties.F_ICE) == 0) { // TODO: check onGroundMinY !? onIce = false; } else { final int id; if (player.isSneaking() || player.isBlocking()) { id = getTypeId(blockX, Location.locToBlock(minY - 0.1D), blockZ); } else { id = getTypeIdBelow().intValue(); } onIce = BlockProperties.isIce(id); } } return onIce; }
/** * Checks if the player is above stairs. * * @return true, if the player above on stairs */ public boolean isAboveStairs() { if (aboveStairs == null) { if (blockFlags != null && (blockFlags.longValue() & BlockProperties.F_STAIRS) == 0) { aboveStairs = false; return false; } // TODO: Distinguish based on actual height off .0 ? // TODO: diff still needed ? final double diff = 0; // 0.001; aboveStairs = BlockProperties.collides( blockCache, minX - diff, minY - 1.0, minZ - diff, maxX + diff, minY + 0.25, maxZ + diff, BlockProperties.F_STAIRS); } return aboveStairs; }
/** * Convenience method: delegate to BlockProperties.isDoppwnStream . * * @param xDistance * @param zDistance * @return */ public boolean isDownStream(final double xDistance, final double zDistance) { return BlockProperties.isDownStream( blockCache, blockX, blockY, blockZ, getData(), xDistance, zDistance); }
/** * 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; }
/** * 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; }
/** * Checks if the player is above a ladder or vine.<br> * Does not save back value to field. * * @return If so. */ public boolean isAboveLadder() { if (blockFlags != null && (blockFlags.longValue() & BlockProperties.F_CLIMBABLE) == 0) return false; // TODO: bounding box ? return (BlockProperties.getBlockFlags(getTypeIdBelow()) & BlockProperties.F_CLIMBABLE) != 0; }