Skip to content

Commit 8cc0dab

Browse files
beanbag44emyfops
andauthored
Feature: Rotation lock module (#152)
Adds a module for locking the player's rotation. Has options for step, and yaw / pitch specific settings. This includes custom angles --------- Co-authored-by: Edouard127 <46357922+Edouard127@users.noreply.github.com>
1 parent d5976ba commit 8cc0dab

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

src/main/java/com/lambda/mixin/entity/EntityMixin.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@
2222
import com.lambda.event.events.EntityEvent;
2323
import com.lambda.event.events.PlayerEvent;
2424
import com.lambda.interaction.request.rotating.RotationManager;
25+
import com.lambda.interaction.request.rotating.RotationMode;
26+
import com.lambda.module.modules.player.RotationLock;
2527
import com.lambda.module.modules.render.NoRender;
2628
import com.lambda.util.math.Vec2d;
2729
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
30+
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
2831
import net.minecraft.entity.Entity;
2932
import net.minecraft.entity.MovementType;
3033
import net.minecraft.entity.data.TrackedData;
@@ -142,4 +145,20 @@ private boolean modifyGetFlagInvisible(boolean original) {
142145
private boolean modifyGetFlagGlowing(boolean original) {
143146
return (NoRender.INSTANCE.isDisabled() || !NoRender.getNoGlow()) && original;
144147
}
148+
149+
@WrapWithCondition(method = "changeLookDirection", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;setYaw(F)V"))
150+
private boolean wrapSetYaw(Entity instance, float yaw) {
151+
return (instance != Lambda.getMc().player ||
152+
RotationLock.INSTANCE.isDisabled() ||
153+
RotationLock.getRotationSettings().getRotationMode() != RotationMode.Lock ||
154+
RotationLock.getYawMode() == RotationLock.RotationMode.None);
155+
}
156+
157+
@WrapWithCondition(method = "changeLookDirection", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;setPitch(F)V"))
158+
private boolean wrapSetPitch(Entity instance, float yaw) {
159+
return (instance != Lambda.getMc().player ||
160+
RotationLock.INSTANCE.isDisabled() ||
161+
RotationLock.getRotationSettings().getRotationMode() != RotationMode.Lock ||
162+
RotationLock.getPitchMode() == RotationLock.RotationMode.None);
163+
}
145164
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright 2025 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.module.modules.player
19+
20+
import com.lambda.config.groups.RotationSettings
21+
import com.lambda.event.events.TickEvent
22+
import com.lambda.event.listener.SafeListener.Companion.listen
23+
import com.lambda.interaction.request.rotating.Rotation
24+
import com.lambda.interaction.request.rotating.RotationRequest
25+
import com.lambda.interaction.request.rotating.visibilty.lookAt
26+
import com.lambda.module.Module
27+
import com.lambda.module.tag.ModuleTag
28+
import com.lambda.util.NamedEnum
29+
import kotlin.math.roundToInt
30+
31+
object RotationLock : Module(
32+
name = "RotationLock",
33+
description = "Locks the player rotation to the given configuration",
34+
tag = ModuleTag.PLAYER,
35+
) {
36+
private enum class Group(override val displayName: String) : NamedEnum {
37+
General("General"),
38+
Rotation("Rotation")
39+
}
40+
41+
@JvmStatic val yawMode by setting("Yaw Mode", RotationMode.Snap).group(Group.General)
42+
private val yawStep by setting("Yaw Step", 45.0, 1.0..180.0, 1.0) { yawMode == RotationMode.Snap }.group(Group.General)
43+
private val customYaw by setting("Custom Yaw", 0.0, -179.0..180.0, 1.0) { yawMode == RotationMode.Custom }.group(Group.General)
44+
@JvmStatic val pitchMode by setting("Pitch Mode", RotationMode.Custom).group(Group.General)
45+
private val pitchStep by setting("Pitch Step", 45.0, 1.0..90.0, 1.0) { pitchMode == RotationMode.Snap }.group(Group.General)
46+
private val customPitch by setting("Custom Pitch", 0.0, -90.0..90.0, 1.0) { pitchMode == RotationMode.Custom }.group(Group.General)
47+
48+
@JvmStatic val rotationSettings = RotationSettings(this, Group.Rotation)
49+
private var rotationRequest: RotationRequest? = null
50+
51+
init {
52+
listen<TickEvent.Pre> {
53+
val yaw = when (yawMode) {
54+
RotationMode.Custom -> customYaw
55+
RotationMode.Snap -> {
56+
val normalizedYaw = (player.yaw % 360.0 + 360.0) % 360.0
57+
(normalizedYaw / yawStep).roundToInt() * yawStep
58+
}
59+
RotationMode.None -> player.yaw.toDouble()
60+
}
61+
val pitch = when (pitchMode) {
62+
RotationMode.Custom -> customPitch
63+
RotationMode.Snap -> {
64+
val clampedPitch = player.pitch.coerceIn(-90f, 90f)
65+
(clampedPitch / pitchStep).roundToInt() * pitchStep
66+
}
67+
RotationMode.None -> player.pitch.toDouble()
68+
}
69+
70+
RotationRequest(lookAt(Rotation(yaw, pitch), 0.001), rotationSettings).submit()
71+
}
72+
}
73+
74+
enum class RotationMode {
75+
Snap,
76+
Custom,
77+
None
78+
}
79+
}

0 commit comments

Comments
 (0)