diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/client/MixinKeyboardInput.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/client/MixinKeyboardInput.java index e91e7d6fac2..2f51380e9a7 100644 --- a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/client/MixinKeyboardInput.java +++ b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/client/MixinKeyboardInput.java @@ -25,6 +25,7 @@ import net.ccbluex.liquidbounce.event.events.MovementInputEvent; import net.ccbluex.liquidbounce.event.events.SprintEvent; import net.ccbluex.liquidbounce.features.module.modules.movement.ModuleInventoryMove; +import net.ccbluex.liquidbounce.utils.aiming.MovementCorrection; import net.ccbluex.liquidbounce.utils.aiming.RotationManager; import net.ccbluex.liquidbounce.utils.input.InputTracker; import net.ccbluex.liquidbounce.utils.movement.DirectionalInput; @@ -113,7 +114,8 @@ private DirectionalInput transformDirection(DirectionalInput input) { float z = KeyboardInput.getMovementMultiplier(input.getForwards(), input.getBackwards()); float x = KeyboardInput.getMovementMultiplier(input.getLeft(), input.getRight()); - if (configurable == null || !configurable.getApplyVelocityFix() || rotation == null || player == null) { + if (configurable == null || configurable.getMovementCorrection() != MovementCorrection.SILENT + || rotation == null || player == null) { return input; } diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/entity/MixinLivingEntity.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/entity/MixinLivingEntity.java index 5fca9c5afdc..fdc7560981d 100644 --- a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/entity/MixinLivingEntity.java +++ b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/entity/MixinLivingEntity.java @@ -26,6 +26,7 @@ import net.ccbluex.liquidbounce.features.module.modules.movement.*; import net.ccbluex.liquidbounce.features.module.modules.render.ModuleAntiBlind; import net.ccbluex.liquidbounce.features.module.modules.world.scaffold.ModuleScaffold; +import net.ccbluex.liquidbounce.utils.aiming.MovementCorrection; import net.ccbluex.liquidbounce.utils.aiming.RotationManager; import net.minecraft.client.MinecraftClient; import net.minecraft.entity.LivingEntity; @@ -176,7 +177,7 @@ private Vec3d hookFixRotation(Vec3d original) { return original; } - if (configurable == null || !configurable.getApplyVelocityFix() || rotation == null) { + if (configurable == null || configurable.getMovementCorrection() == MovementCorrection.OFF || rotation == null) { return original; } @@ -248,7 +249,7 @@ private float hookModifyFallFlyingPitch(float original) { var rotation = rotationManager.getCurrentRotation(); var configurable = rotationManager.getWorkingAimPlan(); - if (rotation == null || configurable == null || !configurable.getApplyVelocityFix() || configurable.getChangeLook()) { + if (rotation == null || configurable == null || configurable.getMovementCorrection() == MovementCorrection.OFF) { return original; } @@ -268,7 +269,7 @@ private Vec3d hookModifyFallFlyingRotationVector(Vec3d original) { var rotation = rotationManager.getCurrentRotation(); var configurable = rotationManager.getWorkingAimPlan(); - if (rotation == null || configurable == null || !configurable.getApplyVelocityFix() || configurable.getChangeLook()) { + if (rotation == null || configurable == null || configurable.getMovementCorrection() == MovementCorrection.OFF) { return original; } diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/entity/MixinPlayerEntity.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/entity/MixinPlayerEntity.java index c5abd307622..0806acb85d4 100644 --- a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/entity/MixinPlayerEntity.java +++ b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/entity/MixinPlayerEntity.java @@ -35,6 +35,7 @@ import net.ccbluex.liquidbounce.features.module.modules.player.nofall.modes.NoFallNoGround; import net.ccbluex.liquidbounce.features.module.modules.world.ModuleNoSlowBreak; import net.ccbluex.liquidbounce.utils.aiming.AimPlan; +import net.ccbluex.liquidbounce.utils.aiming.MovementCorrection; import net.ccbluex.liquidbounce.utils.aiming.Rotation; import net.ccbluex.liquidbounce.utils.aiming.RotationManager; import net.minecraft.client.MinecraftClient; @@ -96,7 +97,7 @@ private float hookFixRotation(float original) { Rotation rotation = rotationManager.getCurrentRotation(); AimPlan configurable = rotationManager.getWorkingAimPlan(); - if (configurable == null || !configurable.getApplyVelocityFix() || rotation == null) { + if (configurable == null || configurable.getMovementCorrection() == MovementCorrection.OFF || rotation == null) { return original; } diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinCamera.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinCamera.java index 5e951e13b29..63252b4147b 100644 --- a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinCamera.java +++ b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinCamera.java @@ -22,6 +22,7 @@ import net.ccbluex.liquidbounce.features.module.modules.combat.aimbot.ModuleDroneControl; import net.ccbluex.liquidbounce.features.module.modules.render.*; import net.ccbluex.liquidbounce.utils.aiming.AimPlan; +import net.ccbluex.liquidbounce.utils.aiming.MovementCorrection; import net.ccbluex.liquidbounce.utils.aiming.RotationManager; import net.minecraft.client.render.Camera; import net.minecraft.entity.Entity; @@ -107,7 +108,7 @@ private void modifyCameraOrientation(BlockView area, Entity focusedEntity, boole var currentRotation = RotationManager.INSTANCE.getCurrentRotation(); boolean shouldModifyRotation = ModuleRotations.INSTANCE.getRunning() && ModuleRotations.INSTANCE.getCamera() - || aimPlan != null && aimPlan.getChangeLook(); + || aimPlan != null && aimPlan.getMovementCorrection() == MovementCorrection.CHANGE_LOOK; if (currentRotation == null || previousRotation == null || !shouldModifyRotation) { return; diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/ModuleSprint.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/ModuleSprint.kt index 4caf8e1097c..f3c0628ba5f 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/ModuleSprint.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/ModuleSprint.kt @@ -25,6 +25,7 @@ import net.ccbluex.liquidbounce.event.handler import net.ccbluex.liquidbounce.features.module.Category import net.ccbluex.liquidbounce.features.module.ClientModule import net.ccbluex.liquidbounce.features.module.modules.world.scaffold.features.ScaffoldSprintControlFeature +import net.ccbluex.liquidbounce.utils.aiming.MovementCorrection import net.ccbluex.liquidbounce.utils.aiming.Rotation import net.ccbluex.liquidbounce.utils.aiming.RotationManager import net.ccbluex.liquidbounce.utils.aiming.RotationsConfigurable @@ -121,7 +122,7 @@ object ModuleSprint : ClientModule("Sprint", Category.MOVEMENT) { MathHelper.sin(deltaYaw * 0.017453292f) > 1.0E-5 val preventSprint = (if (player.isOnGround) stopOnGround else stopOnAir) && !shouldSprintOmnidirectional - && RotationManager.workingAimPlan?.applyVelocityFix == false && !hasForwardMovement + && RotationManager.workingAimPlan?.movementCorrection == MovementCorrection.OFF && !hasForwardMovement return running && preventSprint } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/script/bindings/api/ScriptRotationUtil.kt b/src/main/kotlin/net/ccbluex/liquidbounce/script/bindings/api/ScriptRotationUtil.kt index 82dd819cb22..aa839903e29 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/script/bindings/api/ScriptRotationUtil.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/script/bindings/api/ScriptRotationUtil.kt @@ -22,10 +22,7 @@ import net.ccbluex.liquidbounce.event.EventListener import net.ccbluex.liquidbounce.features.module.Category import net.ccbluex.liquidbounce.features.module.ClientModule import net.ccbluex.liquidbounce.script.bindings.api.ScriptRotationUtil.newRotationEntity -import net.ccbluex.liquidbounce.utils.aiming.Rotation -import net.ccbluex.liquidbounce.utils.aiming.RotationManager -import net.ccbluex.liquidbounce.utils.aiming.RotationsConfigurable -import net.ccbluex.liquidbounce.utils.aiming.raytraceBox +import net.ccbluex.liquidbounce.utils.aiming.* import net.ccbluex.liquidbounce.utils.client.mc import net.ccbluex.liquidbounce.utils.kotlin.Priority import net.minecraft.entity.Entity @@ -91,10 +88,9 @@ object ScriptRotationUtil { RotationManager.aimAt( rotation, configurable = RotationsConfigurable( - object : EventListener { } - ).also { - it.fixVelocity = fixVelocity - }, priority = Priority.NORMAL, provider = ClientModule("ScriptAPI", Category.MISC) + object : EventListener { }, + movementCorrection = if (fixVelocity) MovementCorrection.SILENT else MovementCorrection.OFF + ), priority = Priority.NORMAL, provider = ClientModule("ScriptAPI", Category.MISC) ) } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/AimPlan.kt b/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/AimPlan.kt index a84d6fed70f..a0a3bf127bd 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/AimPlan.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/AimPlan.kt @@ -54,8 +54,7 @@ class AimPlan( * Consider if the inventory is open or not. If the inventory is open, we might not want to continue updating. */ val considerInventory: Boolean, - val applyVelocityFix: Boolean, - val changeLook: Boolean, + val movementCorrection: MovementCorrection, /** * What should be done if the target rotation has been reached. Can be `null`. */ diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/MovementCorrection.kt b/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/MovementCorrection.kt new file mode 100644 index 00000000000..b4141ddcc0e --- /dev/null +++ b/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/MovementCorrection.kt @@ -0,0 +1,52 @@ +/* + * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce) + * + * Copyright (c) 2015 - 2025 CCBlueX + * + * LiquidBounce 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. + * + * LiquidBounce 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 LiquidBounce. If not, see . + */ +package net.ccbluex.liquidbounce.utils.aiming + +import net.ccbluex.liquidbounce.config.types.NamedChoice + +/** + * Corrects movement when aiming away from client-side view direction. + */ +enum class MovementCorrection(override val choiceName: String) : NamedChoice { + + /** + * No movement correction is applied. This feels the best, as it does not + * change the movement of the player and also not affects Sprinting. + * However, this can be detected by anti-cheats. + */ + OFF("Off"), + + /** + * Corrects movement by changing the yaw when updating the movement. + */ + STRICT("Strict"), + + /** + * Correct movement by changing the yaw when updating the movement, + * but also tweaks the keyboard input to not aggressively change the + * players walk direction. + */ + SILENT("Silent"), + + /** + * Corrects movement by changing the actual look direction of the player. + */ + CHANGE_LOOK("ChangeLook") + +} diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/RotationManager.kt b/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/RotationManager.kt index 5647fe17cff..b4ba50695b9 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/RotationManager.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/RotationManager.kt @@ -116,7 +116,7 @@ object RotationManager : EventListener { aimPlanHandler.request( RequestHandler.Request( - if (plan.changeLook) 1 else plan.ticksUntilReset, + if (plan.movementCorrection == MovementCorrection.CHANGE_LOOK) 1 else plan.ticksUntilReset, priority.priority, provider, plan @@ -156,7 +156,8 @@ object RotationManager : EventListener { val diff = rotation.angleTo(playerRotation) - if (aimPlan == null && (workingAimPlan.changeLook || diff <= workingAimPlan.resetThreshold)) { + if (aimPlan == null && (workingAimPlan.movementCorrection == MovementCorrection.CHANGE_LOOK + || diff <= workingAimPlan.resetThreshold)) { currentRotation?.let { currentRotation -> player.yaw = player.withFixedYaw(currentRotation) player.renderYaw = player.yaw @@ -166,7 +167,7 @@ object RotationManager : EventListener { currentRotation = null previousAimPlan = null } else { - if (workingAimPlan.changeLook) { + if (workingAimPlan.movementCorrection == MovementCorrection.CHANGE_LOOK) { player.setRotation(rotation) } @@ -198,7 +199,7 @@ object RotationManager : EventListener { @Suppress("unused") private val velocityHandler = handler { event -> - if (workingAimPlan?.applyVelocityFix == true) { + if (workingAimPlan?.movementCorrection != MovementCorrection.OFF) { val rotation = currentRotation ?: return@handler event.velocity = Entity.movementInputToVelocity( diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/RotationsConfigurable.kt b/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/RotationsConfigurable.kt index f5868e4db26..350a514d965 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/RotationsConfigurable.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/RotationsConfigurable.kt @@ -12,8 +12,7 @@ import net.minecraft.util.math.Vec3d */ open class RotationsConfigurable( owner: EventListener, - fixVelocity: Boolean = true, - changeLook: Boolean = false, + movementCorrection: MovementCorrection = MovementCorrection.SILENT, combatSpecific: Boolean = false ) : Configurable("Rotations") { @@ -31,10 +30,9 @@ open class RotationsConfigurable( private var shortStop = ShortStop(owner).takeIf { combatSpecific }?.also { tree(it) } private val failFocus = FailFocus(owner).takeIf { combatSpecific }?.also { tree(it) } - var fixVelocity by boolean("FixVelocity", fixVelocity) + private val movementCorrection by enumChoice("MovementCorrection", movementCorrection) private val resetThreshold by float("ResetThreshold", 2f, 1f..180f) private val ticksUntilReset by int("TicksUntilReset", 5, 1..30, "ticks") - private val changeLook by boolean("ChangeLook", changeLook) fun toAimPlan( rotation: Rotation, @@ -53,8 +51,7 @@ open class RotationsConfigurable( ticksUntilReset, resetThreshold, considerInventory, - fixVelocity, - changeLook, + movementCorrection, whenReached )