Skip to content

Commit 7d37d75

Browse files
Doogie13Avanatiker
andauthored
Add 85km/h YPort mode to Speed (#288)
* Add Boost to Speed, settings edited on other modes to be better compliant with NCP * Fix Boost speed, now fully functional * Fix formatting * Other fixes * Removed Boost mode and added YPort mode (disabling accelerate is the same as old boost mode) * Add some settings, these are in the video * YPort update No32767 Added maximum speed slider Added Air Strict mode to emulate Y motion better Inflicted pain on Doogie13 * Fixed YPort AirStrict to make it calculate motion properly this time Removed debug messages * Clean up * Clean up 2 * Another cleanup * Added working 42 km/h overhead strafe for 2b Co-authored-by: Constructor <fractalminds@protonmail.com>
1 parent 138d339 commit 7d37d75

File tree

3 files changed

+197
-67
lines changed

3 files changed

+197
-67
lines changed

src/main/kotlin/com/lambda/client/module/modules/combat/HoleSnap.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ object HoleSnap : Module(
9494
}
9595

9696
getHole()?.let {
97-
if (disableStrafe && Speed.mode == Speed.SpeedMode.STRAFE) Speed.disable()
97+
if (disableStrafe && Speed.mode.value == Speed.SpeedMode.STRAFE) Speed.disable()
9898
if ((airStrafe || player.onGround) && !player.isCentered(it)) {
9999
val playerPos = player.positionVector
100100
val targetPos = Vec3d(it.x + 0.5, player.posY, it.z + 0.5)

src/main/kotlin/com/lambda/client/module/modules/combat/Surround.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ object Surround : Module(
101101
// Centered check
102102
if (!player.centerPlayer()) return@safeListener
103103

104-
if (disableStrafe && Speed.mode == Speed.SpeedMode.STRAFE) {
104+
if (disableStrafe && Speed.mode.value == Speed.SpeedMode.STRAFE) {
105105
Speed.disable()
106106
}
107107

Original file line numberDiff line numberDiff line change
@@ -1,150 +1,207 @@
11
package com.lambda.client.module.modules.movement
22

3+
import com.lambda.client.commons.interfaces.DisplayEnum
34
import com.lambda.client.event.SafeClientEvent
5+
import com.lambda.client.event.events.PacketEvent
46
import com.lambda.client.event.events.PlayerMoveEvent
57
import com.lambda.client.event.events.PlayerTravelEvent
68
import com.lambda.client.manager.managers.TimerManager.modifyTimer
79
import com.lambda.client.manager.managers.TimerManager.resetTimer
810
import com.lambda.client.mixin.extension.isInWeb
11+
import com.lambda.client.mixin.extension.playerY
912
import com.lambda.client.module.Category
1013
import com.lambda.client.module.Module
11-
import com.lambda.client.module.modules.player.AutoEat
1214
import com.lambda.client.util.BaritoneUtils
13-
import com.lambda.client.util.EntityUtils.flooredPosition
1415
import com.lambda.client.util.EntityUtils.isInOrAboveLiquid
1516
import com.lambda.client.util.MovementUtils
1617
import com.lambda.client.util.MovementUtils.applySpeedPotionEffects
1718
import com.lambda.client.util.MovementUtils.calcMoveYaw
18-
import com.lambda.client.util.MovementUtils.isMoving
1919
import com.lambda.client.util.MovementUtils.setSpeed
2020
import com.lambda.client.util.MovementUtils.speed
2121
import com.lambda.client.util.TickTimer
2222
import com.lambda.client.util.TimeUnit
2323
import com.lambda.client.util.threads.runSafe
2424
import com.lambda.client.util.threads.safeListener
2525
import net.minecraft.client.settings.KeyBinding
26+
import net.minecraft.network.play.client.CPacketPlayer
27+
import net.minecraft.network.play.server.SPacketPlayerPosLook
2628
import net.minecraftforge.fml.common.gameevent.TickEvent
2729
import java.lang.Double.max
30+
import java.lang.Double.min
2831
import kotlin.math.cos
32+
import kotlin.math.hypot
2933
import kotlin.math.sin
3034

35+
3136
object 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

Comments
 (0)