diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingConfig.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingConfig.java index c6426d7a..cca54e6a 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingConfig.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingConfig.java @@ -14,6 +14,7 @@ import fr.neatmonster.nocheatplus.checks.access.ICheckConfig; import fr.neatmonster.nocheatplus.command.CommandUtil; import fr.neatmonster.nocheatplus.compat.AlmostBoolean; import fr.neatmonster.nocheatplus.compat.versions.Bugs; +import fr.neatmonster.nocheatplus.compat.versions.ServerVersion; import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfigFile; import fr.neatmonster.nocheatplus.config.ConfigManager; @@ -131,6 +132,7 @@ public class MovingConfig extends ACheckConfig { public final boolean survivalFlyAccountingH; public final boolean survivalFlyAccountingV; public final boolean sfFallDamage; + public final boolean sfBedStep; public final long survivalFlyVLFreeze; public final ActionList survivalFlyActions; @@ -228,6 +230,12 @@ public class MovingConfig extends ACheckConfig { survivalFlyAccountingH = config.getBoolean(ConfPaths.MOVING_SURVIVALFLY_EXTENDED_HACC, false); survivalFlyAccountingV = config.getBoolean(ConfPaths.MOVING_SURVIVALFLY_EXTENDED_VACC); sfFallDamage = config.getBoolean(ConfPaths.MOVING_SURVIVALFLY_FALLDAMAGE); + AlmostBoolean bedStep = config.getAlmostBoolean(ConfPaths.MOVING_SURVIVALFLY_BEDSTEP, AlmostBoolean.MAYBE); + if (bedStep == AlmostBoolean.MAYBE) { + sfBedStep = ServerVersion.select("1.8", false, true, true, true); + } else { + sfBedStep = bedStep.decide(); + } survivalFlyVLFreeze = config.getLong(ConfPaths.MOVING_SURVIVALFLY_VLFREEZE, 2000L); survivalFlyActions = config.getOptimizedActionList(ConfPaths.MOVING_SURVIVALFLY_ACTIONS, Permissions.MOVING_SURVIVALFLY); diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java index da071a3b..21334a32 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java @@ -6,6 +6,7 @@ import java.util.Locale; import java.util.Set; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; @@ -391,9 +392,21 @@ public class SurvivalFly extends Check { // Simple-step blocker. // TODO: Complex step blocker: distance to set-back + low jump + accounting info if ((resetFrom || data.noFallAssumeGround) && resetTo && vDistanceAboveLimit <= 0D && - yDistance > MovingUtil.estimateJumpLiftOff(player, data, 0.1) && !player.hasPermission(Permissions.MOVING_SURVIVALFLY_STEP)) { + yDistance > MovingUtil.estimateJumpLiftOff(player, data, 0.1)) { + boolean step = true; // Exclude a lost-ground case. - if (!data.noFallAssumeGround || data.sfLastYDist == Double.MAX_VALUE || data.sfLastYDist > 0.0 || yDistance + Math.abs(data.sfLastYDist) > 2.0 * (MovingUtil.estimateJumpLiftOff(player, data, 0.1))) { + if (data.noFallAssumeGround && data.sfLastYDist != Double.MAX_VALUE && data.sfLastYDist <= 0.0 && yDistance > 0.0 && + yDistance + Math.abs(data.sfLastYDist) <= 2.0 * (MovingUtil.estimateJumpLiftOff(player, data, 0.1))) { + step = false; + } + // Exclude 1.8 beds. + // TODO: Add feature flag (bedstep) and check here. + // TODO: Quick check the distance and offset parameters (!). + if (yDistance <= 0.5625 && cc.sfBedStep && to.standsOnBlock(BlockProperties.getId(Material.BED_BLOCK))) { + step = false; + } + // Check bypass permission last. + if (step && !player.hasPermission(Permissions.MOVING_SURVIVALFLY_STEP)) { vDistanceAboveLimit = Math.max(vDistanceAboveLimit, Math.abs(from.isOnClimbable() ? yDistance : yDistance - MovingUtil.estimateJumpLiftOff(player, data, 0.1) )); // Could adjust if on ladders etc. tags.add("step"); } diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/versions/ServerVersion.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/versions/ServerVersion.java index 60c22294..24dc476a 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/versions/ServerVersion.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/versions/ServerVersion.java @@ -216,6 +216,15 @@ public class ServerVersion { return num; } + /** + * Select a value based on the Minecraft version. + * @param cmpVersion Version to compare to, comparison of server version vs. given version. + * @param valueLT Server has an earlier version. + * @param valueEQ Same versions. + * @param valueGT The server version is later. + * @param valueUnknown Value to return, if the server version could not be determined. + * @return + */ public static V select(final String cmpVersion, final V valueLT, final V valueEQ, final V valueGT, final V valueUnknown) { final String mcVersion = ServerVersion.getMinecraftVersion(); if (mcVersion == ServerVersion.UNKNOWN_VERSION) { diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/config/ConfPaths.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/config/ConfPaths.java index 78bea5f1..9ddb9130 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/config/ConfPaths.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/config/ConfPaths.java @@ -564,6 +564,7 @@ public abstract class ConfPaths { public static final String MOVING_SURVIVALFLY_EXTENDED_HACC = MOVING_SURVIVALFLY_EXTENDED + "horizontal-accounting"; public static final String MOVING_SURVIVALFLY_EXTENDED_VACC = MOVING_SURVIVALFLY_EXTENDED + "vertical-accounting"; public static final String MOVING_SURVIVALFLY_FALLDAMAGE = MOVING_SURVIVALFLY + "falldamage"; + public static final String MOVING_SURVIVALFLY_BEDSTEP = MOVING_SURVIVALFLY + "bedstep"; public static final String MOVING_SURVIVALFLY_VLFREEZE = MOVING_SURVIVALFLY + "vlfreeze"; public static final String MOVING_SURVIVALFLY_ACTIONS = MOVING_SURVIVALFLY + "actions"; diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/config/DefaultConfig.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/config/DefaultConfig.java index 436b1c3c..d4583ace 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/config/DefaultConfig.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/config/DefaultConfig.java @@ -401,6 +401,7 @@ public class DefaultConfig extends ConfigFile { // set(ConfPaths.MOVING_SURVIVALFLY_EXTENDED_HACC, false); set(ConfPaths.MOVING_SURVIVALFLY_EXTENDED_VACC, true); set(ConfPaths.MOVING_SURVIVALFLY_FALLDAMAGE, true); + set(ConfPaths.MOVING_SURVIVALFLY_BEDSTEP, "default"); // The settings aren't enabled by default. Simply write them yourself in the configuration file. // set(ConfPaths.MOVING_SURVIVALFLY_BLOCKINGSPEED, 100); // set(ConfPaths.MOVING_SURVIVALFLY_SNEAKINGSPEED, 100); diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java index de385823..6978307a 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java @@ -584,6 +584,21 @@ public class PlayerLocation { 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); + } + /** * Simple check with custom margins (Boat, Minecart). * @param yOnGround Margin below the player.