Skip to content

Commit c4a0bb9

Browse files
committed
ElytraFlight2b2t Module
1 parent d8a8084 commit c4a0bb9

File tree

5 files changed

+479
-38
lines changed

5 files changed

+479
-38
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.lambda.mixin.accessor.network;
2+
3+
import net.minecraft.client.network.NetHandlerPlayClient;
4+
import org.spongepowered.asm.mixin.Mixin;
5+
import org.spongepowered.asm.mixin.gen.Accessor;
6+
7+
@Mixin(value = NetHandlerPlayClient.class)
8+
public interface AccessorNetHandlerPlayClient {
9+
10+
@Accessor(value = "doneLoadingTerrain")
11+
boolean isDoneLoadingTerrain();
12+
13+
@Accessor(value = "doneLoadingTerrain")
14+
void setDoneLoadingTerrain(boolean loaded);
15+
}
Lines changed: 380 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,380 @@
1+
package com.lambda.client.module.modules.movement
2+
3+
import baritone.api.pathing.goals.GoalXZ
4+
import com.lambda.client.event.SafeClientEvent
5+
import com.lambda.client.event.events.ConnectionEvent
6+
import com.lambda.client.event.events.PacketEvent
7+
import com.lambda.client.event.events.PlayerMoveEvent
8+
import com.lambda.client.event.events.PlayerTravelEvent
9+
import com.lambda.client.manager.managers.PlayerPacketManager.sendPlayerPacket
10+
import com.lambda.client.mixin.extension.tickLength
11+
import com.lambda.client.mixin.extension.timer
12+
import com.lambda.client.module.Category
13+
import com.lambda.client.module.Module
14+
import com.lambda.client.module.modules.player.ViewLock
15+
import com.lambda.client.util.BaritoneUtils
16+
import com.lambda.client.util.MovementUtils.setSpeed
17+
import com.lambda.client.util.TickTimer
18+
import com.lambda.client.util.TimeUnit
19+
import com.lambda.client.util.text.MessageSendHelper
20+
import com.lambda.client.util.threads.defaultScope
21+
import com.lambda.client.util.threads.safeListener
22+
import com.lambda.client.util.world.getGroundPos
23+
import kotlinx.coroutines.Job
24+
import kotlinx.coroutines.delay
25+
import kotlinx.coroutines.launch
26+
import net.minecraft.init.Items
27+
import net.minecraft.network.play.client.CPacketEntityAction
28+
import net.minecraft.network.play.client.CPacketPlayer
29+
import net.minecraft.network.play.server.SPacketPlayerPosLook
30+
import net.minecraft.util.math.BlockPos
31+
import net.minecraft.util.math.Vec2f
32+
import net.minecraft.util.math.Vec3d
33+
import net.minecraftforge.client.event.InputUpdateEvent
34+
import net.minecraftforge.fml.common.gameevent.TickEvent
35+
import kotlin.math.max
36+
import kotlin.math.min
37+
38+
object ElytraFlight2b2t : Module(
39+
name = "ElytraFlight2b2t",
40+
description = "Go very fast on 2b2t",
41+
category = Category.MOVEMENT,
42+
modulePriority = 1000
43+
) {
44+
private val takeoffTimerSpeed by setting("Takeoff Timer Tick Length", 395.0f, 100.0f..1000.0f, 1.0f,
45+
description = "How long each timer tick is during redeploy (ms). Lower length = faster timer. " +
46+
"Try increasing this if experiencing elytra timeout or rubberbands. This value is multiplied by 2 when setting timer")
47+
private val baritoneBlockagePathing by setting("Baritone Blockage Pathing", true,
48+
description = "Use baritone to path around blockages on the highway.")
49+
private val baritonePathForwardBlocks by setting("Baritone Path Distance", 20, 1..50, 1,
50+
visibility = { baritoneBlockagePathing })
51+
private val baritoneEndDelayMs by setting("Baritone End Pathing Delay Ms", 500, 0..2000, 50,
52+
visibility = { baritoneBlockagePathing })
53+
private val baritoneStartDelayMs by setting("Baritone Start Delay Ms", 500, 0..2000, 50,
54+
visibility = { baritoneBlockagePathing })
55+
private val midairFallFly by setting("Mid-flight Packet Deploy", true,
56+
description = "Uses packets to redeploy when mid-flight.")
57+
private val autoFlyForward by setting("Auto Fly Forward", true,
58+
description = "Automatically move forward when flying.")
59+
private val rubberBandDetectionTime by setting("Rubberband Detection Time", 1110, 0..2000, 10,
60+
description = "Time period (ms) between which to detect rubberband teleports. Lower period = more sensitive.")
61+
private val enableBoost by setting("Enable boost", true,
62+
description = "Enable boost during mid-air flight.")
63+
private val boostDelayTicks by setting("Boost delay ticks", 11, 1..200, 1,
64+
visibility = { enableBoost },
65+
description = "Number of ticks to wait before beginning boost")
66+
private val boostSpeedIncrease by setting("Boost speed increase", 0.65, 0.0..2.0, 0.01,
67+
visibility = { enableBoost },
68+
description = "Boost speed increase per tick (blocks per second / 2)")
69+
private val initialFlightSpeed by setting("Initial Flight Speed", 39.5, 35.0..80.0, 0.01,
70+
description = "Speed to start at for first successful deployment (blocks per second / 2).")
71+
private val speedMax by setting("Speed Max", 100.0, 40.0..100.0, 0.1,
72+
description = "Max flight speed (blocks per second / 2).")
73+
private val redeploySpeedDecreaseFactor by setting("Redeploy Speed Dec Factor", 1.1, 1.0..2.0, 0.01,
74+
description = "Decreases speed by a set factor during redeploys. Value is a divisor on current speed.")
75+
private val avoidUnloaded by setting("Avoid Unloaded", true,
76+
description = "Preserves speed while flying into unloaded chunks")
77+
private val autoViewLockManage by setting("Auto ViewLock Manage", true,
78+
description = "Automatically configures and toggles viewlock for straight flight on highways.")
79+
80+
private const val takeOffYVelocity: Double = -0.16976 // magic number - do not question
81+
private const val magicPitch = -2.52f
82+
private var currentState = State.PAUSED
83+
private var timer = TickTimer(TimeUnit.TICKS)
84+
private var currentFlightSpeed: Double = 40.2
85+
private var shouldStartBoosting: Boolean = false;
86+
private var elytraIsEquipped = false
87+
private var elytraDurability = 0
88+
private var wasInLiquid: Boolean = false
89+
private var isFlying: Boolean = false
90+
private var isStandingStill = false
91+
private var lastSPacketPlayerPosLook: Long = Long.MIN_VALUE
92+
private var lastRubberband: Long = Long.MIN_VALUE
93+
private var startedFlying: Boolean = false
94+
private var stoppedFlying: Boolean = false
95+
private var nextBlockMoveLoaded: Boolean = true
96+
private var flyTickCount = 0
97+
private var flyPlayerLastPos: Vec3d = Vec3d.ZERO
98+
private var flyBlockedTickCount = 0
99+
private var isBaritoning: Boolean = false
100+
private var baritoneStartTime: Long = 0L
101+
private var baritoneEndPathingTime: Long = 0L
102+
private var beforePathingPlayerPitchYaw= Vec2f.ZERO
103+
private var scheduleBaritoneJob: Job? = null
104+
private var motionPrev: Vec2f = Vec2f(0.0f, 0.0f)
105+
private const val jumpDelay: Int = 10
106+
107+
enum class State {
108+
FLYING, TAKEOFF, PAUSED, WALKING
109+
}
110+
111+
override fun getHudInfo(): String {
112+
return currentState.name
113+
}
114+
115+
init {
116+
117+
onEnable {
118+
currentState = State.PAUSED
119+
timer.reset()
120+
shouldStartBoosting = false
121+
lastRubberband = Long.MIN_VALUE
122+
if (autoViewLockManage)
123+
configureViewLock()
124+
}
125+
126+
onDisable {
127+
currentState = State.PAUSED
128+
resetFlightSpeed()
129+
BaritoneUtils.cancelEverything()
130+
shouldStartBoosting = false
131+
mc.timer.tickLength = 50.0f
132+
wasInLiquid = false
133+
isFlying = false
134+
if (autoViewLockManage)
135+
ViewLock.disable()
136+
}
137+
138+
safeListener<ConnectionEvent.Disconnect> {
139+
disable()
140+
}
141+
142+
safeListener<TickEvent.ClientTickEvent>(priority = 9999) {
143+
if (it.phase != TickEvent.Phase.END) return@safeListener
144+
when (currentState) {
145+
State.PAUSED -> {
146+
val armorSlot = player.inventory.armorInventory[2]
147+
elytraIsEquipped = armorSlot.item == Items.ELYTRA
148+
if (!elytraIsEquipped) {
149+
MessageSendHelper.sendChatMessage("No Elytra equipped")
150+
disable()
151+
return@safeListener
152+
}
153+
if (armorSlot.maxDamage <= 1) {
154+
MessageSendHelper.sendChatMessage("Equipped Elytra broken or almost broken")
155+
disable()
156+
return@safeListener
157+
}
158+
currentState = State.TAKEOFF
159+
}
160+
State.WALKING -> {
161+
if (autoViewLockManage && ViewLock.isEnabled) ViewLock.disable()
162+
if (scheduleBaritoneJob?.isActive == true) return@safeListener
163+
if (BaritoneUtils.isActive) {
164+
isBaritoning = true
165+
return@safeListener
166+
}
167+
// delay takeoff if we were pathing
168+
if (isBaritoning) {
169+
baritoneEndPathingTime = System.currentTimeMillis()
170+
mc.player.rotationPitch = beforePathingPlayerPitchYaw.x
171+
mc.player.rotationYaw = beforePathingPlayerPitchYaw.y
172+
isBaritoning = false
173+
return@safeListener
174+
}
175+
if (System.currentTimeMillis() - baritoneEndPathingTime < baritoneEndDelayMs) return@safeListener
176+
currentState = State.TAKEOFF
177+
}
178+
State.TAKEOFF -> {
179+
if (autoViewLockManage && ViewLock.isDisabled) ViewLock.enable()
180+
mc.timer.tickLength = 50.0f
181+
shouldStartBoosting = false
182+
resetFlightSpeed()
183+
if (baritoneBlockagePathing && player.onGround && timer.tick(jumpDelay.toLong())) player.jump()
184+
if ((withinRange(mc.player.motionY, takeOffYVelocity, 0.05)) && !mc.player.isElytraFlying) {
185+
timer.reset()
186+
currentState = State.FLYING
187+
} else if (midairFallFly && mc.player.isElytraFlying) {
188+
connection.sendPacket(CPacketPlayer(true))
189+
}
190+
}
191+
State.FLYING -> {
192+
if (autoViewLockManage && ViewLock.isDisabled) ViewLock.enable()
193+
if (!mc.player.isElytraFlying && flyTickCount++ > 30) {
194+
pathForward()
195+
currentState = State.WALKING
196+
} else flyTickCount = 0
197+
val playerCurrentPos = mc.player.positionVector
198+
if (!avoidUnloaded || (avoidUnloaded && nextBlockMoveLoaded)) {
199+
if (playerCurrentPos.distanceTo(flyPlayerLastPos) < 2.0) {
200+
if (flyBlockedTickCount++ > 20) {
201+
pathForward()
202+
currentState = State.WALKING
203+
}
204+
} else flyBlockedTickCount = 0
205+
}
206+
flyPlayerLastPos = playerCurrentPos
207+
if (!enableBoost) return@safeListener
208+
if (shouldStartBoosting) {
209+
if (avoidUnloaded) {
210+
if (nextBlockMoveLoaded && isFlying) setFlightSpeed(currentFlightSpeed + boostSpeedIncrease)
211+
} else setFlightSpeed(currentFlightSpeed + boostSpeedIncrease)
212+
} else if (timer.tick(boostDelayTicks, true)) shouldStartBoosting = true
213+
}
214+
}
215+
}
216+
217+
safeListener<PacketEvent.Receive> {
218+
if (it.packet !is SPacketPlayerPosLook || currentState != State.FLYING) return@safeListener
219+
timer.reset()
220+
if (System.currentTimeMillis() - lastSPacketPlayerPosLook < rubberBandDetectionTime.toLong()) {
221+
resetFlightSpeed()
222+
shouldStartBoosting = false
223+
mc.timer.tickLength = 50.0f
224+
wasInLiquid = false
225+
isFlying = false
226+
currentState = if (baritoneBlockagePathing) {
227+
pathForward()
228+
State.WALKING
229+
} else State.TAKEOFF
230+
lastRubberband = System.currentTimeMillis()
231+
}
232+
lastSPacketPlayerPosLook = System.currentTimeMillis()
233+
}
234+
235+
safeListener<PacketEvent.Send> {
236+
if (avoidUnloaded && !nextBlockMoveLoaded && it.packet is CPacketPlayer)
237+
it.cancel()
238+
}
239+
240+
safeListener<PlayerTravelEvent> {
241+
stateUpdate()
242+
if (currentState == State.FLYING && elytraIsEquipped && elytraDurability > 1) {
243+
if (stoppedFlying) setFlightSpeed(currentFlightSpeed / redeploySpeedDecreaseFactor)
244+
if (isFlying) {
245+
mc.timer.tickLength = 50.0f
246+
player.isSprinting = false
247+
} else takeoff(it)
248+
}
249+
// rotation spoof also kicks us out of elytra during glide takeoffs due to rotation not matching flight speed
250+
spoofRotation()
251+
}
252+
253+
safeListener<PlayerMoveEvent> {
254+
if (currentState == State.FLYING) {
255+
if (avoidUnloaded) {
256+
if (nextBlockMoveLoaded && !mc.world.isBlockLoaded(BlockPos(mc.player.posX + it.x, mc.player.posY, mc.player.posZ + it.z), false)) {
257+
nextBlockMoveLoaded = false
258+
motionPrev = Vec2f(it.x.toFloat(), it.z.toFloat())
259+
setSpeed(0.0)
260+
player.motionY = 0.0
261+
return@safeListener
262+
} else if (!nextBlockMoveLoaded) {
263+
if (!mc.world.isBlockLoaded(BlockPos(mc.player.posX + motionPrev.x, 1.0, mc.player.posZ + motionPrev.y), false)) {
264+
setSpeed(0.0)
265+
player.motionY = 0.0
266+
return@safeListener
267+
}
268+
}
269+
}
270+
setSpeed(currentFlightSpeed / 10.0)
271+
player.motionY = 0.0
272+
}
273+
nextBlockMoveLoaded = true
274+
}
275+
276+
safeListener<InputUpdateEvent> {
277+
if (autoFlyForward && (currentState == State.FLYING || currentState == State.TAKEOFF) && !mc.player.onGround) {
278+
it.movementInput.moveStrafe = 0.0f
279+
it.movementInput.moveForward = 1.0f
280+
}
281+
}
282+
}
283+
284+
private fun withinRange(num: Double, target: Double, range: Double): Boolean {
285+
return (num >= target - range && num <= target + range)
286+
}
287+
288+
private fun resetFlightSpeed() {
289+
setFlightSpeed(this.initialFlightSpeed)
290+
}
291+
292+
private fun setFlightSpeed(speed: Double) {
293+
currentFlightSpeed = max(initialFlightSpeed, min(speed, speedMax))
294+
}
295+
296+
private fun SafeClientEvent.stateUpdate() {
297+
/* Elytra Check */
298+
val armorSlot = player.inventory.armorInventory[2]
299+
elytraIsEquipped = armorSlot.item == Items.ELYTRA
300+
301+
/* Elytra Durability Check */
302+
if (elytraIsEquipped) {
303+
elytraDurability = armorSlot.maxDamage - armorSlot.itemDamage
304+
} else elytraDurability = 0
305+
306+
/* wasInLiquid check */
307+
if (player.isInWater || player.isInLava) {
308+
wasInLiquid = true
309+
} else if (player.onGround || isFlying) {
310+
wasInLiquid = false
311+
}
312+
313+
/* Elytra flying status check */
314+
startedFlying = !isFlying && player.isElytraFlying
315+
stoppedFlying = isFlying && !player.isElytraFlying
316+
isFlying = player.isElytraFlying
317+
318+
/* Movement input check */
319+
val isStandingStillH = player.movementInput.moveForward == 0f && player.movementInput.moveStrafe == 0f
320+
isStandingStill = isStandingStillH && !player.movementInput.jump && !player.movementInput.sneak
321+
}
322+
323+
private fun SafeClientEvent.takeoff(event: PlayerTravelEvent) {
324+
val timerSpeed = takeoffTimerSpeed
325+
val height = 0.1
326+
val closeToGround = player.posY <= world.getGroundPos(player).y + height && !wasInLiquid && !mc.isSingleplayer
327+
if (player.motionY >= -0.02) return
328+
if (closeToGround) {
329+
mc.timer.tickLength = 50.0f
330+
return
331+
}
332+
if (!wasInLiquid && !mc.isSingleplayer) {
333+
event.cancel()
334+
player.setVelocity(0.0, -0.02, 0.0)
335+
}
336+
if (!mc.isSingleplayer) mc.timer.tickLength = timerSpeed * 2.0f
337+
connection.sendPacket(CPacketEntityAction(player, CPacketEntityAction.Action.START_FALL_FLYING))
338+
}
339+
340+
private fun SafeClientEvent.spoofRotation() {
341+
if (player.isSpectator || !elytraIsEquipped || elytraDurability <= 1 || !isFlying) return
342+
var rotation = com.lambda.client.util.math.Vec2f(player)
343+
if (!isStandingStill) rotation = com.lambda.client.util.math.Vec2f(rotation.x, magicPitch)
344+
/* Cancels rotation packets if player is not moving and not clicking */
345+
var cancelRotation = isStandingStill
346+
&& ((!mc.gameSettings.keyBindUseItem.isKeyDown && !mc.gameSettings.keyBindAttack.isKeyDown))
347+
sendPlayerPacket {
348+
if (cancelRotation) {
349+
cancelRotate()
350+
} else {
351+
rotate(rotation)
352+
}
353+
}
354+
}
355+
356+
private fun SafeClientEvent.pathForward() {
357+
beforePathingPlayerPitchYaw = mc.player.pitchYaw
358+
if (scheduleBaritoneJob?.isActive == true) return
359+
baritoneStartTime = System.currentTimeMillis()
360+
scheduleBaritoneJob = defaultScope.launch {
361+
delay(baritoneStartDelayMs.toLong())
362+
val playerContext = BaritoneUtils.primary?.playerContext!!
363+
BaritoneUtils.primary?.customGoalProcess?.setGoalAndPath(GoalXZ.fromDirection(
364+
playerContext.playerFeetAsVec(),
365+
playerContext.player().rotationYawHead,
366+
baritonePathForwardBlocks.toDouble()
367+
))
368+
}
369+
}
370+
371+
private fun configureViewLock() {
372+
ViewLock.mode.value = ViewLock.Mode.TRADITIONAL
373+
ViewLock.yaw.value = true
374+
ViewLock.autoYaw.value = true
375+
ViewLock.hardAutoYaw.value = true
376+
ViewLock.disableMouseYaw.value = true
377+
ViewLock.yawSlice.value = 8
378+
ViewLock.pitch.value = false
379+
}
380+
}

0 commit comments

Comments
 (0)