Example #1
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;
    }
  }
Example #2
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;
    }
  }
Example #3
0
  /**
   * @param player
   * @param from
   * @param to
   * @param data
   * @param cc
   * @param time Milliseconds.
   * @return
   */
  public Location check(
      final Player player,
      final PlayerLocation from,
      final PlayerLocation to,
      final MovingData data,
      final MovingConfig cc,
      final long time,
      final boolean useBlockChangeTracker) {

    // Reset tags, just in case.
    tags.clear();

    // Some edge data for this move.
    final GameMode gameMode = player.getGameMode();
    final ModelFlying model = cc.getModelFlying(player, from);
    final PlayerMoveData thisMove = data.playerMoves.getCurrentMove();
    //        if (!data.thisMove.from.extraPropertiesValid) {
    //            // TODO: Confine by model config flag or just always do [if the latter: do it in
    // the listener]?
    //            data.thisMove.setExtraProperties(from, to);
    //        }
    thisMove.modelFlying = model;
    final PlayerMoveData lastMove = data.playerMoves.getFirstPastMove();

    // Calculate some distances.
    final double yDistance = thisMove.yDistance;
    final double hDistance = thisMove.hDistance;

    final boolean flying = gameMode == BridgeMisc.GAME_MODE_SPECTATOR || player.isFlying();
    final boolean sprinting = time <= data.timeSprinting + cc.sprintingGrace;

    // Lost ground, if set so.
    if (model.ground) {
      MovingUtil.prepareFullCheck(from, to, thisMove, Math.max(cc.yOnGround, cc.noFallyOnGround));
      if (!thisMove.from.onGroundOrResetCond) {
        if (from.isSamePos(to)) {
          if (lastMove.toIsValid
              && lastMove.hDistance > 0.0
              && lastMove.yDistance < -0.3 // Copy and paste from sf.
              && LostGround.lostGroundStill(
                  player, from, to, hDistance, yDistance, sprinting, lastMove, data, cc, tags)) {
            // Nothing to do.
          }
        } else if (LostGround.lostGround(
            player,
            from,
            to,
            hDistance,
            yDistance,
            sprinting,
            lastMove,
            data,
            cc,
            useBlockChangeTracker ? blockChangeTracker : null,
            tags)) {
          // Nothing to do.
        }
      }
    }

    // Horizontal distance check.
    double[] resH =
        hDist(
            player, from, to, hDistance, yDistance, sprinting, flying, lastMove, time, model, data,
            cc);
    double limitH = resH[0];
    double resultH = resH[1];

    // Check velocity.
    if (resultH > 0) {
      double hFreedom = data.getHorizontalFreedom();
      if (hFreedom < resultH) {
        // Use queued velocity if possible.
        hFreedom += data.useHorizontalVelocity(resultH - hFreedom);
      }
      if (hFreedom > 0.0) {
        resultH = Math.max(0.0, resultH - hFreedom);
        if (resultH <= 0.0) {
          limitH = hDistance;
        }
        tags.add("hvel");
      }
    } else {
      data.clearActiveHorVel(); // TODO: test/check !
    }

    resultH *= 100.0; // Normalize to % of a block.
    if (resultH > 0.0) {
      tags.add("hdist");
    }

    // Vertical move.
    double limitV = 0.0; // Limit.
    double resultV = 0.0; // Violation (normalized to 100 * 1 block, applies if > 0.0).

    // Distinguish checking method by y-direction of the move.
    if (yDistance > 0.0) {
      // Ascend.
      double[] res = vDistAscend(from, to, yDistance, flying, thisMove, lastMove, model, data, cc);
      resultV = Math.max(resultV, res[1]);
      limitV = res[0];
    } else if (yDistance < 0.0) {
      // Descend.
      double[] res = vDistDescend(from, to, yDistance, flying, lastMove, model, data, cc);
      resultV = Math.max(resultV, res[1]);
      limitV = res[0];
    } else {
      // Keep altitude.
      double[] res = vDistZero(from, to, yDistance, flying, lastMove, model, data, cc);
      resultV = Math.max(resultV, res[1]);
      limitV = res[0];
    }

    // Velocity.
    if (resultV > 0.0 && data.getOrUseVerticalVelocity(yDistance) != null) {
      resultV = 0.0;
      tags.add("vvel");
    }

    // Add tag for maximum height check (silent set back).
    final double maximumHeight = model.maxHeight + player.getWorld().getMaxHeight();
    if (to.getY() > maximumHeight) {
      // TODO: Allow use velocity there (would need a flag to signal the actual check below)?
      tags.add("maxheight");
    }

    resultV *= 100.0; // Normalize to % of a block.
    if (resultV > 0.0) {
      tags.add("vdist");
    }

    final double result = Math.max(0.0, resultH) + Math.max(0.0, resultV);

    if (data.debug) {
      outpuDebugMove(player, hDistance, limitH, yDistance, limitV, model, tags, data);
    }

    // Violation handling.
    Location setBack = null; // Might get altered below.
    if (result > 0.0) {
      // Increment violation level.
      data.creativeFlyVL += result;

      // Execute whatever actions are associated with this check and the violation level and find
      // out if we
      // should cancel the event.
      final ViolationData vd =
          new ViolationData(this, player, data.creativeFlyVL, result, cc.creativeFlyActions);
      if (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)));
        if (!tags.isEmpty()) {
          vd.setParameter(ParameterName.TAGS, StringUtil.join(tags, "+"));
        }
      }
      if (executeActions(vd).willCancel()) {
        // Compose a new location based on coordinates of "newTo" and viewing direction of
        // "event.getTo()"
        // to allow the player to look somewhere else despite getting pulled back by NoCheatPlus.
        setBack = data.getSetBack(to);
      }
    } else {
      // Maximum height check (silent set back).
      if (to.getY() > maximumHeight) {
        setBack = data.getSetBack(to);
      }
      if (setBack == null) {
        // Slowly reduce the violation level with each event.
        data.creativeFlyVL *= 0.97;
      }
    }

    // Return setBack, if set.
    if (setBack != null) {
      // Check for max height of the set-back.
      if (setBack.getY() > maximumHeight) {
        // Correct the y position.
        setBack.setY(getCorrectedHeight(maximumHeight, setBack.getWorld()));
        if (data.debug) {
          debug(player, "Maximum height exceeded by set-back, correct to: " + setBack.getY());
        }
      }
      data.sfJumpPhase = 0;
      return setBack;
    } else {
      // Adjust the set-back and other last distances.
      data.setSetBack(to);
      // Adjust jump phase.
      if (!thisMove.from.onGroundOrResetCond && !thisMove.to.onGroundOrResetCond) {
        data.sfJumpPhase++;
      } else if (thisMove.touchedGround && !thisMove.to.onGroundOrResetCond) {
        data.sfJumpPhase = 1;
      } else {
        data.sfJumpPhase = 0;
      }
      return null;
    }
  }