예제 #1
0
 /**
  * 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;
 }
예제 #2
0
 /**
  * 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;
 }
예제 #3
0
 /**
  * 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;
 }
예제 #4
0
 /**
  * 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;
 }
예제 #5
0
  private Location potentialViolation(
      final Player player,
      final Location loc,
      final PlayerLocation from,
      final PlayerLocation to,
      final int manhattan,
      String tags,
      final MovingData data,
      final MovingConfig cc) {
    // Moving into a block, possibly a violation.

    // Check the players location if different from others.
    // (It provides a better set-back for some exploits.)
    final int lbX = loc.getBlockX();
    final int lbY = loc.getBlockY();
    final int lbZ = loc.getBlockZ();
    Location setBackLoc = null; // Alternative to from.getLocation().
    // First check if the player is moving from a passable location.
    // If not, the move might still be allowed, if moving inside of the same block, or from and to
    // have head position passable.
    if (from.isPassable()) {
      // Put one workaround for 1.5 high blocks here:
      if (from.isBlockAbove(to)
          && (BlockProperties.getBlockFlags(to.getTypeId()) & BlockProperties.F_HEIGHT150) != 0) {
        // Check if the move went from inside of the block.
        if (BlockProperties.collidesBlock(
            to.getBlockCache(),
            from.getX(),
            from.getY(),
            from.getZ(),
            from.getX(),
            from.getY(),
            from.getZ(),
            to.getBlockX(),
            to.getBlockY(),
            to.getBlockZ(),
            to.getTypeId())) {
          // Allow moving inside of 1.5 high blocks.
          return null;
        }
      }
      // From should be the set-back.
      tags += "into";
    } else if (BlockProperties.isPassable(
        from.getBlockCache(), loc.getX(), loc.getY(), loc.getZ(), from.getTypeId(lbX, lbY, lbZ))) {
      // Keep loc, because it it is passable.
      tags += "into_shift";
      setBackLoc = loc;
    }
    //				} else if (BlockProperties.isPassableExact(from.getBlockCache(), loc.getX(), loc.getY(),
    // loc.getZ(), from.getTypeId(lbX, lbY, lbZ))) {
    // (Mind that this can be the case on the same block theoretically.)
    // Keep loc as set-back.
    //				}
    else if (!from.isSameBlock(lbX, lbY, lbZ)) {
      // Both loc and from are not passable. Use from as set.back (earliest).
      tags += "cross_shift";
    } else if (manhattan == 1
        && to.isBlockAbove(from)
        && BlockProperties.isPassable(
            from.getBlockCache(),
            from.getX(),
            from.getY() + player.getEyeHeight(),
            from.getZ(),
            from.getTypeId(
                from.getBlockX(),
                Location.locToBlock(from.getY() + player.getEyeHeight()),
                from.getBlockZ()))) {
      //				else if (to.isBlockAbove(from) && BlockProperties.isPassableExact(from.getBlockCache(),
      // from.getX(), from.getY() + player.getEyeHeight(), from.getZ(),
      // from.getTypeId(from.getBlockX(), Location.locToBlock(from.getY() + player.getEyeHeight()),
      // from.getBlockZ()))) {
      // Allow the move up if the head is free.
      // TODO: Better distinguish ray-tracing (through something thin) or check to-head-passable
      // too?
      return null;
    } else if (manhattan > 0) {
      // Otherwise keep from as set-back.
      tags += "cross";
    } else {
      // All blocks are the same, allow the move.
      return null;
    }

    // Discard inconsistent locations.
    // TODO: Might get rid of using the in-between loc - needs use-case checking.
    if (setBackLoc != null
        && (TrigUtil.distance(from, to) > 0.75 || TrigUtil.distance(from, setBackLoc) > 0.125)) {
      setBackLoc = null;
    }

    // Prefer the set-back location from the data.
    if (data.hasSetBack()) {
      // TODO: Review or make configurable.
      final Location ref = data.getSetBack(to);
      if (BlockProperties.isPassable(from.getBlockCache(), ref)
          || setBackLoc == null
          || TrigUtil.distance(from, setBackLoc) > 0.13) {
        //					if (BlockProperties.isPassableExact(from.getBlockCache(), ref)) {
        setBackLoc = ref;
        if (data.debug) {
          NCPAPIProvider.getNoCheatPlusAPI()
              .getLogManager()
              .debug(
                  Streams.TRACE_FILE, player.getName() + " Using set-back location for passable.");
        }
      } else if (data.debug) {
        NCPAPIProvider.getNoCheatPlusAPI()
            .getLogManager()
            .debug(Streams.TRACE_FILE, player.getName() + " Ignoring set-back for passable.");
      }
    }

    // TODO: set data.set-back ? or something: still some aji here.

    // Return the reset position.
    data.passableVL += 1d;
    final ViolationData vd =
        new ViolationData(this, player, data.passableVL, 1, cc.passableActions);
    if (data.debug || vd.needsParameters()) {
      vd.setParameter(
          ParameterName.LOCATION_FROM,
          String.format(Locale.US, "%.2f, %.2f, %.2f", from.getX(), from.getY(), from.getZ()));
      vd.setParameter(
          ParameterName.LOCATION_TO,
          String.format(Locale.US, "%.2f, %.2f, %.2f", to.getX(), to.getY(), to.getZ()));
      vd.setParameter(
          ParameterName.DISTANCE, String.format(Locale.US, "%.2f", TrigUtil.distance(from, to)));
      // TODO: Consider adding from.getTypeId() too, if blocks differ and non-air.
      vd.setParameter(ParameterName.BLOCK_ID, "" + to.getTypeId());
      if (!tags.isEmpty()) {
        vd.setParameter(ParameterName.TAGS, tags);
      }
    }
    if (executeActions(vd)) {
      // TODO: Consider another set back position for this, also keeping track of players moving
      // around in blocks.
      final Location newTo;
      if (setBackLoc != null) {
        // Ensure the given location is cloned.
        newTo = LocUtil.clone(setBackLoc);
      } else {
        newTo = from.getLocation();
        if (data.debug) {
          NCPAPIProvider.getNoCheatPlusAPI()
              .getLogManager()
              .debug(Streams.TRACE_FILE, player.getName() + " Using from location for passable.");
        }
      }
      newTo.setYaw(to.getYaw());
      newTo.setPitch(to.getPitch());
      return newTo;
    } else {
      // No cancel action set.
      return null;
    }
  }
예제 #6
0
 /**
  * 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;
 }
예제 #7
0
  private Location potentialViolation(
      final Player player,
      Location loc,
      final PlayerLocation from,
      final PlayerLocation to,
      final int manhattan,
      String tags,
      final MovingData data,
      final MovingConfig cc) {
    // Moving into a block, possibly a violation.

    // Check the players location if different from others.
    // (It provides a better set-back for some exploits.)
    final int lbX = loc.getBlockX();
    final int lbY = loc.getBlockY();
    final int lbZ = loc.getBlockZ();
    // First check if the player is moving from a passable location.
    // If not, the move might still be allowed, if moving inside of the same block, or from and to
    // have head position passable.
    if (from.isPassable()) {
      // Put one workaround for 1.5 high blocks here:
      if (from.isBlockAbove(to)
          && (BlockProperties.getBlockFlags(to.getTypeId()) & BlockProperties.F_HEIGHT150) != 0) {
        // Check if the move went from inside of the block.
        if (BlockProperties.collidesBlock(
            to.getBlockCache(),
            from.getX(),
            from.getY(),
            from.getZ(),
            from.getX(),
            from.getY(),
            from.getZ(),
            to.getBlockX(),
            to.getBlockY(),
            to.getBlockZ(),
            to.getTypeId())) {
          // Allow moving inside of 1.5 high blocks.
          return null;
        }
      }
      // From should be the set-back.
      loc = null;
      tags += "into";
    } else if (BlockProperties.isPassable(
        from.getBlockCache(), loc.getX(), loc.getY(), loc.getZ(), from.getTypeId(lbX, lbY, lbZ))) {
      tags += "into_shift";
    }
    //				} else if (BlockProperties.isPassableExact(from.getBlockCache(), loc.getX(), loc.getY(),
    // loc.getZ(), from.getTypeId(lbX, lbY, lbZ))) {
    // (Mind that this can be the case on the same block theoretically.)
    // Keep loc as set-back.
    //				}
    else if (!from.isSameBlock(lbX, lbY, lbZ)) {
      // Otherwise keep loc as set-back.
      tags += "cross_shift";
    } else if (manhattan == 1
        && to.isBlockAbove(from)
        && BlockProperties.isPassable(
            from.getBlockCache(),
            from.getX(),
            from.getY() + player.getEyeHeight(),
            from.getZ(),
            from.getTypeId(
                from.getBlockX(),
                Location.locToBlock(from.getY() + player.getEyeHeight()),
                from.getBlockZ()))) {
      //				else if (to.isBlockAbove(from) && BlockProperties.isPassableExact(from.getBlockCache(),
      // from.getX(), from.getY() + player.getEyeHeight(), from.getZ(),
      // from.getTypeId(from.getBlockX(), Location.locToBlock(from.getY() + player.getEyeHeight()),
      // from.getBlockZ()))) {
      // Allow the move up if the head is free.
      return null;
    } else if (manhattan > 0) {
      // Otherwise keep from as set-back.
      loc = null;
      tags += "cross";
    } else {
      // All blocks are the same, allow the move.
      return null;
    }

    // Discard inconsistent locations.
    // TODO: Might get rid of using the in-between loc - needs use-case checking.
    if (loc != null
        && (TrigUtil.distance(from, to) > 0.75 || TrigUtil.distance(from, loc) > 0.125)) {
      loc = null;
    }

    // Prefer the set-back location from the data.
    if (data.hasSetBack()) {
      final Location ref = data.getSetBack(to);
      if (BlockProperties.isPassable(from.getBlockCache(), ref)
          || loc == null
          || TrigUtil.distance(from, loc) > 0.13) {
        //					if (BlockProperties.isPassableExact(from.getBlockCache(), ref)) {
        loc = ref;
        if (cc.debug) {
          System.out.println(player.getName() + " Using set-back location for passable.");
        }
      } else if (cc.debug) {
        System.out.println(player.getName() + " Ignoring set-back for passable.");
      }
    }

    // TODO: set data.set-back ? or something: still some aji here.

    // Return the reset position.
    data.passableVL += 1d;
    final ViolationData vd =
        new ViolationData(this, player, data.passableVL, 1, cc.passableActions);
    if (cc.debug || vd.needsParameters()) {
      vd.setParameter(ParameterName.BLOCK_ID, "" + to.getTypeId());
      if (!tags.isEmpty()) {
        vd.setParameter(ParameterName.TAGS, tags);
      }
    }
    if (executeActions(vd)) {
      // TODO: Consider another set back position for this, also keeping track of players moving
      // around in blocks.
      final Location newTo;
      if (loc != null) {
        // Ensure the given location is cloned.
        newTo = LocUtil.clone(loc);
      } else {
        newTo = from.getLocation();
        if (cc.debug) {
          System.out.println(player.getName() + " Using from location for passable.");
        }
      }
      newTo.setYaw(to.getYaw());
      newTo.setPitch(to.getPitch());
      return newTo;
    } else {
      // No cancel action set.
      return null;
    }
  }