11package com.lambda.client.module.modules.movement
22
3+ import com.lambda.client.commons.interfaces.DisplayEnum
34import com.lambda.client.event.SafeClientEvent
5+ import com.lambda.client.event.events.PacketEvent
46import com.lambda.client.event.events.PlayerMoveEvent
57import com.lambda.client.event.events.PlayerTravelEvent
68import com.lambda.client.manager.managers.TimerManager.modifyTimer
79import com.lambda.client.manager.managers.TimerManager.resetTimer
810import com.lambda.client.mixin.extension.isInWeb
11+ import com.lambda.client.mixin.extension.playerY
912import com.lambda.client.module.Category
1013import com.lambda.client.module.Module
11- import com.lambda.client.module.modules.player.AutoEat
1214import com.lambda.client.util.BaritoneUtils
13- import com.lambda.client.util.EntityUtils.flooredPosition
1415import com.lambda.client.util.EntityUtils.isInOrAboveLiquid
1516import com.lambda.client.util.MovementUtils
1617import com.lambda.client.util.MovementUtils.applySpeedPotionEffects
1718import com.lambda.client.util.MovementUtils.calcMoveYaw
18- import com.lambda.client.util.MovementUtils.isMoving
1919import com.lambda.client.util.MovementUtils.setSpeed
2020import com.lambda.client.util.MovementUtils.speed
2121import com.lambda.client.util.TickTimer
2222import com.lambda.client.util.TimeUnit
2323import com.lambda.client.util.threads.runSafe
2424import com.lambda.client.util.threads.safeListener
2525import net.minecraft.client.settings.KeyBinding
26+ import net.minecraft.network.play.client.CPacketPlayer
27+ import net.minecraft.network.play.server.SPacketPlayerPosLook
2628import net.minecraftforge.fml.common.gameevent.TickEvent
2729import java.lang.Double.max
30+ import java.lang.Double.min
2831import kotlin.math.cos
32+ import kotlin.math.hypot
2933import kotlin.math.sin
3034
35+
3136object Speed : Module(
3237 name = " Speed" ,
3338 description = " Move faster" ,
3439 category = Category .MOVEMENT ,
3540 modulePriority = 100
3641) {
3742 // General settings
38- val mode by setting(" Mode" , SpeedMode .STRAFE )
39-
40- // strafe settings
41- private val strafeAirSpeedBoost by setting(" Air Speed Boost" , 0.029f , 0.01f .. 0.04f , 0.001f , { mode == SpeedMode .STRAFE })
42- private val strafeTimerBoost by setting(" Timer Boost" , true , { mode == SpeedMode .STRAFE })
43- private val strafeAutoJump by setting(" Auto Jump" , true , { mode == SpeedMode .STRAFE })
44- private val strafeOnHoldingSprint by setting(" On Holding Sprint" , false , { mode == SpeedMode .STRAFE })
45- private val strafeCancelInertia by setting(" Cancel Inertia" , false , { mode == SpeedMode .STRAFE })
46-
47- // onGround settings
48- private val onGroundTimer by setting(" Timer" , true , { mode == SpeedMode .ONGROUND })
49- private val onGroundTimerSpeed by setting(" Timer Speed" , 1.29f , 1.0f .. 2.0f , 0.01f , { mode == SpeedMode .ONGROUND && onGroundTimer })
50- private val onGroundSpeed by setting(" Speed" , 1.31f , 1.0f .. 2.0f , 0.01f , { mode == SpeedMode .ONGROUND })
51- private val onGroundSprint by setting(" Sprint" , true , { mode == SpeedMode .ONGROUND })
52- private val onGroundCheckAbove by setting(" Smart Mode" , true , { mode == SpeedMode .ONGROUND })
43+ val mode = setting(" Mode" , SpeedMode .STRAFE )
44+
45+ // Strafe settings
46+ private val strafeAirSpeedBoost by setting(" Air Speed Boost" , 0.028f , 0.01f .. 0.04f , 0.001f , { mode.value == SpeedMode .STRAFE })
47+ private val strafeTimerBoost by setting(" Timer Boost" , true , { mode.value == SpeedMode .STRAFE })
48+ private val strafeAutoJump by setting(" Auto Jump" , true , { mode.value == SpeedMode .STRAFE }, description = " WARNING: Food intensive!" )
49+ private val strafeOnlyOverhead by setting(" Only strafe on overhead" , false , { mode.value == SpeedMode .STRAFE && strafeAutoJump })
50+ private val strafeOnHoldingSprint by setting(" On Holding Sprint" , false , { mode.value == SpeedMode .STRAFE })
51+ private val strafeCancelInertia by setting(" Cancel Inertia" , false , { mode.value == SpeedMode .STRAFE })
52+
53+ // YPort settings
54+ private val yPortAccelerate by setting(" Accelerate" , true , { mode.value == SpeedMode .YPORT })
55+ private val yPortStrict by setting(" Head Strict" , false , { mode.value == SpeedMode .YPORT }, description = " Only allow YPort when you are under a block" )
56+ private val yPortAirStrict by setting(" Air Strict" , false , { mode.value == SpeedMode .YPORT }, description = " Force YPort to handle Y movement differently, slows this down A LOT" )
57+ private val yPortMaxSpeed by setting(" Maximum Speed" , 0.0 , 0.0 .. 2.0 , 0.001 , { mode.value == SpeedMode .YPORT })
58+ private val yPortAcceleration by setting(" Acceleration Speed" , 2.149 , 1.0 .. 5.0 , 0.001 , { mode.value == SpeedMode .YPORT })
59+ private val yPortDecay by setting(" Decay Amount" , 0.66 , 0.0 .. 1.0 , 0.001 , { mode.value == SpeedMode .YPORT })
60+
61+ private const val TIMER_SPEED = 45.955883f
5362
5463 // Strafe Mode
5564 private var jumpTicks = 0
5665 private val strafeTimer = TickTimer (TimeUnit .TICKS )
5766
58- // onGround Mode
59- private var wasSprintEnabled = Sprint .isEnabled
67+ // yport stuff
68+ private var currentSpeed = .2873
69+ private var currentY = 0.0
70+ private var phase: YPortPhase = YPortPhase .WALKING
71+ private var prevPhase: YPortPhase = YPortPhase .WALKING
72+ private var goUp = false
73+ private var lastDistance = 0.0
6074
61- private var currentMode = mode
75+ private enum class YPortPhase {
76+ // to help with bypassing right after setback
77+ WAITING ,
78+ // to get some speed initially
79+ WALKING ,
80+ // to jump and accelerate
81+ ACCELERATING ,
82+ // to fall to the ground
83+ SLOWDOWN ,
84+ // to slowly fall to the ground
85+ FALLING
86+ }
6287
63- enum class SpeedMode {
64- STRAFE , ONGROUND
88+ enum class SpeedMode (override val displayName : String ) : DisplayEnum {
89+ STRAFE (" Strafe" ),
90+ YPORT (" YPort" )
6591 }
6692
6793 init {
6894 onEnable {
69- wasSprintEnabled = Sprint .isEnabled
95+ currentSpeed = .2873
96+ phase = YPortPhase .WALKING
97+ prevPhase = YPortPhase .WALKING
98+ goUp = false
99+ currentY = 0.0
70100 }
71101
72102 onDisable {
73- if (! wasSprintEnabled && mode == SpeedMode .ONGROUND ) Sprint .disable()
74103 runSafe {
75104 reset()
76105 }
77106 }
78107
79108 safeListener<TickEvent .ClientTickEvent > {
80- if (mode != currentMode) {
81- currentMode = mode
82- reset()
83- }
84-
85- if (mode == SpeedMode .ONGROUND && Sprint .isDisabled && onGroundSprint) Sprint .enable()
86- }
87-
88- safeListener<PlayerTravelEvent > {
89- if (mode == SpeedMode .STRAFE && shouldStrafe()) strafe()
109+ lastDistance = hypot(player.posX - player.prevPosX, player.posZ - player.prevPosZ)
110+ if (mode.value == SpeedMode .STRAFE
111+ && shouldStrafe()
112+ ) strafe()
90113 }
91114
92115 safeListener<PlayerMoveEvent > {
93- when (mode) {
116+ when (mode.value ) {
94117 SpeedMode .STRAFE -> {
95- if (shouldStrafe()) setSpeed(max(player.speed, applySpeedPotionEffects(0.2873 )))
96- else {
118+ if (shouldStrafe()) {
119+ setSpeed(max(player.speed, applySpeedPotionEffects(0.2873 )))
120+ } else {
97121 reset()
98122 if (strafeCancelInertia && ! strafeTimer.tick(2L , false )) {
99123 player.motionX = 0.0
100124 player.motionZ = 0.0
101125 }
102126 }
103127 }
104- SpeedMode .ONGROUND -> {
105- if (shouldOnGround()) onGround()
106- else resetTimer()
128+
129+ SpeedMode .YPORT -> {
130+ handleBoost(it)
131+ }
132+ }
133+ }
134+
135+ safeListener<PacketEvent .Send > {
136+ if (mode.value != SpeedMode .YPORT
137+ || it.packet !is CPacketPlayer
138+ || ! goUp
139+ ) return @safeListener
140+
141+ var offset = .42
142+
143+ // .015625 is the largest number that block heights are always divisible
144+ while (world.collidesWithAnyBlock(player.entityBoundingBox.offset(.0 , offset, .0 ))) {
145+ if (offset <= 0 )
146+ break
147+
148+ offset - = .015625
149+ }
150+
151+ val unModOffset = offset
152+
153+ if (currentY + unModOffset > 0 )
154+ offset + = currentY
155+ else if (yPortAirStrict && phase == YPortPhase .FALLING && prevPhase == YPortPhase .FALLING ) {
156+
157+ var predictedY = currentY
158+ predictedY - = 0.08
159+ predictedY * = 0.9800000190734863 // 0.333200006 vs 0.341599999
160+
161+ if (predictedY + player.posY <= player.posY) {
162+ phase = YPortPhase .WAITING
107163 }
108164 }
165+
166+ it.packet.playerY = (offset + player.posY)
167+
168+ currentY = offset - unModOffset
169+ }
170+
171+ safeListener<PacketEvent .Receive > {
172+ if (mode.value != SpeedMode .YPORT || it.packet !is SPacketPlayerPosLook ) return @safeListener
173+
174+ currentSpeed = 0.0
175+ currentY = 0.0
176+ goUp = false
177+ // 3 extra ticks at base speed
178+ phase = YPortPhase .WAITING
179+ }
180+
181+ mode.listeners.add {
182+ runSafe { reset() }
109183 }
110184 }
111185
112186 private fun SafeClientEvent.strafe () {
113187 player.jumpMovementFactor = strafeAirSpeedBoost
114- if (strafeTimerBoost) modifyTimer( 45.87156f )
115- if (( Step .isDisabled || ! player.collidedHorizontally) && strafeAutoJump) jump( )
188+ // slightly slower timer speed bypasses better (1.088 )
189+ if (strafeTimerBoost) modifyTimer( TIMER_SPEED )
116190
117- strafeTimer.reset()
118- }
191+ if ((Step .isDisabled || player.onGround) && strafeAutoJump) jump()
119192
120- private fun SafeClientEvent.onGround () {
121- if (onGroundTimer) modifyTimer(50.0f / onGroundTimerSpeed)
122- else resetTimer()
123-
124- player.motionX * = onGroundSpeed
125- player.motionZ * = onGroundSpeed
193+ strafeTimer.reset()
126194 }
127195
128196 private fun SafeClientEvent.shouldStrafe (): Boolean =
129- ( ! player.capabilities.isFlying
197+ ! player.capabilities.isFlying
130198 && ! player.isElytraFlying
131199 && ! mc.gameSettings.keyBindSneak.isKeyDown
132200 && (! strafeOnHoldingSprint || mc.gameSettings.keyBindSprint.isKeyDown)
133201 && ! BaritoneUtils .isPathing
134202 && MovementUtils .isInputting
135- && ! (player.isInOrAboveLiquid || player.isInWeb))
136-
137- private fun SafeClientEvent.shouldOnGround (): Boolean =
138- (world.getBlockState(player.flooredPosition.add(0.0 , 2.0 , 0.0 )).material.isSolid || ! onGroundCheckAbove)
139- && ! AutoEat .eating
140- && player.isMoving
141- && MovementUtils .isInputting
142- && ! player.movementInput.sneak
143- && player.onGround
144203 && ! (player.isInOrAboveLiquid || player.isInWeb)
145- && ! player.capabilities.isFlying
146- && ! player.isElytraFlying
147- && ! mc.gameSettings.keyBindSneak.isKeyDown
204+ && (! strafeOnlyOverhead || world.collidesWithAnyBlock(player.entityBoundingBox.offset(.0 ,.42 ,.0 )))
148205
149206 private fun SafeClientEvent.reset () {
150207 player.jumpMovementFactor = 0.02f
@@ -168,4 +225,77 @@ object Speed : Module(
168225
169226 jumpTicks--
170227 }
171- }
228+
229+ private fun SafeClientEvent.handleBoost (event : PlayerMoveEvent ) {
230+ if (player.movementInput.moveForward == 0f && player.movementInput.moveStrafe == 0f
231+ || player.isInOrAboveLiquid
232+ || mc.gameSettings.keyBindJump.isKeyDown
233+ || ! player.onGround
234+ || ! world.collidesWithAnyBlock(player.entityBoundingBox.offset(0.0 , 0.42 , 0.0 )) && yPortStrict
235+ ) {
236+ resetTimer()
237+ currentSpeed = .2873
238+ return
239+ }
240+
241+ modifyTimer(TIMER_SPEED )
242+
243+ prevPhase = phase
244+
245+ when (phase) {
246+ YPortPhase .ACCELERATING -> {
247+ // NCP says hDistance < 2.15 * hDistanceBaseRef
248+ currentSpeed * = yPortAcceleration
249+ phase = if (yPortAirStrict) YPortPhase .FALLING else YPortPhase .SLOWDOWN
250+ goUp = true
251+ currentY = 0.0
252+ }
253+
254+ YPortPhase .SLOWDOWN -> {
255+ // NCP says hDistDiff >= 0.66 * (lastMove.hDistance - hDistanceBaseRef)
256+ currentSpeed = if (yPortAccelerate) {
257+ lastDistance - yPortDecay * (lastDistance - .2873 )
258+ } else {
259+ .2873
260+ }
261+ phase = YPortPhase .ACCELERATING
262+ goUp = false
263+ }
264+
265+ YPortPhase .FALLING -> {
266+ if (prevPhase == YPortPhase .WALKING ) {
267+ currentSpeed = if (yPortAccelerate) {
268+ lastDistance - yPortDecay * (lastDistance - .2873 )
269+ } else {
270+ .2873
271+ }
272+ }
273+
274+ goUp = true
275+
276+ currentSpeed - = currentSpeed / 159
277+
278+ currentY - = 0.08
279+ currentY * = 0.9800000190734863
280+ }
281+
282+ else -> {
283+ currentSpeed = max(currentSpeed, .2873 )
284+ phase = YPortPhase .values()[phase.ordinal + 1 % YPortPhase .values().size]
285+ goUp = false
286+ }
287+ }
288+
289+ val yaw = calcMoveYaw()
290+
291+ if (yPortMaxSpeed != 0.0 ) {
292+ currentSpeed = currentSpeed.coerceAtMost(yPortMaxSpeed)
293+ }
294+
295+ event.x = - sin(yaw) * currentSpeed
296+ event.y = min(0.0 , event.y)
297+ event.z = cos(yaw) * currentSpeed
298+
299+ player.setVelocity(event.x, event.y, event.z)
300+ }
301+ }
0 commit comments