From 770ad0ff91a990c15d9ab4babe647f852a99b1f4 Mon Sep 17 00:00:00 2001 From: Ic3Tank <61137113+IceTank@users.noreply.github.com> Date: Thu, 27 Nov 2025 22:16:37 +0100 Subject: [PATCH 1/4] Add more freecam features --- .../lambda/module/modules/player/Freecam.kt | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt b/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt index a0a73c212..ef94ee26a 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt @@ -26,6 +26,7 @@ import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.interaction.request.rotating.Rotation import com.lambda.interaction.request.rotating.RotationConfig import com.lambda.interaction.request.rotating.RotationMode +import com.lambda.interaction.request.rotating.visibilty.lookAt import com.lambda.interaction.request.rotating.visibilty.lookAtHit import com.lambda.module.Module import com.lambda.module.tag.ModuleTag @@ -55,11 +56,16 @@ object Freecam : Module( private val speed by setting("Speed", 0.5, 0.1..1.0, 0.1) private val sprint by setting("Sprint Multiplier", 3.0, 0.1..10.0, 0.1, description = "Set below 1.0 to fly slower on sprint.") private val reach by setting("Reach", 10.0, 1.0..100.0, 1.0, "Freecam reach distance") - private val rotateToTarget by setting("Rotate to target", true) + private val rotateMode by setting("Rotate Mode", FreecamRotationMode.None, "Rotation mode") + private val relative by setting("Relative", false, "Moves freecam relative to player position").onValueChange { _, it -> + if (it) lastPlayerPosition = player.pos + } + private val keepYLevel by setting("Keep Y Level", false, "Don't change the camera y-level on player movement", { relative }) override val rotationConfig = RotationConfig.Instant(RotationMode.Lock) private var lastPerspective = Perspective.FIRST_PERSON + private var lastPlayerPosition: Vec3d = Vec3d.ZERO private var prevPosition: Vec3d = Vec3d.ZERO private var position: Vec3d = Vec3d.ZERO private val lerpPos: Vec3d @@ -90,6 +96,7 @@ object Freecam : Module( position = player.eyePos rotation = player.rotation velocity = Vec3d.ZERO + lastPlayerPosition = player.pos } onDisable { @@ -97,10 +104,16 @@ object Freecam : Module( } listen { - if (!rotateToTarget) return@listen - - mc.crosshairTarget?.let { - lookAtHit(it)?.requestBy(this@Freecam) + when (rotateMode) { + FreecamRotationMode.None -> return@listen + FreecamRotationMode.KeepRotation -> { + lookAt(rotation).requestBy(this@Freecam) + } + FreecamRotationMode.LookAtTarget -> { + mc.crosshairTarget?.let { + lookAtHit(it)?.requestBy(this@Freecam) + } + } } } @@ -135,6 +148,12 @@ object Freecam : Module( // Update position prevPosition = position position += velocity + + if (relative) { + val delta = player.pos.subtract(lastPlayerPosition) + position += if (keepYLevel) Vec3d(delta.x, 0.0, delta.z) else delta + lastPlayerPosition = player.pos + } } listen { @@ -145,4 +164,10 @@ object Freecam : Module( .orMiss // Can't be null (otherwise mc will spam "Null returned as 'hitResult', this shouldn't happen!") } } + + enum class FreecamRotationMode { + None, + LookAtTarget, + KeepRotation + } } From 4a96e37532a49d0d85a3d4b322fa7c7a24411502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emy=20=F0=9F=92=9C?= Date: Thu, 27 Nov 2025 16:39:10 -0500 Subject: [PATCH 2/4] nit --- .../com/lambda/module/modules/player/Freecam.kt | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt b/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt index ef94ee26a..ff5d4af6d 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt @@ -60,7 +60,7 @@ object Freecam : Module( private val relative by setting("Relative", false, "Moves freecam relative to player position").onValueChange { _, it -> if (it) lastPlayerPosition = player.pos } - private val keepYLevel by setting("Keep Y Level", false, "Don't change the camera y-level on player movement", { relative }) + private val keepYLevel by setting("Keep Y Level", false, "Don't change the camera y-level on player movement") { relative } override val rotationConfig = RotationConfig.Instant(RotationMode.Lock) @@ -106,14 +106,8 @@ object Freecam : Module( listen { when (rotateMode) { FreecamRotationMode.None -> return@listen - FreecamRotationMode.KeepRotation -> { - lookAt(rotation).requestBy(this@Freecam) - } - FreecamRotationMode.LookAtTarget -> { - mc.crosshairTarget?.let { - lookAtHit(it)?.requestBy(this@Freecam) - } - } + FreecamRotationMode.KeepRotation -> lookAt(rotation).requestBy(this@Freecam) + FreecamRotationMode.LookAtTarget -> mc.crosshairTarget?.let { lookAtHit(it)?.requestBy(this@Freecam) } } } From f1c78e10851780c615ddc9062af9ebd86600ab5a Mon Sep 17 00:00:00 2001 From: Ic3Tank <61137113+IceTank@users.noreply.github.com> Date: Thu, 27 Nov 2025 23:45:37 +0100 Subject: [PATCH 3/4] Update setting descriptions --- .../kotlin/com/lambda/module/modules/player/Freecam.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt b/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt index ff5d4af6d..ec200ad7a 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt @@ -53,7 +53,7 @@ object Freecam : Module( tag = ModuleTag.PLAYER, autoDisable = true, ) { - private val speed by setting("Speed", 0.5, 0.1..1.0, 0.1) + private val speed by setting("Speed", 0.5, 0.1..1.0, 0.1, "Freecam movement speed", unit = "m/s") private val sprint by setting("Sprint Multiplier", 3.0, 0.1..10.0, 0.1, description = "Set below 1.0 to fly slower on sprint.") private val reach by setting("Reach", 10.0, 1.0..100.0, 1.0, "Freecam reach distance") private val rotateMode by setting("Rotate Mode", FreecamRotationMode.None, "Rotation mode") @@ -159,9 +159,9 @@ object Freecam : Module( } } - enum class FreecamRotationMode { - None, - LookAtTarget, - KeepRotation + enum class FreecamRotationMode(override val displayName: String, override val description: String) : NamedEnum, Describable { + None("None", "No rotation changes"), + LookAtTarget("Look At Target", "Look at the block or entity under your crosshair"), + KeepRotation("Keep Rotation", "Look in the same direction as the camera"); } } From 169308d1e61f196e158744b2c3dd6516714bdc77 Mon Sep 17 00:00:00 2001 From: Ic3Tank <61137113+IceTank@users.noreply.github.com> Date: Thu, 27 Nov 2025 23:46:36 +0100 Subject: [PATCH 4/4] - Make rotations for looking at target smooth - Fix LookAtTarget not working due to conflict with RotationManager --- .../rotating/visibilty/RotationTargets.kt | 12 +++++++++ .../lambda/module/modules/player/Freecam.kt | 27 ++++++++++++++----- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/com/lambda/interaction/request/rotating/visibilty/RotationTargets.kt b/src/main/kotlin/com/lambda/interaction/request/rotating/visibilty/RotationTargets.kt index 0ffdb6cea..0cc60f7bb 100644 --- a/src/main/kotlin/com/lambda/interaction/request/rotating/visibilty/RotationTargets.kt +++ b/src/main/kotlin/com/lambda/interaction/request/rotating/visibilty/RotationTargets.kt @@ -34,6 +34,9 @@ import net.minecraft.util.hit.EntityHitResult import net.minecraft.util.hit.HitResult import net.minecraft.util.math.BlockPos import net.minecraft.util.math.Direction +import net.minecraft.util.math.Vec3d +import kotlin.math.atan2 +import kotlin.math.hypot @DslMarker annotation class RotationDsl @@ -51,6 +54,15 @@ fun lookAt(angle: Rotation, maxAngleDistance: Double = 0.001) = RotationManager.activeRotation dist angle < maxAngleDistance }) { angle } +@RotationDsl +fun lookAt(pos: Vec3d) = + RotationTarget(null) { + val direction = pos.subtract(player.eyePos).normalize() + val yaw = Math.toDegrees(atan2(direction.z, direction.x)) - 90.0 + val pitch = -Math.toDegrees(atan2(direction.y, hypot(direction.x, direction.z))) + Rotation(yaw, pitch) + } + @RotationDsl fun lookInDirection(direction: PlaceDirection) = RotationTarget(null, { diff --git a/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt b/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt index ec200ad7a..a7d39f876 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt @@ -30,6 +30,8 @@ import com.lambda.interaction.request.rotating.visibilty.lookAt import com.lambda.interaction.request.rotating.visibilty.lookAtHit import com.lambda.module.Module import com.lambda.module.tag.ModuleTag +import com.lambda.util.Describable +import com.lambda.util.NamedEnum import com.lambda.util.extension.rotation import com.lambda.util.math.interpolate import com.lambda.util.math.plus @@ -45,6 +47,10 @@ import com.lambda.util.player.MovementUtils.roundedStrafing import com.lambda.util.player.MovementUtils.verticalMovement import com.lambda.util.world.raycast.RayCastUtils.orMiss import net.minecraft.client.option.Perspective +import net.minecraft.util.hit.BlockHitResult +import net.minecraft.util.hit.HitResult +import net.minecraft.util.math.BlockPos +import net.minecraft.util.math.Direction import net.minecraft.util.math.Vec3d object Freecam : Module( @@ -57,9 +63,9 @@ object Freecam : Module( private val sprint by setting("Sprint Multiplier", 3.0, 0.1..10.0, 0.1, description = "Set below 1.0 to fly slower on sprint.") private val reach by setting("Reach", 10.0, 1.0..100.0, 1.0, "Freecam reach distance") private val rotateMode by setting("Rotate Mode", FreecamRotationMode.None, "Rotation mode") - private val relative by setting("Relative", false, "Moves freecam relative to player position").onValueChange { _, it -> - if (it) lastPlayerPosition = player.pos - } + .onValueChange { _, it -> if (it == FreecamRotationMode.LookAtTarget) mc.crosshairTarget = BlockHitResult.createMissed(Vec3d.ZERO, Direction.UP, BlockPos.ORIGIN) } + private val relative by setting("Relative", false, "Moves freecam relative to player position") + .onValueChange { _, it -> if (it) lastPlayerPosition = player.pos } private val keepYLevel by setting("Keep Y Level", false, "Don't change the camera y-level on player movement") { relative } override val rotationConfig = RotationConfig.Instant(RotationMode.Lock) @@ -107,7 +113,14 @@ object Freecam : Module( when (rotateMode) { FreecamRotationMode.None -> return@listen FreecamRotationMode.KeepRotation -> lookAt(rotation).requestBy(this@Freecam) - FreecamRotationMode.LookAtTarget -> mc.crosshairTarget?.let { lookAtHit(it)?.requestBy(this@Freecam) } + FreecamRotationMode.LookAtTarget -> + mc.crosshairTarget?.let { + when (it) { + is BlockHitResult -> lookAt(it.pos).requestBy(this@Freecam) + else -> lookAtHit(it)?.requestBy(this@Freecam) + + } + } } } @@ -150,12 +163,12 @@ object Freecam : Module( } } - listen { - it.cancel() - + listen(priority = 1) { event -> // Higher priority then RotationManager to run before RotationManager modifies mc.crosshairTarget mc.crosshairTarget = rotation .rayCast(reach, lerpPos) .orMiss // Can't be null (otherwise mc will spam "Null returned as 'hitResult', this shouldn't happen!") + + mc.crosshairTarget?.let { if (it.type != HitResult.Type.MISS) event.cancel() } } }