diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/MovingData.java b/src/fr/neatmonster/nocheatplus/checks/moving/MovingData.java index c0e67b48..e945eab3 100644 --- a/src/fr/neatmonster/nocheatplus/checks/moving/MovingData.java +++ b/src/fr/neatmonster/nocheatplus/checks/moving/MovingData.java @@ -139,7 +139,6 @@ public class MovingData extends ACheckData { public final ActionFrequency vDistCount = new ActionFrequency(3, 333); // Locations shared between all checks. - public Location ground; public Location setBack; public Location teleported; diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java b/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java index 6402878d..e6df2bc0 100644 --- a/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java +++ b/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java @@ -209,18 +209,22 @@ public class MovingListener implements Listener { * |___/ */ final Player player = event.getPlayer(); - final MovingData data = MovingData.getData(player); - if (!creativeFly.isEnabled(player) && survivalFly.isEnabled(player) && survivalFly.check(player)) { - // To cancel the event, we simply teleport the player to his last - // safe location. - Location target = null; - if (data.ground != null) target = data.ground; - else if (data.setBack != null) target = data.setBack; -// else target = player.getLocation(); // TODO - - - if (target != null) player.teleport(target);// TODO: schedule / other measures ? + if (!player.hasPermission(Permissions.MOVING_CREATIVEFLY) && survivalFly.isEnabled(player)) { + final MovingData data = MovingData.getData(player); + // Check if the player has to be reset. + final Location target = survivalFly.checkBed(player, data); + // To cancel the event, we teleport the player. + if (target != null){ + if (noFall.isEnabled(player)){ + // Check if to deal damage. + noFall.checkDamage(player, data); + } + // Teleport. + data.teleported = target; + player.teleport(target);// TODO: schedule / other measures ? + + } } } @@ -394,11 +398,6 @@ public class MovingListener implements Listener { } else if (data.verticalFreedom > 0.001D) // Counter has run out, now reduce the vertical freedom over time. data.verticalFreedom *= 0.93D; - - if (pFrom.isOnGround()){ - data.ground = from; // pFrom.getLocation(); - } - Location newTo = null; @@ -417,10 +416,17 @@ public class MovingListener implements Listener { && cc.survivalFlyCheck && !NCPExemptionManager.isExempted(player, CheckType.MOVING_SURVIVALFLY) && !player.hasPermission(Permissions.MOVING_SURVIVALFLY)){ // If he is handled by the survival fly check, execute it. newTo = survivalFly.check(player, mcPlayer, pFrom, pTo, data, cc); - // If don't have a new location and if he is handled by the no fall check, execute it. - if (newTo == null && cc.noFallCheck && !NCPExemptionManager.isExempted(player, CheckType.MOVING_NOFALL) && !player.hasPermission(Permissions.MOVING_NOFALL)) - // NOTE: noFall might set yOnGround for the positions. - noFall.check(player, pFrom, pTo, data, cc); + // Check NoFall if no reset is done. + if (cc.noFallCheck && !NCPExemptionManager.isExempted(player, CheckType.MOVING_NOFALL) && !player.hasPermission(Permissions.MOVING_NOFALL)) { + if (newTo == null) { + // NOTE: noFall might set yOnGround for the positions. + noFall.check(player, pFrom, pTo, data, cc); + } + else{ + // Deal damage if necessary. + noFall.checkDamage(player, data); + } + } } else if (cc.creativeFlyCheck && !NCPExemptionManager.isExempted(player, CheckType.MOVING_CREATIVEFLY)){ // If the player is handled by the creative fly check, execute it. @@ -601,7 +607,6 @@ public class MovingListener implements Listener { data.clearMorePacketsData(); if (survivalFly.isEnabled(player)) { data.setBack = event.getRespawnLocation(); - data.ground = event.getRespawnLocation(); } } @@ -615,6 +620,7 @@ public class MovingListener implements Listener { final MovingData data = MovingData.getData(player); data.clearFlyData(); data.clearMorePacketsData(); + data.setBack = player.getLocation(); // TODO: Monitor this change (!). } /** diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/NoFall.java b/src/fr/neatmonster/nocheatplus/checks/moving/NoFall.java index f5fdcf2f..4bc2e58e 100644 --- a/src/fr/neatmonster/nocheatplus/checks/moving/NoFall.java +++ b/src/fr/neatmonster/nocheatplus/checks/moving/NoFall.java @@ -64,19 +64,23 @@ public class NoFall extends Check { // Damage to be dealt. // TODO: more effects like sounds, maybe use custom event with violation added. if (cc.debug) System.out.println(mcPlayer.name + " NoFall deal damage: " + maxD); - final EntityDamageEvent event = new EntityDamageEvent(mcPlayer.getBukkitEntity(), DamageCause.FALL, maxD); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()){ - mcPlayer.damageEntity(DamageSource.FALL, event.getDamage()); - } - // TODO: let this be done by the damage event (!). -// data.clearNoFallData(); // -> currently done in the damage eventhandling method. - mcPlayer.fallDistance = 0; + dealFallDamage(mcPlayer, maxD); } else data.clearNoFallData(); } - /** + private static void dealFallDamage(EntityPlayer mcPlayer, int damage) { + final EntityDamageEvent event = new EntityDamageEvent(mcPlayer.getBukkitEntity(), DamageCause.FALL, damage); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()){ + mcPlayer.damageEntity(DamageSource.FALL, event.getDamage()); + } + // TODO: let this be done by the damage event (!). +// data.clearNoFallData(); // -> currently done in the damage eventhandling method. + mcPlayer.fallDistance = 0; + } + + /** * Checks a player. * * @param player @@ -90,6 +94,8 @@ public class NoFall extends Check { final double fromY = from.getY(); final double toY = to.getY(); + + // TODO: account for player.getLocation.getY (how exactly ?) final double yDiff = toY - fromY; // Adapt yOnGround if necessary (sf uses another setting). @@ -182,5 +188,37 @@ public class NoFall extends Check { parameters.put(ParameterName.FALL_DISTANCE, String.format(Locale.US, "%.2f", MovingData.getData(violationData.player).noFallFallDistance)); return parameters; } + + /** + * This is called if a player fails a check and gets set back, to avoid using that to avoid fall damage the player might be dealt damage here. + * @param player + * @param data + */ + public void checkDamage(final Player player, final MovingData data) { + final MovingConfig cc = MovingConfig.getConfig(player); + // Get the max difference for fall distance. + final float fallDistance = player.getFallDistance(); + final float yDiff = (float) (data.noFallMaxY - player.getLocation().getY()); + final double maxDiff = Math.max(yDiff, Math.max(data.noFallFallDistance, fallDistance)); + // Calculate damage that would be dealt (plus return if none). + final int damage = NoFall.getDamage((float) maxDiff); + if (damage <= 0) return; +// // Heuristic check for if damage would count at all. +// final long fDamage = BlockProperties.F_GROUND | BlockProperties.F_SOLID | BlockProperties.F_STAIRS | BlockProperties.F_LAVA; +// final long fNoDamage = BlockProperties.F_LIQUID; // Checked second. +// final IBlockAccess access = ((CraftWorld) player.getWorld()).getHandle(); +// final Location loc = player.getLocation(); +// final int x = loc.getBlockX(); +// final int y = loc.getBlockY(); +// final int z = loc.getBlockZ(); +// while (y > 0){ +// +// } +// // TODO + + // Deal damage. + if (cc.debug) System.out.println(player.getName() + " NoFall deal damage (violation): " + damage); + dealFallDamage(((CraftPlayer) player).getHandle(), damage); + } } diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java b/src/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java index f4a04fed..cf0890e2 100644 --- a/src/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java +++ b/src/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java @@ -62,29 +62,38 @@ public class SurvivalFly extends Check { super(CheckType.MOVING_SURVIVALFLY); } - /** - * Checks a player. - * - * @param player - * the player - * @return true, if successful - */ - public boolean check(final Player player) { - final MovingData data = MovingData.getData(player); + /** + * Checks a player. + * + * @param player + * the player + * @return Location to teleport to if it is a violation. + */ + public Location checkBed(final Player player, final MovingData data) { + Location newTo = null; + // Check if the player had been in bed at all. + if (!data.sfWasInBed) { + // Violation ... + data.survivalFlyVL += 100D; + - // Check if the player has entered the bed he is trying to leave. - if (!data.sfWasInBed) { - // He hasn't, increment his violation level. - data.survivalFlyVL += 100D; - - // And return if we need to do something or not. - return executeActions(player, data.survivalFlyVL, 100D, MovingConfig.getConfig(player).survivalFlyActions); - } else - // He has, everything is alright. - data.sfWasInBed = false; - - return false; - } + // And return if we need to do something or not. + if (executeActions(player, data.survivalFlyVL, 100D, MovingConfig.getConfig(player).survivalFlyActions)){ + final Location loc = player.getLocation(); + newTo = data.setBack; + if (newTo == null){ + // TODO: Add something to guess the best set back location (possibly data.guessSetBack(Location)). + newTo = loc; + } + newTo.setPitch(loc.getPitch()); + newTo.setYaw(loc.getYaw()); + } + } else{ + // He has, everything is alright. + data.sfWasInBed = false; + } + return newTo; + } /** * Checks a player.