1+ package com.lambda.module.modules.movement
2+
3+ import com.lambda.context.SafeContext
4+ import com.lambda.event.events.ConnectionEvent
5+ import com.lambda.event.events.PacketEvent
6+ import com.lambda.event.events.RenderEvent
7+ import com.lambda.event.events.TickEvent
8+ import com.lambda.event.listener.SafeListener.Companion.listener
9+ import com.lambda.graphics.renderer.esp.DynamicAABB
10+ import com.lambda.graphics.renderer.esp.builders.build
11+ import com.lambda.module.Module
12+ import com.lambda.module.modules.client.GuiSettings
13+ import com.lambda.module.modules.combat.KillAura
14+ import com.lambda.module.tag.ModuleTag
15+ import com.lambda.util.PacketUtils.handlePacketSilently
16+ import com.lambda.util.ServerPacket
17+ import com.lambda.util.math.ColorUtils.multAlpha
18+ import com.lambda.util.math.MathUtils.lerp
19+ import com.lambda.util.math.VecUtils.dist
20+ import com.lambda.util.math.VecUtils.minus
21+ import com.lambda.util.math.VecUtils.plus
22+ import net.minecraft.network.packet.s2c.play.EntityAnimationS2CPacket
23+ import net.minecraft.network.packet.s2c.play.EntityPositionS2CPacket
24+ import net.minecraft.network.packet.s2c.play.EntityS2CPacket
25+ import net.minecraft.network.packet.s2c.play.EntityStatusEffectS2CPacket
26+ import net.minecraft.network.packet.s2c.play.ParticleS2CPacket
27+ import net.minecraft.network.packet.s2c.play.PlaySoundFromEntityS2CPacket
28+ import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket
29+ import net.minecraft.network.packet.s2c.play.StopSoundS2CPacket
30+ import net.minecraft.network.packet.s2c.play.WorldEventS2CPacket
31+ import net.minecraft.network.packet.s2c.play.WorldTimeUpdateS2CPacket
32+ import net.minecraft.util.math.Vec3d
33+ import java.awt.Color
34+ import java.util.concurrent.ConcurrentLinkedDeque
35+
36+ object BackTrack : Module(
37+ name = " BackTrack" ,
38+ description = " Gives reach advantage by delaying your packets" ,
39+ defaultTags = setOf(ModuleTag .MOVEMENT )
40+ ) {
41+ private val mode by setting(" Mode" , Mode .FIXED )
42+ private val delay by setting(" Delay" , 500 , 100 .. 2000 ) { mode == Mode .FIXED }
43+ private val maxDelay by setting(" Max Delay" , 1000 , 100 .. 2000 ) { mode == Mode .RANGED || mode == Mode .ADAPTIVE }
44+ private val distance by setting(" Distance" , 3.0 , 1.0 .. 5.0 , 0.1 ) { mode == Mode .RANGED || mode == Mode .ADAPTIVE }
45+
46+ private val target get() = if (KillAura .isDisabled) null else KillAura .target
47+ private var targetPos: Vec3d ? = null
48+
49+ private val box = DynamicAABB ()
50+
51+ private const val POSITION_PACKET_SCALE = 1 / 4096.0
52+ private val currentTime get() = System .currentTimeMillis()
53+ private val packetPool = ConcurrentLinkedDeque <Pair <ServerPacket , Long >>()
54+
55+ enum class Mode (val shouldSend : SafeContext .(Vec3d , Vec3d , Long ) -> Boolean ) {
56+ FIXED ({ _, _, timing ->
57+ currentTime > timing + delay
58+ }),
59+ RANGED ({ _, serverPos, timing ->
60+ val serverDist = player.pos dist serverPos
61+ currentTime > timing + maxDelay * serverDist.coerceIn(0.0 , distance) / distance
62+ }),
63+ ADAPTIVE ({ clientPos, serverPos, timing ->
64+ val clientDist = player.pos dist clientPos
65+ val serverDist = player.pos dist serverPos
66+ val advantage = serverDist - clientDist
67+ currentTime > timing + maxDelay * advantage.coerceIn(0.0 , distance) / distance
68+ })
69+ }
70+
71+ init {
72+ listener<TickEvent .Pre > {
73+ target?.let { target ->
74+ val pos = targetPos ? : target.pos
75+ targetPos = pos
76+
77+ box.update(target.boundingBox.offset(pos - target.pos))
78+ poolPackets()
79+ return @listener
80+ }
81+
82+ poolPackets(true )
83+ targetPos = null
84+ box.reset()
85+ }
86+
87+ listener<RenderEvent .DynamicESP > {
88+ val target = target ? : return @listener
89+
90+ val c1 = GuiSettings .primaryColor
91+ val c2 = Color .RED
92+ val p = target.hurtTime / 10.0
93+ val c = lerp(c1, c2, p)
94+
95+ it.renderer.build(box, c.multAlpha(0.3 ), c.multAlpha(0.8 ))
96+ }
97+
98+ listener<PacketEvent .Receive .Pre > { event ->
99+ val target = target ? : return @listener
100+
101+ val packet = event.packet
102+
103+ when (packet) {
104+ is EntityS2CPacket -> {
105+ if (target.id == packet.id) {
106+ targetPos = targetPos?.plus(
107+ Vec3d (
108+ packet.deltaX * POSITION_PACKET_SCALE ,
109+ packet.deltaY * POSITION_PACKET_SCALE ,
110+ packet.deltaZ * POSITION_PACKET_SCALE
111+ )
112+ )
113+ }
114+ }
115+
116+ is EntityPositionS2CPacket -> {
117+ if (target.id == packet.id) {
118+ targetPos = Vec3d (packet.x, packet.y, packet.z)
119+ }
120+ }
121+
122+ is PlaySoundS2CPacket , is PlaySoundFromEntityS2CPacket , is StopSoundS2CPacket ,
123+ /* is EntityStatusS2CPacket,*/ is EntityStatusEffectS2CPacket , is EntityAnimationS2CPacket ,
124+ is ParticleS2CPacket , is WorldTimeUpdateS2CPacket , is WorldEventS2CPacket -> {
125+ return @listener
126+ }
127+ }
128+
129+ packetPool.add(packet to currentTime)
130+ event.cancel()
131+ }
132+
133+ listener<ConnectionEvent .Connect > {
134+ packetPool.clear()
135+ }
136+
137+ onEnable {
138+ poolPackets(true )
139+ }
140+
141+ onDisable {
142+ poolPackets(true )
143+ }
144+ }
145+
146+ private fun SafeContext.poolPackets (all : Boolean = false) {
147+ while (packetPool.isNotEmpty()) {
148+ val (packet, timing) = packetPool.poll() ? : break
149+
150+ val send = all || targetPos?.let { serverPos ->
151+ target?.pos?.let { clientPos ->
152+ mode.shouldSend(this , clientPos, serverPos, timing)
153+ }
154+ } ? : true
155+
156+ if (! send) break
157+ connection.handlePacketSilently(packet)
158+ }
159+ }
160+ }
0 commit comments