diff --git a/src/main/java/com/lambda/mixin/render/CameraMixin.java b/src/main/java/com/lambda/mixin/render/CameraMixin.java index 9c8167947..5a269a13d 100644 --- a/src/main/java/com/lambda/mixin/render/CameraMixin.java +++ b/src/main/java/com/lambda/mixin/render/CameraMixin.java @@ -20,6 +20,7 @@ import com.lambda.interaction.request.rotation.RotationManager; import com.lambda.module.modules.player.Freecam; import com.lambda.module.modules.render.CameraTweaks; +import com.lambda.module.modules.render.FreeLook; import net.minecraft.client.render.Camera; import net.minecraft.entity.Entity; import net.minecraft.world.BlockView; @@ -28,8 +29,10 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.ModifyArgs; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.invoke.arg.Args; @Mixin(Camera.class) public abstract class CameraMixin { @@ -74,6 +77,8 @@ private void injectQuickPerspectiveSwap(BlockView area, Entity focusedEntity, bo private void onClipToSpace(float desiredCameraDistance, CallbackInfoReturnable info) { if (CameraTweaks.INSTANCE.isEnabled() && CameraTweaks.getNoClipCam()) { info.setReturnValue(desiredCameraDistance); + } else if (FreeLook.INSTANCE.isEnabled()) { + info.setReturnValue(desiredCameraDistance); } } @@ -93,8 +98,51 @@ private void onClipToSpace(float desiredCameraDistance, CallbackInfoReturnableExperimental Minecart Controller:

+ *
+     * if (experimentalMinecartController.hasCurrentLerpSteps()) {
+     *     Vec3d vec3d = minecartEntity.getPassengerRidingPos(focusedEntity).subtract(minecartEntity.getPos()).subtract(focusedEntity.getVehicleAttachmentPos(minecartEntity)).add(new Vec3d(0.0, (double)MathHelper.lerp(tickProgress, this.lastCameraY, this.cameraY), 0.0));
+     *     this.setRotation(focusedEntity.getYaw(tickProgress), focusedEntity.getPitch(tickProgress));
+     *     this.setPos(experimentalMinecartController.getLerpedPosition(tickProgress).add(vec3d));
+     *     break label39;
+     * }
+     * 
+ *

Default Camera:

+ *
+     * this.setRotation(focusedEntity.getYaw(tickProgress), focusedEntity.getPitch(tickProgress));
+     * this.setPos(MathHelper.lerp((double)tickProgress, focusedEntity.lastX, focusedEntity.getX()), MathHelper.lerp((double)tickProgress, focusedEntity.lastY, focusedEntity.getY()) + (double)MathHelper.lerp(tickProgress, this.lastCameraY, this.cameraY), MathHelper.lerp((double)tickProgress, focusedEntity.lastZ, focusedEntity.getZ()));
+     * 
+ *

Third person camera:

+ *
+     * if (thirdPerson) {
+     *     if (inverseView) {
+     *         this.setRotation(this.yaw + 180.0F, -this.pitch);
+     *     }
+     *     // ...
+     * }
+     * 
+ *

When the player is focused on another Living Entity:

+ *
+     * Direction direction = ((LivingEntity)focusedEntity).getSleepingDirection();
+     * this.setRotation(direction != null ? direction.getPositiveHorizontalDegrees() - 180.0F : 0.0F, 0.0F);
+     * this.moveBy(0.0F, 0.3F, 0.0F);
+     * 
+ */ + @ModifyArgs(method = "update", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/Camera;setRotation(FF)V")) + private void onUpdateSetRotationArgs(Args args) { + if (FreeLook.INSTANCE.isEnabled()) { + args.set(0, FreeLook.INSTANCE.getCamera().getYawF()); + args.set(1, FreeLook.INSTANCE.getCamera().getPitchF()); + } + } } diff --git a/src/main/kotlin/com/lambda/module/modules/render/FreeLook.kt b/src/main/kotlin/com/lambda/module/modules/render/FreeLook.kt new file mode 100644 index 000000000..f7163f9a3 --- /dev/null +++ b/src/main/kotlin/com/lambda/module/modules/render/FreeLook.kt @@ -0,0 +1,83 @@ +/* + * Copyright 2025 Lambda + * + * 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 com.lambda.module.modules.render + +import com.lambda.Lambda +import com.lambda.Lambda.mc +import com.lambda.event.events.PlayerEvent +import com.lambda.event.listener.SafeListener.Companion.listen +import com.lambda.interaction.request.rotation.Rotation +import com.lambda.module.Module +import com.lambda.module.tag.ModuleTag +import com.lambda.util.extension.rotation +import net.minecraft.client.option.Perspective + + +object FreeLook : Module( + name = "FreeLook", + description = "Allows you to look around freely while moving", + tag = ModuleTag.PLAYER, +) { + val enableYaw by setting("Enable Yaw", false, "Don't effect pitch if enabled") + val enablePitch by setting("Enable Pitch", false, "Don't effect yaw if enabled") + val togglePerspective by setting("Toggle Perspective", true, "Toggle perspective when enabling FreeLook") + + var camera: Rotation = Rotation.ZERO + var previousPerspective: Perspective = Perspective.FIRST_PERSON + + /** + * @see net.minecraft.entity.Entity.changeLookDirection + */ + private const val SENSITIVITY_FACTOR = 0.15 + + @JvmStatic + fun updateCam() { + mc.gameRenderer.apply { + camera.setRotation(this@FreeLook.camera.yawF, this@FreeLook.camera.pitchF) + } + } + + init { + previousPerspective = mc.options.perspective + + onEnable { + camera = player.rotation + previousPerspective = mc.options.perspective + if (togglePerspective) mc.options.perspective = Perspective.THIRD_PERSON_BACK + } + + onDisable { + updateCam() + mc.options.perspective = previousPerspective + } + + listen { + if (!isEnabled) return@listen + + camera = camera.withDelta( + it.deltaYaw * SENSITIVITY_FACTOR, + it.deltaPitch * SENSITIVITY_FACTOR + ) + + if (enablePitch) player.pitch = camera.pitchF + if (enableYaw) player.yaw = camera.yawF + + it.cancel() + } + } +}