From bf4cfb71f89786dfdc82baf186faf3e019a62acf Mon Sep 17 00:00:00 2001 From: Constructor Date: Sat, 23 Mar 2024 08:42:12 +0100 Subject: [PATCH 1/2] Added Freecam --- .../mixin/entity/ClientPlayerEntityMixin.java | 13 +- .../mixin/input/KeyboardInputMixin.java | 17 +++ .../com/lambda/mixin/input/MouseMixin.java | 21 ++++ .../com/lambda/mixin/render/CameraMixin.java | 27 ++++ .../mixin/render/GameRendererMixin.java | 19 +++ .../mixin/render/WorldRendererMixin.java | 22 ++++ .../com/lambda/config/RotationSettings.kt | 2 +- .../com/lambda/event/events/InputEvent.kt | 5 + .../com/lambda/event/events/MovementEvent.kt | 6 + .../com/lambda/event/events/RotationEvent.kt | 2 +- .../com/lambda/interaction/RotationManager.kt | 28 ++--- .../lambda/interaction/rotation/Rotation.kt | 21 ++-- .../interaction/rotation/RotationRequest.kt | 5 +- .../visibilty/VisibilityChecker.kt | 4 +- .../main/kotlin/com/lambda/module/Module.kt | 2 +- .../lambda/module/modules/player/Freecam.kt | 119 ++++++++++++++++++ .../com/lambda/util/player/MovementUtils.kt | 6 +- .../util/primitives/extension/Entity.kt | 8 +- .../src/main/resources/lambda.accesswidener | 5 + .../main/resources/lambda.mixins.common.json | 7 +- 20 files changed, 301 insertions(+), 38 deletions(-) create mode 100644 common/src/main/java/com/lambda/mixin/input/KeyboardInputMixin.java create mode 100644 common/src/main/java/com/lambda/mixin/input/MouseMixin.java create mode 100644 common/src/main/java/com/lambda/mixin/render/CameraMixin.java create mode 100644 common/src/main/java/com/lambda/mixin/render/GameRendererMixin.java create mode 100644 common/src/main/java/com/lambda/mixin/render/WorldRendererMixin.java create mode 100644 common/src/main/kotlin/com/lambda/event/events/InputEvent.kt create mode 100644 common/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt diff --git a/common/src/main/java/com/lambda/mixin/entity/ClientPlayerEntityMixin.java b/common/src/main/java/com/lambda/mixin/entity/ClientPlayerEntityMixin.java index e4883ad8e..c5814f11a 100644 --- a/common/src/main/java/com/lambda/mixin/entity/ClientPlayerEntityMixin.java +++ b/common/src/main/java/com/lambda/mixin/entity/ClientPlayerEntityMixin.java @@ -5,6 +5,7 @@ import com.lambda.event.events.MovementEvent; import com.lambda.interaction.PlayerPacketManager; import com.lambda.interaction.RotationManager; +import net.minecraft.client.input.Input; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.entity.MovementType; import net.minecraft.util.math.Vec3d; @@ -26,6 +27,8 @@ public abstract class ClientPlayerEntityMixin extends EntityMixin { @Shadow private boolean autoJumpEnabled; + @Shadow public Input input; + @Inject(method = "move", at = @At("HEAD"), cancellable = true) void onMove(MovementType movementType, Vec3d movement, CallbackInfo ci) { ClientPlayerEntity self = (ClientPlayerEntity) (Object) this; @@ -49,12 +52,14 @@ void onMove(MovementType movementType, Vec3d movement, CallbackInfo ci) { @Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isUsingItem()Z")) boolean onSlowDown(ClientPlayerEntity entity) { if (EventFlow.post(new MovementEvent.SlowDown()).isCanceled()) return false; - return this.isUsingItem(); + return isUsingItem(); } - @Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/input/Input;tick(ZF)V", shift = At.Shift.AFTER)) - void processMovement(CallbackInfo ci) { - RotationManager.BaritoneProcessor.processPlayerMovement(); + @Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/input/Input;tick(ZF)V")) + void processMovement(Input input, boolean slowDown, float slowDownFactor) { + if (EventFlow.post(new MovementEvent.InputUpdate(input, slowDown, slowDownFactor)).isCanceled()) return; + + input.tick(slowDown, slowDownFactor); } @Inject(method = "sendMovementPackets", at = @At(value = "HEAD"), cancellable = true) diff --git a/common/src/main/java/com/lambda/mixin/input/KeyboardInputMixin.java b/common/src/main/java/com/lambda/mixin/input/KeyboardInputMixin.java new file mode 100644 index 000000000..0b9a5ac8c --- /dev/null +++ b/common/src/main/java/com/lambda/mixin/input/KeyboardInputMixin.java @@ -0,0 +1,17 @@ +package com.lambda.mixin.input; + +import com.lambda.event.EventFlow; +import com.lambda.event.events.InputEvent; +import net.minecraft.client.input.KeyboardInput; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(KeyboardInput.class) +public class KeyboardInputMixin { + @Inject(method = "tick", at = @At("TAIL")) + private void onTick(boolean slowDown, float slowDownFactor, CallbackInfo ci) { + EventFlow.post(new InputEvent()); + } +} diff --git a/common/src/main/java/com/lambda/mixin/input/MouseMixin.java b/common/src/main/java/com/lambda/mixin/input/MouseMixin.java new file mode 100644 index 000000000..77cdeb238 --- /dev/null +++ b/common/src/main/java/com/lambda/mixin/input/MouseMixin.java @@ -0,0 +1,21 @@ +package com.lambda.mixin.input; + +import com.lambda.module.modules.player.Freecam; +import net.minecraft.client.Mouse; +import net.minecraft.client.network.ClientPlayerEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(Mouse.class) +public class MouseMixin { + @Redirect(method = "updateMouse", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;changeLookDirection(DD)V")) + private void updateMouseChangeLookDirection(ClientPlayerEntity player, double cursorDeltaX, double cursorDeltaY) { + if (Freecam.INSTANCE.isEnabled()) { + Freecam.updateRotation(cursorDeltaX, cursorDeltaY); + return; + } + + player.changeLookDirection(cursorDeltaX, cursorDeltaY); + } +} diff --git a/common/src/main/java/com/lambda/mixin/render/CameraMixin.java b/common/src/main/java/com/lambda/mixin/render/CameraMixin.java new file mode 100644 index 000000000..453bf4312 --- /dev/null +++ b/common/src/main/java/com/lambda/mixin/render/CameraMixin.java @@ -0,0 +1,27 @@ +package com.lambda.mixin.render; + +import com.lambda.module.modules.player.Freecam; +import net.minecraft.entity.Entity; +import net.minecraft.world.BlockView; +import org.spongepowered.asm.mixin.Mixin; +import net.minecraft.client.render.Camera; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Camera.class) +public class CameraMixin { + @Inject(method = "update", at = @At("TAIL")) + private void onUpdate( + BlockView area, + Entity focusedEntity, + boolean thirdPerson, + boolean inverseView, + float tickDelta, + CallbackInfo ci + ) { + if (!Freecam.INSTANCE.isEnabled()) return; + + Freecam.updateCam(); + } +} diff --git a/common/src/main/java/com/lambda/mixin/render/GameRendererMixin.java b/common/src/main/java/com/lambda/mixin/render/GameRendererMixin.java new file mode 100644 index 000000000..97cd4628e --- /dev/null +++ b/common/src/main/java/com/lambda/mixin/render/GameRendererMixin.java @@ -0,0 +1,19 @@ +package com.lambda.mixin.render; + +import com.lambda.module.modules.player.Freecam; +import net.minecraft.client.render.GameRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(GameRenderer.class) +public class GameRendererMixin { + @Inject(method = "updateTargetedEntity", at = @At("HEAD"), cancellable = true) + private void updateTargetedEntityInvoke(float tickDelta, CallbackInfo info) { + if (!Freecam.INSTANCE.isEnabled()) return; + + info.cancel(); + Freecam.updateTarget(); + } +} diff --git a/common/src/main/java/com/lambda/mixin/render/WorldRendererMixin.java b/common/src/main/java/com/lambda/mixin/render/WorldRendererMixin.java new file mode 100644 index 000000000..e95ee1303 --- /dev/null +++ b/common/src/main/java/com/lambda/mixin/render/WorldRendererMixin.java @@ -0,0 +1,22 @@ +package com.lambda.mixin.render; + +import com.lambda.module.modules.player.Freecam; +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.WorldRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(WorldRenderer.class) +public class WorldRendererMixin { + @Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/Camera;isThirdPerson()Z")) + private boolean renderIsThirdPerson(Camera camera) { + return Freecam.INSTANCE.isEnabled() || camera.isThirdPerson(); + } + + @ModifyArg(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;setupTerrain(Lnet/minecraft/client/render/Camera;Lnet/minecraft/client/render/Frustum;ZZ)V"), index = 3) + private boolean renderSetupTerrainModifyArg(boolean spectator) { + return Freecam.INSTANCE.isEnabled() || spectator; + } +} diff --git a/common/src/main/kotlin/com/lambda/config/RotationSettings.kt b/common/src/main/kotlin/com/lambda/config/RotationSettings.kt index b76deb647..6df4ad2f8 100644 --- a/common/src/main/kotlin/com/lambda/config/RotationSettings.kt +++ b/common/src/main/kotlin/com/lambda/config/RotationSettings.kt @@ -8,7 +8,7 @@ class RotationSettings( c: Configurable, vis: () -> Boolean = { true } ) : IRotationConfig { - override val rotationMode by c.setting("Mode", RotationMode.LOCK, "SILENT - server-side rotation, SYNC - server-side rotation; client-side movement, LOCK - Lock camera", vis) + override var rotationMode by c.setting("Mode", RotationMode.SYNC, "SILENT - server-side rotation, SYNC - server-side rotation; client-side movement, LOCK - Lock camera", vis) override val keepTicks by c.setting("Keep Rotation", 3, 1..10, 1, "Ticks to keep rotation", vis) override val resetTicks by c.setting("Reset Rotation", 3, 1..10, 1, "Ticks before rotation is reset", vis) diff --git a/common/src/main/kotlin/com/lambda/event/events/InputEvent.kt b/common/src/main/kotlin/com/lambda/event/events/InputEvent.kt new file mode 100644 index 000000000..19a9c8db3 --- /dev/null +++ b/common/src/main/kotlin/com/lambda/event/events/InputEvent.kt @@ -0,0 +1,5 @@ +package com.lambda.event.events + +import com.lambda.event.Event + +class InputEvent : Event \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/event/events/MovementEvent.kt b/common/src/main/kotlin/com/lambda/event/events/MovementEvent.kt index 34d2df099..12b364978 100644 --- a/common/src/main/kotlin/com/lambda/event/events/MovementEvent.kt +++ b/common/src/main/kotlin/com/lambda/event/events/MovementEvent.kt @@ -3,10 +3,16 @@ package com.lambda.event.events import com.lambda.event.Event import com.lambda.event.cancellable.Cancellable import com.lambda.event.cancellable.ICancellable +import net.minecraft.client.input.Input abstract class MovementEvent : Event { class Pre : MovementEvent() class Post : MovementEvent() + class InputUpdate( + val input: Input, + val slowDown: Boolean, + val slowDownFactor: Float + ) : MovementEvent(), ICancellable by Cancellable() class ClipAtLedge : MovementEvent(), ICancellable by Cancellable() class Jump(var height: Double) : MovementEvent(), ICancellable by Cancellable() class SlowDown : Event, ICancellable by Cancellable() diff --git a/common/src/main/kotlin/com/lambda/event/events/RotationEvent.kt b/common/src/main/kotlin/com/lambda/event/events/RotationEvent.kt index b83e3e7bc..bfd1e3694 100644 --- a/common/src/main/kotlin/com/lambda/event/events/RotationEvent.kt +++ b/common/src/main/kotlin/com/lambda/event/events/RotationEvent.kt @@ -24,7 +24,7 @@ abstract class RotationEvent : Event { init { // Always check if baritone wants to rotate as well RotationManager.BaritoneProcessor.baritoneContext?.let { context -> - requests.add(RotationRequest(-1, context.config, context.rotation)) + requests.add(RotationRequest(context.config, context.rotation, -1)) } } diff --git a/common/src/main/kotlin/com/lambda/interaction/RotationManager.kt b/common/src/main/kotlin/com/lambda/interaction/RotationManager.kt index 3aebab7a6..348351251 100644 --- a/common/src/main/kotlin/com/lambda/interaction/RotationManager.kt +++ b/common/src/main/kotlin/com/lambda/interaction/RotationManager.kt @@ -1,14 +1,10 @@ package com.lambda.interaction -import com.lambda.Lambda.LOG import com.lambda.Lambda.mc import com.lambda.Loadable import com.lambda.config.RotationSettings import com.lambda.event.EventFlow -import com.lambda.event.events.ConnectionEvent -import com.lambda.event.events.PacketEvent -import com.lambda.event.events.RotationEvent -import com.lambda.event.events.TickEvent +import com.lambda.event.events.* import com.lambda.event.listener.SafeListener.Companion.listener import com.lambda.event.listener.UnsafeListener.Companion.unsafeListener import com.lambda.interaction.rotation.* @@ -18,7 +14,6 @@ import com.lambda.interaction.rotation.Rotation.Companion.interpolate import com.lambda.module.modules.client.Baritone import com.lambda.threading.runOnGameThread import com.lambda.threading.runSafe -import com.lambda.util.Communication.info import com.lambda.util.math.MathUtils.lerp import com.lambda.util.math.MathUtils.toRadian import com.lambda.util.math.Vec2d @@ -50,15 +45,14 @@ object RotationManager : Loadable { @JvmStatic fun updateInterpolated() = runSafe { -// if (currentRequest == null) return@runSafe -// val interpolation = interpolate(prevRotation, currentRotation, mc.tickDelta.toDouble()) -// + if (currentRequest == null) return@runSafe + if (currentRequest?.config?.rotationMode != RotationMode.LOCK) return@runSafe + val interpolation = prevRotation.interpolate(currentRotation, mc.tickDelta.toDouble()) + // val rot = interpolation.fixSensitivity(prevRotation) -// -// if (currentRequest?.config?.rotationMode == RotationMode.LOCK) { -// player.yaw = rot.yaw.toFloat() -// player.pitch = rot.pitch.toFloat() -// } + + player.yaw = interpolation.yaw.toFloat() + player.pitch = interpolation.pitch.toFloat() } init { @@ -105,7 +99,7 @@ object RotationManager : Loadable { val turnSpeed = context.config.turnSpeed * speedMultiplier - val interpolation = interpolate(prevRotation, rotationTo, turnSpeed) + val interpolation = prevRotation.interpolate(rotationTo, turnSpeed) currentRotation = interpolation.fixSensitivity(prevRotation) @@ -183,6 +177,10 @@ object RotationManager : Loadable { listener { baritoneContext = null } + + listener { + processPlayerMovement() + } } @JvmStatic diff --git a/common/src/main/kotlin/com/lambda/interaction/rotation/Rotation.kt b/common/src/main/kotlin/com/lambda/interaction/rotation/Rotation.kt index dbb459d73..2cb39e161 100644 --- a/common/src/main/kotlin/com/lambda/interaction/rotation/Rotation.kt +++ b/common/src/main/kotlin/com/lambda/interaction/rotation/Rotation.kt @@ -14,7 +14,7 @@ import kotlin.math.* data class Rotation(val yaw: Double, val pitch: Double) { constructor(yaw: Float, pitch: Float) : this(yaw.toDouble(), pitch.toDouble()) - private val rotationVector: Vec3d get() { + val vector: Vec3d get() { val yawRad = -yaw.toRadian() val pitchRad = pitch.toRadian() @@ -22,13 +22,16 @@ data class Rotation(val yaw: Double, val pitch: Double) { .multiply(Vec3d(cos(pitchRad), sin(pitchRad), cos(pitchRad))) } + fun withDelta(yaw: Double = 0.0, pitch: Double = 0.0) = + Rotation(this.yaw + yaw, (this.pitch + pitch).coerceIn(-90.0, 90.0)) + fun rayCast( reach: Double, mask: RayCastMask = RayCastMask.BOTH, eye: Vec3d? = null, fluids: Boolean = false ) = runSafe { - rayCast(eye ?: player.eyePos, rotationVector, reach, mask, fluids) + rayCast(eye ?: player.eyePos, vector, reach, mask, fluids) } val Direction.yaw: Float @@ -46,17 +49,17 @@ data class Rotation(val yaw: Double, val pitch: Double) { private fun wrap(deg: Double) = MathHelper.wrapDegrees(deg) - fun interpolate(a: Rotation, b: Rotation, speed: Double): Rotation { - val yawDiff = wrap(b.yaw - a.yaw) - val pitchDiff = wrap(b.pitch - a.pitch) + fun Rotation.interpolate(other: Rotation, delta: Double): Rotation { + val yawDiff = wrap(other.yaw - yaw) + val pitchDiff = wrap(other.pitch - pitch) val diff = hypot(yawDiff, pitchDiff) - val yawSpeed = abs(yawDiff / diff) * speed - val pitchSpeed = abs(pitchDiff / diff) * speed + val yawSpeed = abs(yawDiff / diff) * delta + val pitchSpeed = abs(pitchDiff / diff) * delta - val yaw = a.yaw + yawDiff.coerceIn(-yawSpeed, yawSpeed) - val pitch = a.pitch + pitchDiff.coerceIn(-pitchSpeed, pitchSpeed) + val yaw = yaw + yawDiff.coerceIn(-yawSpeed, yawSpeed) + val pitch = pitch + pitchDiff.coerceIn(-pitchSpeed, pitchSpeed) return Rotation(yaw, pitch) } diff --git a/common/src/main/kotlin/com/lambda/interaction/rotation/RotationRequest.kt b/common/src/main/kotlin/com/lambda/interaction/rotation/RotationRequest.kt index 27282e1e1..d238248a6 100644 --- a/common/src/main/kotlin/com/lambda/interaction/rotation/RotationRequest.kt +++ b/common/src/main/kotlin/com/lambda/interaction/rotation/RotationRequest.kt @@ -1,11 +1,12 @@ package com.lambda.interaction.rotation data class RotationRequest( - val priority: Int = 1, val config: IRotationConfig, val rotation: Rotation, - var isPending: Boolean = true + val priority: Int = 0, ) : Comparable { + var isPending: Boolean = true + override fun compareTo(other: RotationRequest) = priority.compareTo(other.priority) } \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/interaction/visibilty/VisibilityChecker.kt b/common/src/main/kotlin/com/lambda/interaction/visibilty/VisibilityChecker.kt index 72a87f787..6909e9207 100644 --- a/common/src/main/kotlin/com/lambda/interaction/visibilty/VisibilityChecker.kt +++ b/common/src/main/kotlin/com/lambda/interaction/visibilty/VisibilityChecker.kt @@ -73,14 +73,14 @@ object VisibilityChecker { // Rotate to selected point closestRotation?.let { rotation -> - return RotationRequest(priority, rotationConfig, rotation) + return RotationRequest(rotationConfig, rotation, priority) } return null } private fun stay(priority: Int = 0, config: IRotationConfig) = - RotationRequest(priority, config, RotationManager.currentRotation) + RotationRequest(config, RotationManager.currentRotation, priority) inline fun SafeContext.scanVisibleSurfaces(box: Box, sides: Set, resolution: Int, check: (Vec3d) -> Unit) { val shrunk = box.expand(-0.005) diff --git a/common/src/main/kotlin/com/lambda/module/Module.kt b/common/src/main/kotlin/com/lambda/module/Module.kt index c26364ada..7adf79675 100644 --- a/common/src/main/kotlin/com/lambda/module/Module.kt +++ b/common/src/main/kotlin/com/lambda/module/Module.kt @@ -34,7 +34,7 @@ import com.lambda.util.Nameable * If a module does not need to be activated by a key (like [ClickGUI]), * the default [keybind] should not be set (using [KeyCode.Unbound]). * - * [Module]s are [Configurable] with [settings] (see [AbstractSetting] for all setting types). + * [Module]s are [Configurable]s with [settings] (see [AbstractSetting] for all setting types). * For example, a [BooleanSetting] and a [DoubleSetting] can be defined like this: * ```kotlin * private val foo by setting("Foo", true) diff --git a/common/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt b/common/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt new file mode 100644 index 000000000..e78ae9062 --- /dev/null +++ b/common/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt @@ -0,0 +1,119 @@ +package com.lambda.module.modules.player + +import com.lambda.Lambda.mc +import com.lambda.config.RotationSettings +import com.lambda.event.events.ConnectionEvent +import com.lambda.event.events.MovementEvent +import com.lambda.event.events.RotationEvent +import com.lambda.event.listener.SafeListener.Companion.listener +import com.lambda.interaction.rotation.Rotation +import com.lambda.interaction.rotation.Rotation.Companion.interpolate +import com.lambda.interaction.rotation.Rotation.Companion.rotationTo +import com.lambda.interaction.rotation.RotationMode +import com.lambda.interaction.rotation.RotationRequest +import com.lambda.module.Module +import com.lambda.module.tag.ModuleTag +import com.lambda.threading.runSafe +import com.lambda.util.KeyCode +import com.lambda.util.player.MovementUtils.cancel +import com.lambda.util.primitives.extension.interpolate +import com.lambda.util.primitives.extension.rotation +import com.lambda.util.world.raycast.RayCastMask +import com.lambda.util.world.raycast.RayCastUtils.rayCast +import net.minecraft.client.input.KeyboardInput +import net.minecraft.entity.Entity +import net.minecraft.util.math.Vec3d +import kotlin.math.pow + +object Freecam : Module( + name = "Freecam", + description = "Move your camera freely", + defaultTags = setOf(ModuleTag.RENDER), + defaultKeybind = KeyCode.G +) { + private val speed by setting("Speed", 0.5, 0.1..1.0, 0.1) + private val rotateToTarget by setting("Rotate to target", true) + + private val rotationConfig = RotationSettings(this).apply { + rotationMode = RotationMode.LOCK + } + + private var prevPosition: Vec3d = Vec3d.ZERO + @JvmStatic var position: Vec3d = Vec3d.ZERO + private val interpolatedPosition: Vec3d + get() = prevPosition.interpolate(position, mc.tickDelta.toDouble()) + + private var previousRotation: Rotation = Rotation.ZERO + @JvmStatic var rotation: Rotation = Rotation.ZERO + private val interpolatedRotation: Rotation + get() = previousRotation.interpolate(rotation, mc.tickDelta.toDouble()) + + private var velocity: Vec3d = Vec3d.ZERO + + @JvmStatic fun updateCam() { + mc.gameRenderer.camera.apply { + setRotation(interpolatedRotation.yaw.toFloat(), interpolatedRotation.pitch.toFloat()) + setPos(interpolatedPosition.x, interpolatedPosition.y, interpolatedPosition.z) + } + } + + @JvmStatic fun updateRotation(deltaYaw: Double, deltaPitch: Double) { + previousRotation = rotation + val factor = (mc.options.mouseSensitivity.value * 0.6 + 0.2).pow(3) + rotation = rotation.withDelta(deltaYaw * factor, deltaPitch * factor) + } + + @JvmStatic fun updateTarget() { + runSafe { + val cast = rayCast( + interpolatedPosition, + interpolatedRotation.vector, + interaction.reachDistance.toDouble(), + RayCastMask.BOTH, + true + ) + mc.crosshairTarget = cast + } + } + + init { + onEnable { + position = player.eyePos + rotation = player.rotation + velocity = Vec3d.ZERO + } + + listener { + if (!rotateToTarget) return@listener + val target = mc.crosshairTarget ?: return@listener + + val rotation = player.eyePos.rotationTo(target.pos) + it.requests.add(RotationRequest(rotationConfig, rotation)) + } + + listener { event -> + event.cancel() + + // Reset actual input + player.input.cancel() + + // Create new input for freecam + val input = KeyboardInput(mc.options) + input.tick(event.slowDown, event.slowDownFactor) + var y = 0.0 + if (input.jumping) y++ + if (input.sneaking) y-- + val inputVec = Vec3d(input.movementSideways.toDouble(), y, input.movementForward.toDouble()) + val velocityDelta = Entity.movementInputToVelocity(inputVec, speed.toFloat(), rotation.yaw.toFloat()) + + // move freecam + velocity = velocity.add(velocityDelta).multiply(0.6) + prevPosition = position + position = position.add(velocity) + } + + listener { + disable() + } + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/util/player/MovementUtils.kt b/common/src/main/kotlin/com/lambda/util/player/MovementUtils.kt index 7d2542469..c7d743ce8 100644 --- a/common/src/main/kotlin/com/lambda/util/player/MovementUtils.kt +++ b/common/src/main/kotlin/com/lambda/util/player/MovementUtils.kt @@ -34,7 +34,11 @@ object MovementUtils { val SafeContext.verticalMovement get() = player.input.jumping.toInt() - player.input.sneaking.toInt() - fun SafeContext.calcMoveYaw(yawIn: Float = player.moveYaw, moveForward: Float = roundedForward, moveStrafe: Float = roundedStrafing): Double { + fun SafeContext.calcMoveYaw( + yawIn: Float = player.moveYaw, + moveForward: Float = roundedForward, + moveStrafe: Float = roundedStrafing + ): Double { var strafe = 90 * moveStrafe strafe *= if (moveForward != 0F) moveForward * 0.5F else 1F diff --git a/common/src/main/kotlin/com/lambda/util/primitives/extension/Entity.kt b/common/src/main/kotlin/com/lambda/util/primitives/extension/Entity.kt index 32fd32bfb..7c61d51e4 100644 --- a/common/src/main/kotlin/com/lambda/util/primitives/extension/Entity.kt +++ b/common/src/main/kotlin/com/lambda/util/primitives/extension/Entity.kt @@ -1,5 +1,6 @@ package com.lambda.util.primitives.extension +import com.lambda.interaction.rotation.Rotation import com.lambda.util.math.MathUtils.lerp import net.minecraft.client.MinecraftClient import net.minecraft.entity.Entity @@ -12,6 +13,9 @@ val Entity.prevPos val Entity.interpolatedPos get() = lerp(prevPos, pos, MinecraftClient.getInstance().partialTicks) +val Entity.rotation + get() = Rotation(yaw, pitch) + val Entity.interpolatedBox: Box get() { val box = boundingBox @@ -21,4 +25,6 @@ val Entity.interpolatedBox: Box val pos = interpolatedPos return Box(pos.x - xw, pos.y, pos.z - zw, pos.x + xw, pos.y + yw, pos.z + zw) - } \ No newline at end of file + } + +fun Vec3d.interpolate(other: Vec3d, t: Double) = lerp(this, other, t) \ No newline at end of file diff --git a/common/src/main/resources/lambda.accesswidener b/common/src/main/resources/lambda.accesswidener index dc5a5cd89..eba7ff6b3 100644 --- a/common/src/main/resources/lambda.accesswidener +++ b/common/src/main/resources/lambda.accesswidener @@ -10,6 +10,11 @@ accessible field net/minecraft/client/world/ClientWorld entityManager Lnet/minec # Entity accessible field net/minecraft/entity/projectile/FireworkRocketEntity shooter Lnet/minecraft/entity/LivingEntity; +accessible method net/minecraft/entity/Entity movementInputToVelocity (Lnet/minecraft/util/math/Vec3d;FF)Lnet/minecraft/util/math/Vec3d; + +# Camera +accessible method net/minecraft/client/render/Camera setPos (DDD)V +accessible method net/minecraft/client/render/Camera setRotation (FF)V # Text accessible field net/minecraft/text/Style color Lnet/minecraft/text/TextColor; diff --git a/common/src/main/resources/lambda.mixins.common.json b/common/src/main/resources/lambda.mixins.common.json index 29732afc6..463eefb84 100644 --- a/common/src/main/resources/lambda.mixins.common.json +++ b/common/src/main/resources/lambda.mixins.common.json @@ -15,7 +15,12 @@ "PlayerEntityMixin", "entity.ClientPlayerEntityMixin", "entity.EntityMixin", - "entity.LivingEntityMixin" + "entity.LivingEntityMixin", + "input.KeyboardInputMixin", + "input.MouseMixin", + "render.CameraMixin", + "render.GameRendererMixin", + "render.WorldRendererMixin" ], "injectors": { "defaultRequire": 1 From 417bd0adf4dbf1d55eb24f3898c2950ba6945cc2 Mon Sep 17 00:00:00 2001 From: Constructor Date: Sun, 24 Mar 2024 06:13:52 +0100 Subject: [PATCH 2/2] Cleanup --- .../main/kotlin/com/lambda/module/modules/player/Freecam.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt b/common/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt index e78ae9062..8a3a5fbab 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt @@ -65,14 +65,13 @@ object Freecam : Module( @JvmStatic fun updateTarget() { runSafe { - val cast = rayCast( + mc.crosshairTarget = rayCast( interpolatedPosition, interpolatedRotation.vector, interaction.reachDistance.toDouble(), RayCastMask.BOTH, true ) - mc.crosshairTarget = cast } }