/** * Various corner cases that would cause this check to fail or require special treatment * * @param player * @param data * @param from * @param to * @return */ public boolean shouldBeApplied( final Player player, final MovingData data, final Location from, final Location to) { if (player.isDead() || player.isInsideVehicle() || data.insideVehicle) return false; if (data.wasTeleported) { // Remember this location data.teleportedTo = from.clone(); data.wasTeleported = false; data.jumpPhase = 0; } if (data.teleportedTo != null && data.teleportedTo.getWorld().equals(from.getWorld())) { // As long as the from-Location doesn't change, the player didn't accept the teleport if (data.teleportedTo.distanceSquared(from) < 0.01D) { // Event after Teleport ignored return false; } else { // The player finally accepted the teleport with the previous event data.teleportedTo = null; } } // If the target is a bed, don't check (going to bed is a kind of mini teleport...) if (to.getWorld().getBlockTypeIdAt(to) == Material.BED_BLOCK.getId()) { return false; } return true; }
/** * Call this when a player got successfully teleported with the corresponding event to adjust * stored data to the new situation * * @param event */ public void teleported(PlayerTeleportEvent event) { MovingData data = MovingData.get(event.getPlayer()); // We can enforce a teleport, if that flag is explicitly set (but I'd rather have other plugins // not arbitrarily cancel teleport events in the first place... if (data.teleportInitializedByMe != null && event.isCancelled() && enforceTeleport && event.getTo().equals(data.teleportInitializedByMe)) { event.setCancelled(false); data.teleportInitializedByMe = null; } if (!event.isCancelled()) { data.wasTeleported = true; data.setBackPoint = event.getTo().clone(); // data.lastLocation = event.getTo().clone(); } // reset anyway - if another plugin cancelled our teleport it's no use to try and be precise data.jumpPhase = 0; }
/** * The actual check. First find out if the event needs to be handled at all Second check if the * player moved too far horizontally Third check if the player moved too high vertically Fourth * treat any occured violations as configured * * @param event */ public Location check(Player player, Location from, Location to, MovingData data) { updateVelocity(player.getVelocity(), data); Location newToLocation = null; final long startTime = System.nanoTime(); /** *********** DECIDE WHICH CHECKS NEED TO BE RUN ************ */ final boolean flyCheck = !allowFlying && !plugin.hasPermission(player, PermissionData.PERMISSION_FLYING, checkOPs); final boolean runCheck = true; /** *************** REFINE EVENT DATA FOR CHECKS ************** */ if (flyCheck || runCheck) { // In both cases it will be interesting to know the type of underground the player // is in or goes to final int fromType = helper.isLocationOnGround(from.getWorld(), from.getX(), from.getY(), from.getZ(), false); final int toType = helper.isLocationOnGround(to.getWorld(), to.getX(), to.getY(), to.getZ(), false); final boolean fromOnGround = fromType != MovingEventHelper.NONSOLID; final boolean toOnGround = toType != MovingEventHelper.NONSOLID; // Distribute data to checks in the form needed by the checks /** ******************* EXECUTE THE CHECKS ******************* */ double result = 0.0D; if (flyCheck) { result += Math.max(0D, flyingCheck.check(player, from, fromOnGround, to, toOnGround, data)); } if (runCheck) { result += Math.max( 0D, runningCheck.check( from, to, !allowFakeSneak && player.isSneaking(), !allowFastSwim && (fromType & toType & MovingEventHelper.LIQUID) > 0, data)); } /** ******* HANDLE/COMBINE THE RESULTS OF THE CHECKS ********** */ data.jumpPhase++; if (result <= 0) { if (fromOnGround) { data.setBackPoint = from; data.jumpPhase = 0; } else if (toOnGround) { data.jumpPhase = 0; } } else if (result > 0) { // Increment violation counter data.violationLevel += result; if (data.setBackPoint == null) data.setBackPoint = from; } if (result > 0 && data.violationLevel > 1) { setupSummaryTask(player, data); int level = limitCheck(data.violationLevel - 1); data.violationsInARow[level]++; newToLocation = action(player, from, to, actions[level], data.violationsInARow[level], data); } } // Slowly reduce the level with each event data.violationLevel *= 0.97; data.horizFreedom *= 0.97; statisticElapsedTimeNano += System.nanoTime() - startTime; statisticTotalEvents++; return newToLocation; }