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 29043e980..c3f9a6879 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt @@ -20,6 +20,7 @@ package com.lambda.module.modules.player import com.lambda.Lambda.mc import com.lambda.config.AutomationConfig.Companion.setDefaultAutomationConfig import com.lambda.config.applyEdits +import com.lambda.context.AutomatedSafeContext import com.lambda.context.SafeContext import com.lambda.event.events.MovementEvent import com.lambda.event.events.PlayerEvent @@ -29,10 +30,12 @@ import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.interaction.managers.rotating.IRotationRequest.Companion.rotationRequest import com.lambda.interaction.managers.rotating.Rotation import com.lambda.interaction.managers.rotating.RotationMode +import com.lambda.interaction.managers.rotating.RotationRequest import com.lambda.interaction.managers.rotating.visibilty.lookAt import com.lambda.module.Module import com.lambda.module.tag.ModuleTag import com.lambda.threading.runSafe +import com.lambda.threading.runSafeAutomated import com.lambda.util.Describable import com.lambda.util.NamedEnum import com.lambda.util.extension.rotation @@ -76,8 +79,11 @@ object Freecam : Module( private val speed by setting("Speed", 0.5, 0.1..1.0, 0.1, "Freecam movement speed", unit = "m/s") { mode == Mode.Free } 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.") { mode == Mode.Free } 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").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") { mode == Mode.Free }.onValueChange { _, it -> if (it) lastPlayerPosition = player.pos } + private val rotateMode by setting("Rotate Mode", RotationModeFreecam.None, "Rotation mode") + .onValueChange { _, it -> if (it == RotationModeFreecam.LookAtTarget) mc.crosshairTarget = BlockHitResult.createMissed(Vec3d.ZERO, Direction.UP, BlockPos.ORIGIN) } + private val excludeRotation by setting("Exclude Rotation", FreecamRotationExclusion.None, description = "Exclude certain rotation changes from rotate mode") { rotateMode != RotationModeFreecam.None } + private val relative by setting("Relative", false, "Moves freecam relative to player position") { mode == Mode.Free } + .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") { mode == Mode.Free && relative } // Follow Player settings @@ -143,14 +149,6 @@ object Freecam : Module( mc.options.perspective = lastPerspective } - listen { - when (rotateMode) { - FreecamRotationMode.None -> return@listen - FreecamRotationMode.KeepRotation -> rotationRequest { rotation(rotation) }.submit() - FreecamRotationMode.LookAtTarget -> mc.crosshairTarget?.let { rotationRequest { rotation(lookAt(it.pos)) }.submit() } - } - } - listen { rotation = rotation.withDelta(it.deltaYaw * SENSITIVITY_FACTOR, it.deltaPitch * SENSITIVITY_FACTOR) it.cancel() @@ -227,17 +225,30 @@ object Freecam : Module( 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() } } - } - private 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"); + listen { + runSafeAutomated { + when (rotateMode) { + RotationModeFreecam.None -> null + RotationModeFreecam.KeepRotation -> rotationRequest { + buildRotationTo(rotation) + } + RotationModeFreecam.LookAtTarget -> mc.crosshairTarget?.let { rotationRequest { + buildRotationTo(lookAt(it.pos)) + } } + }?.submit() + } + } } - private enum class Mode(override val displayName: String, override val description: String) : NamedEnum, Describable { - Free("Free", "Move the camera freely with keyboard input"), - FollowPlayer("Follow Player", "Camera follows a player as if attached by an invisible string"); + private fun AutomatedSafeContext.buildRotationTo(rotation: Rotation): RotationRequest { + return rotationRequest { + when (excludeRotation) { + FreecamRotationExclusion.Pitch -> yaw(rotation.yaw) + FreecamRotationExclusion.Yaw -> pitch(rotation.pitch) + else -> rotation(rotation) + } + } } private fun SafeContext.findFollowTarget(): PlayerEntity? { @@ -247,4 +258,21 @@ object Freecam : Module( val players = world.players.filter { it !is ClientPlayerEntity } return players.minByOrNull { it.eyePos.squaredDistanceTo(position) } } + + private enum class RotationModeFreecam(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"); + } + + private enum class FreecamRotationExclusion(override val displayName: String, override val description: String) : NamedEnum, Describable { + Yaw("Yaw", "Don't change yaw"), + Pitch("Pitch", "Don't change pitch"), + None("None", "Don't exclude any rotation changes"); + } + + private enum class Mode(override val displayName: String, override val description: String) : NamedEnum, Describable { + Free("Free", "Move the camera freely with keyboard input"), + FollowPlayer("Follow Player", "Camera follows a player as if attached by an invisible string"); + } }