From 867ad1519ae561284fe6f16c6250f825c85f4791 Mon Sep 17 00:00:00 2001 From: Alexander Noyle Date: Wed, 22 Jul 2026 19:27:04 -0400 Subject: [PATCH 1/3] Relax instant bow timing threshold --- .../checks/inventory/InstantBow.java | 220 +++++++++--------- 1 file changed, 110 insertions(+), 110 deletions(-) diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/inventory/InstantBow.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/inventory/InstantBow.java index f8b957c66..baf0b43c2 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/inventory/InstantBow.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/inventory/InstantBow.java @@ -1,110 +1,110 @@ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package fr.neatmonster.nocheatplus.checks.inventory; - -import org.bukkit.ChatColor; -import org.bukkit.entity.Player; - -import fr.neatmonster.nocheatplus.checks.Check; -import fr.neatmonster.nocheatplus.checks.CheckType; -import fr.neatmonster.nocheatplus.permissions.Permissions; -import fr.neatmonster.nocheatplus.players.DataManager; -import fr.neatmonster.nocheatplus.players.IPlayerData; -import fr.neatmonster.nocheatplus.utilities.TickTask; - -/** - * The InstantBow check will find out if a player pulled the string of their bow too fast. - */ -public class InstantBow extends Check { - - private static final float maxTime = 800f; - - /** - * Instantiates a new instant bow check. - */ - public InstantBow() { - super(CheckType.INVENTORY_INSTANTBOW); - } - - /** - * Checks a player. - * - * @param player - * the player - * @param force - * the force - * @return true, if successful - */ - public boolean check(final Player player, final float force, final long now) { - - final IPlayerData pData = DataManager.getPlayerData(player); - final InventoryData data = pData.getGenericInstance(InventoryData.class); - final InventoryConfig cc = pData.getGenericInstance(InventoryConfig.class); - - boolean cancel = false; - - // Rough estimation of how long pulling the string should've taken. - final long expectedPullDuration = (long) (maxTime - maxTime * (1f - force) * (1f - force)) - cc.instantBowDelay; - - // Time taken to pull the string. - final long pullDuration; - final boolean valid; - if (cc.instantBowStrict) { - // The interact time is invalid, if set to 0. - valid = data.instantBowInteract != 0; - pullDuration = valid ? (now - data.instantBowInteract) : 0L; - } else { - valid = true; - pullDuration = now - data.instantBowShoot; - } - - if (valid && (!cc.instantBowStrict || data.instantBowInteract > 0L) && pullDuration >= expectedPullDuration) { - // The player was slow enough, reward them by lowering their violation level. - data.instantBowVL *= 0.9D; - } - else if (valid && data.instantBowInteract > now) { - // Security check if time ran backwards. - // TODO: Maybe this can be removed, though TickTask does not reset at the exact moment. - } - else { - // Account for server side lag. - // (Do not apply correction to invalid pulling.) - final long correctedPullduration = valid ? - (pData.getCurrentWorldData().shouldAdjustToLag(type) - ? (long) (TickTask.getLag(expectedPullDuration, true) * pullDuration) - : pullDuration) : 0; - if (correctedPullduration < expectedPullDuration) { - // TODO: Consider: Allow one time but set yawrate penalty time ? - final double difference = (expectedPullDuration - pullDuration) / 100D; - - // Player was too fast, increase their violation level. - data.instantBowVL += difference; - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, data.instantBowVL, difference, cc.instantBowActions).willCancel(); - } - } - - if (pData.isDebugActive(type) && pData.hasPermission(Permissions.ADMINISTRATION_DEBUG, player)) { - player.sendMessage(ChatColor.YELLOW + "NCP: " + ChatColor.GRAY + "Bow shot - force: " + force +", " + (cc.instantBowStrict || pullDuration < 2 * expectedPullDuration ? ("pull time: " + pullDuration) : "") + "(" + expectedPullDuration +")"); - } - - // Reset data here. - data.instantBowInteract = 0; - data.instantBowShoot = now; - return cancel; - } -} +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package fr.neatmonster.nocheatplus.checks.inventory; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckType; +import fr.neatmonster.nocheatplus.permissions.Permissions; +import fr.neatmonster.nocheatplus.players.DataManager; +import fr.neatmonster.nocheatplus.players.IPlayerData; +import fr.neatmonster.nocheatplus.utilities.TickTask; + +/** + * The InstantBow check will find out if a player pulled the string of their bow too fast. + */ +public class InstantBow extends Check { + + private static final float maxTime = 750f; + + /** + * Instantiates a new instant bow check. + */ + public InstantBow() { + super(CheckType.INVENTORY_INSTANTBOW); + } + + /** + * Checks a player. + * + * @param player + * the player + * @param force + * the force + * @return true, if successful + */ + public boolean check(final Player player, final float force, final long now) { + + final IPlayerData pData = DataManager.getPlayerData(player); + final InventoryData data = pData.getGenericInstance(InventoryData.class); + final InventoryConfig cc = pData.getGenericInstance(InventoryConfig.class); + + boolean cancel = false; + + // Rough estimation of how long pulling the string should've taken. + final long expectedPullDuration = (long) (maxTime - maxTime * (1f - force) * (1f - force)) - cc.instantBowDelay; + + // Time taken to pull the string. + final long pullDuration; + final boolean valid; + if (cc.instantBowStrict) { + // The interact time is invalid, if set to 0. + valid = data.instantBowInteract != 0; + pullDuration = valid ? (now - data.instantBowInteract) : 0L; + } else { + valid = true; + pullDuration = now - data.instantBowShoot; + } + + if (valid && (!cc.instantBowStrict || data.instantBowInteract > 0L) && pullDuration >= expectedPullDuration) { + // The player was slow enough, reward them by lowering their violation level. + data.instantBowVL *= 0.9D; + } + else if (valid && data.instantBowInteract > now) { + // Security check if time ran backwards. + // TODO: Maybe this can be removed, though TickTask does not reset at the exact moment. + } + else { + // Account for server side lag. + // (Do not apply correction to invalid pulling.) + final long correctedPullduration = valid ? + (pData.getCurrentWorldData().shouldAdjustToLag(type) + ? (long) (TickTask.getLag(expectedPullDuration, true) * pullDuration) + : pullDuration) : 0; + if (correctedPullduration < expectedPullDuration) { + // TODO: Consider: Allow one time but set yawrate penalty time ? + final double difference = (expectedPullDuration - pullDuration) / 100D; + + // Player was too fast, increase their violation level. + data.instantBowVL += difference; + + // Execute whatever actions are associated with this check and the + // violation level and find out if we should cancel the event + cancel = executeActions(player, data.instantBowVL, difference, cc.instantBowActions).willCancel(); + } + } + + if (pData.isDebugActive(type) && pData.hasPermission(Permissions.ADMINISTRATION_DEBUG, player)) { + player.sendMessage(ChatColor.YELLOW + "NCP: " + ChatColor.GRAY + "Bow shot - force: " + force +", " + (cc.instantBowStrict || pullDuration < 2 * expectedPullDuration ? ("pull time: " + pullDuration) : "") + "(" + expectedPullDuration +")"); + } + + // Reset data here. + data.instantBowInteract = 0; + data.instantBowShoot = now; + return cancel; + } +} -- 2.47.3 From 507eca9ad77d44af796828d9bc24b74c4b54c1c6 Mon Sep 17 00:00:00 2001 From: Alexander Noyle Date: Wed, 22 Jul 2026 19:27:42 -0400 Subject: [PATCH 2/3] Allow double-speed creative flight --- .../nocheatplus/checks/moving/model/ModelFlying.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/model/ModelFlying.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/model/ModelFlying.java index 146dd0e1f..81f393428 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/model/ModelFlying.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/model/ModelFlying.java @@ -69,7 +69,7 @@ public class ModelFlying { */ private boolean scaleSlowfallingEffect = false; - /** + /** * Allow an extra amount to ascend speed, scaling with the riptiding effect * level. */ @@ -118,6 +118,14 @@ public class ModelFlying { scaleLevitationEffect(defaults.getScaleLevitationEffect()); // Config? scaleSlowfallingEffect(defaults.getScaleSlowfallingEffect()); scaleRiptidingEffect(defaults.getScaleRiptidingEffect()); + + // Only the resolved creative game-mode model gets the extra allowance. + // The first creative model is the defaults template; doubling that would + // also leak into survival/adventure allow-flight models. + if ("gamemode.creative".equals(id) && defaults.getId() != null) { + horizontalModSpeed(horizontalModSpeed * 2.0); + verticalAscendModSpeed(verticalAscendModSpeed * 2.0); + } } /** @@ -216,7 +224,6 @@ public class ModelFlying { return scaleRiptidingEffect; } - public ModelFlying horizontalModSpeed(double horizontalModSpeed) { checkLocked(); this.horizontalModSpeed = horizontalModSpeed; -- 2.47.3 From a863f54a0016c8ce89125af620fbee47647c67a1 Mon Sep 17 00:00:00 2001 From: Alexander Noyle Date: Wed, 22 Jul 2026 19:32:05 -0400 Subject: [PATCH 3/3] Preserve InstantBow line endings --- .../checks/inventory/InstantBow.java | 220 +++++++++--------- 1 file changed, 110 insertions(+), 110 deletions(-) diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/inventory/InstantBow.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/inventory/InstantBow.java index baf0b43c2..2db87d845 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/inventory/InstantBow.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/inventory/InstantBow.java @@ -1,110 +1,110 @@ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package fr.neatmonster.nocheatplus.checks.inventory; - -import org.bukkit.ChatColor; -import org.bukkit.entity.Player; - -import fr.neatmonster.nocheatplus.checks.Check; -import fr.neatmonster.nocheatplus.checks.CheckType; -import fr.neatmonster.nocheatplus.permissions.Permissions; -import fr.neatmonster.nocheatplus.players.DataManager; -import fr.neatmonster.nocheatplus.players.IPlayerData; -import fr.neatmonster.nocheatplus.utilities.TickTask; - -/** - * The InstantBow check will find out if a player pulled the string of their bow too fast. - */ -public class InstantBow extends Check { - - private static final float maxTime = 750f; - - /** - * Instantiates a new instant bow check. - */ - public InstantBow() { - super(CheckType.INVENTORY_INSTANTBOW); - } - - /** - * Checks a player. - * - * @param player - * the player - * @param force - * the force - * @return true, if successful - */ - public boolean check(final Player player, final float force, final long now) { - - final IPlayerData pData = DataManager.getPlayerData(player); - final InventoryData data = pData.getGenericInstance(InventoryData.class); - final InventoryConfig cc = pData.getGenericInstance(InventoryConfig.class); - - boolean cancel = false; - - // Rough estimation of how long pulling the string should've taken. - final long expectedPullDuration = (long) (maxTime - maxTime * (1f - force) * (1f - force)) - cc.instantBowDelay; - - // Time taken to pull the string. - final long pullDuration; - final boolean valid; - if (cc.instantBowStrict) { - // The interact time is invalid, if set to 0. - valid = data.instantBowInteract != 0; - pullDuration = valid ? (now - data.instantBowInteract) : 0L; - } else { - valid = true; - pullDuration = now - data.instantBowShoot; - } - - if (valid && (!cc.instantBowStrict || data.instantBowInteract > 0L) && pullDuration >= expectedPullDuration) { - // The player was slow enough, reward them by lowering their violation level. - data.instantBowVL *= 0.9D; - } - else if (valid && data.instantBowInteract > now) { - // Security check if time ran backwards. - // TODO: Maybe this can be removed, though TickTask does not reset at the exact moment. - } - else { - // Account for server side lag. - // (Do not apply correction to invalid pulling.) - final long correctedPullduration = valid ? - (pData.getCurrentWorldData().shouldAdjustToLag(type) - ? (long) (TickTask.getLag(expectedPullDuration, true) * pullDuration) - : pullDuration) : 0; - if (correctedPullduration < expectedPullDuration) { - // TODO: Consider: Allow one time but set yawrate penalty time ? - final double difference = (expectedPullDuration - pullDuration) / 100D; - - // Player was too fast, increase their violation level. - data.instantBowVL += difference; - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, data.instantBowVL, difference, cc.instantBowActions).willCancel(); - } - } - - if (pData.isDebugActive(type) && pData.hasPermission(Permissions.ADMINISTRATION_DEBUG, player)) { - player.sendMessage(ChatColor.YELLOW + "NCP: " + ChatColor.GRAY + "Bow shot - force: " + force +", " + (cc.instantBowStrict || pullDuration < 2 * expectedPullDuration ? ("pull time: " + pullDuration) : "") + "(" + expectedPullDuration +")"); - } - - // Reset data here. - data.instantBowInteract = 0; - data.instantBowShoot = now; - return cancel; - } -} +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package fr.neatmonster.nocheatplus.checks.inventory; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckType; +import fr.neatmonster.nocheatplus.permissions.Permissions; +import fr.neatmonster.nocheatplus.players.DataManager; +import fr.neatmonster.nocheatplus.players.IPlayerData; +import fr.neatmonster.nocheatplus.utilities.TickTask; + +/** + * The InstantBow check will find out if a player pulled the string of their bow too fast. + */ +public class InstantBow extends Check { + + private static final float maxTime = 750f; + + /** + * Instantiates a new instant bow check. + */ + public InstantBow() { + super(CheckType.INVENTORY_INSTANTBOW); + } + + /** + * Checks a player. + * + * @param player + * the player + * @param force + * the force + * @return true, if successful + */ + public boolean check(final Player player, final float force, final long now) { + + final IPlayerData pData = DataManager.getPlayerData(player); + final InventoryData data = pData.getGenericInstance(InventoryData.class); + final InventoryConfig cc = pData.getGenericInstance(InventoryConfig.class); + + boolean cancel = false; + + // Rough estimation of how long pulling the string should've taken. + final long expectedPullDuration = (long) (maxTime - maxTime * (1f - force) * (1f - force)) - cc.instantBowDelay; + + // Time taken to pull the string. + final long pullDuration; + final boolean valid; + if (cc.instantBowStrict) { + // The interact time is invalid, if set to 0. + valid = data.instantBowInteract != 0; + pullDuration = valid ? (now - data.instantBowInteract) : 0L; + } else { + valid = true; + pullDuration = now - data.instantBowShoot; + } + + if (valid && (!cc.instantBowStrict || data.instantBowInteract > 0L) && pullDuration >= expectedPullDuration) { + // The player was slow enough, reward them by lowering their violation level. + data.instantBowVL *= 0.9D; + } + else if (valid && data.instantBowInteract > now) { + // Security check if time ran backwards. + // TODO: Maybe this can be removed, though TickTask does not reset at the exact moment. + } + else { + // Account for server side lag. + // (Do not apply correction to invalid pulling.) + final long correctedPullduration = valid ? + (pData.getCurrentWorldData().shouldAdjustToLag(type) + ? (long) (TickTask.getLag(expectedPullDuration, true) * pullDuration) + : pullDuration) : 0; + if (correctedPullduration < expectedPullDuration) { + // TODO: Consider: Allow one time but set yawrate penalty time ? + final double difference = (expectedPullDuration - pullDuration) / 100D; + + // Player was too fast, increase their violation level. + data.instantBowVL += difference; + + // Execute whatever actions are associated with this check and the + // violation level and find out if we should cancel the event + cancel = executeActions(player, data.instantBowVL, difference, cc.instantBowActions).willCancel(); + } + } + + if (pData.isDebugActive(type) && pData.hasPermission(Permissions.ADMINISTRATION_DEBUG, player)) { + player.sendMessage(ChatColor.YELLOW + "NCP: " + ChatColor.GRAY + "Bow shot - force: " + force +", " + (cc.instantBowStrict || pullDuration < 2 * expectedPullDuration ? ("pull time: " + pullDuration) : "") + "(" + expectedPullDuration +")"); + } + + // Reset data here. + data.instantBowInteract = 0; + data.instantBowShoot = now; + return cancel; + } +} -- 2.47.3