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.context.SafeContext
22+ import com.lambda.event.events.TickEvent
23+ import com.lambda.event.events.UpdateManagerEvent
24+ import com.lambda.event.listener.SafeListener.Companion.listen
25+ import com.lambda.interaction.request.rotating.Rotation
26+ import com.lambda.interaction.request.rotating.Rotation.Companion.rotationTo
27+ import com.lambda.interaction.request.rotating.Rotation.Companion.wrap
28+ import com.lambda.interaction.request.rotating.RotationRequest
29+ import com.lambda.interaction.request.rotating.visibilty.lookAt
30+ import com.lambda.module.Module
31+ import com.lambda.module.tag.ModuleTag
32+ import com.lambda.util.math.distSq
33+ import net.minecraft.entity.Entity
34+ import net.minecraft.entity.player.PlayerEntity
35+ import net.minecraft.util.math.MathHelper.wrapDegrees
36+ import java.util.*
37+ import java.util.random.RandomGenerator
38+
39+ object AntiAim : Module(
40+ " AntiAim" ,
41+ " Rotates the player using the given configs" ,
42+ setOf(ModuleTag .PLAYER , ModuleTag .MOVEMENT )
43+ ) {
44+ private val page by setting(" Page" , Page .General )
45+ private val yaw by setting(" Yaw Mode" , YawMode .Spin , " The mode used when setting the players yaw" ) { page == Page .General }
46+ .onValueChange { _, to ->
47+ if (to == YawMode .Custom ) {
48+ // To bypass recursion issue
49+ setConfigCustomYaw(player.yaw)
50+ }
51+ }
52+ private val spinMode by setting(" Spin Mode" , LeftRight .Right ) { yaw == YawMode .Spin && page == Page .General }
53+ private val sideMode by setting(" Side Mode" , LeftRight .Left ) { yaw == YawMode .Sideways && page == Page .General }
54+ private var customYaw by setting(" Custom Yaw" , 0f , - 179f .. 180f , 1f ) { yaw == YawMode .Custom && page == Page .General }
55+ private val yawPlayerMode by setting(" Yaw Player mode" , PlayerMode .Closest ) { yaw == YawMode .Player && page == Page .General }
56+
57+ private val pitch by setting(" Pitch Mode" , PitchMode .UpAndDown , " The mode used when setting the players pitch" ) { page == Page .General }
58+ .onValueChange { _, to ->
59+ if (to == PitchMode .Custom ) {
60+ // To bypass recursion issue
61+ setConfigCustomPitch(player.pitch)
62+ }
63+ }
64+ private val verticalMode by setting(" Vertical Mode" , VerticalMode .Up ) { pitch == PitchMode .Vertical && page == Page .General }
65+ private var customPitch by setting(" Custom Pitch" , 0f , - 90f .. 90f , 1f ) { pitch == PitchMode .Custom && page == Page .General }
66+ private val pitchPlayerMode by setting(" Pitch Player Mode" , PlayerMode .Closest ) { pitch == PitchMode .Player && page == Page .General }
67+
68+ private val yawSpeed by setting(" Yaw Speed" , 30 , 1 .. 90 , 1 , " Yaw rotation degrees per tick" , " °" ) { page == Page .General && yaw != YawMode .None }
69+ private val pitchSpeed by setting(" Pitch Speed" , 30 , 1 .. 90 , 1 , " Pitch rotation degrees per tick" , " °" ) { page == Page .General && pitch != PitchMode .None }
70+
71+ private val rotation = RotationSettings (this , - 1 ) { page == Page .Rotation }
72+
73+ private var currentYaw = 0.0f
74+ private var currentPitch = 0.0f
75+
76+ private val random = Random .from(RandomGenerator .getDefault())
77+ private var jitterRight = true
78+ private var jitterUp = true
79+ private var pitchingUp = true
80+
81+ init {
82+ onEnable {
83+ currentYaw = player.yaw
84+ currentPitch = player.pitch
85+ }
86+
87+ listen<TickEvent .Pre >(priority = Int .MAX_VALUE ) {
88+ currentYaw = wrapDegrees(when (yaw) {
89+ YawMode .Spin -> when (spinMode) {
90+ LeftRight .Left -> currentYaw - yawSpeed
91+ LeftRight .Right -> currentYaw + yawSpeed
92+ }
93+ YawMode .Jitter -> {
94+ val delta = random.nextFloat() * (yawSpeed)
95+ if (jitterRight) {
96+ jitterRight = false
97+ currentYaw + delta
98+ } else {
99+ jitterRight = true
100+ currentYaw - delta
101+ }
102+ }
103+ YawMode .Sideways -> when (sideMode) {
104+ LeftRight .Left -> player.yaw - 90
105+ LeftRight .Right -> player.yaw + 90
106+ }
107+ YawMode .Backwards -> player.yaw - 180
108+ YawMode .Custom -> customYaw
109+ YawMode .Player -> {
110+ val target = getLookAtPlayer(yawPlayerMode)
111+ target?.let {
112+ player.eyePos.rotationTo(target.eyePos).yawF
113+ } ? : player.yaw
114+ }
115+ YawMode .None -> player.yaw
116+ })
117+
118+ currentPitch = when (pitch) {
119+ PitchMode .UpAndDown -> {
120+ if (pitchingUp) {
121+ (currentPitch - pitchSpeed).also {
122+ if (currentPitch <= - 90 ) {
123+ pitchingUp = false
124+ }
125+ }
126+ } else {
127+ (currentPitch + pitchSpeed).also {
128+ if (currentPitch >= 90 ) {
129+ pitchingUp = true
130+ }
131+ }
132+ }
133+ }
134+ PitchMode .Jitter -> {
135+ val delta = random.nextFloat() * (pitchSpeed)
136+ if (jitterUp) {
137+ jitterUp = false
138+ currentPitch - delta
139+ } else {
140+ jitterUp = true
141+ currentPitch + delta
142+ }
143+ }
144+ PitchMode .Vertical -> {
145+ when (verticalMode) {
146+ VerticalMode .Up -> - 90f
147+ VerticalMode .Down -> 90f
148+ }
149+ }
150+ PitchMode .Custom -> customPitch
151+ PitchMode .Player -> {
152+ val target = getLookAtPlayer(pitchPlayerMode)
153+ target?.let {
154+ player.eyePos.rotationTo(target.eyePos).pitchF
155+ } ? : player.pitch
156+ }
157+ PitchMode .None -> player.pitch
158+ }.coerceIn(- 90f .. 90f )
159+ }
160+
161+ listen<UpdateManagerEvent .Rotation >(priority = Int .MIN_VALUE ) {
162+ if (currentYaw == wrap(player.yaw) && currentPitch == player.pitch) return @listen
163+ val rotationRequest = RotationRequest (lookAt(Rotation (currentYaw, currentPitch)), rotation)
164+ rotation.request(rotationRequest, false )
165+ }
166+ }
167+
168+ private fun SafeContext.getLookAtPlayer (playerMode : PlayerMode ): Entity ? {
169+ val players = world.entities.filter { it is PlayerEntity && it != player }
170+ return when (playerMode) {
171+ PlayerMode .Closest -> players.minByOrNull { it.eyePos distSq player.eyePos }
172+ PlayerMode .Farthest -> players.maxByOrNull { it.eyePos distSq player.eyePos }
173+ PlayerMode .Random -> players.randomOrNull()
174+ }
175+ }
176+
177+ private fun setConfigCustomYaw (newYaw : Float ) {
178+ customYaw = newYaw
179+ }
180+
181+ private fun setConfigCustomPitch (newPitch : Float ) {
182+ customPitch = newPitch
183+ }
184+
185+ private enum class YawMode {
186+ None ,
187+ Spin ,
188+ Jitter ,
189+ Sideways ,
190+ Backwards ,
191+ Custom ,
192+ Player
193+ }
194+
195+ private enum class LeftRight {
196+ Left ,
197+ Right
198+ }
199+
200+ private enum class PlayerMode {
201+ Closest ,
202+ Farthest ,
203+ Random
204+ }
205+
206+ private enum class PitchMode {
207+ None ,
208+ UpAndDown ,
209+ Jitter ,
210+ Vertical ,
211+ Custom ,
212+ Player
213+ }
214+
215+ private enum class VerticalMode {
216+ Up ,
217+ Down
218+ }
219+
220+ private enum class Page {
221+ General ,
222+ Rotation
223+ }
224+ }
0 commit comments