Skip to content

Commit b9374bc

Browse files
authored
Merge pull request #577 from rfresh2/elytraflight2b2t-lite
ElytraFlight2b2t Module
2 parents d8a8084 + 55f2528 commit b9374bc

File tree

5 files changed

+488
-38
lines changed

5 files changed

+488
-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: 383 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,383 @@
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.manager.managers.TimerManager.modifyTimer
11+
import com.lambda.client.manager.managers.TimerManager.resetTimer
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, 5.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", unit = "ms")
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", 500, 0..2000, 50,
52+
visibility = { baritoneBlockagePathing }, unit = "ms")
53+
private val baritoneStartDelayMs by setting("Baritone Start Delay", 500, 0..2000, 50,
54+
visibility = { baritoneBlockagePathing }, unit = "ms")
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.", unit = "ms")
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", 11, 1..200, 1,
64+
visibility = { enableBoost }, unit = "ticks",
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 TAKE_OFF_Y_VELOCITY = -0.16976 // magic number - do not question
81+
private const val MAGIC_PITCH = -2.52f
82+
private const val JUMP_DELAY = 10
83+
84+
private var currentState = State.PAUSED
85+
private var isFlying = false
86+
private var isBaritoning = false
87+
88+
private var timer = TickTimer(TimeUnit.TICKS)
89+
private var lastSPacketPlayerPosLook = Long.MIN_VALUE
90+
private var lastRubberband = Long.MIN_VALUE
91+
private var baritoneStartTime = 0L
92+
private var baritoneEndPathingTime = 0L
93+
94+
private var shouldStartBoosting = false
95+
private var elytraIsEquipped = false
96+
private var wasInLiquid = false
97+
private var isStandingStill = false
98+
private var startedFlying = false
99+
private var stoppedFlying = false
100+
private var nextBlockMoveLoaded = true
101+
102+
private var elytraDurability = 0
103+
private var flyTickCount = 0
104+
private var flyBlockedTickCount = 0
105+
private var currentFlightSpeed = 40.2
106+
107+
private var flyPlayerLastPos = Vec3d.ZERO
108+
private var beforePathingPlayerPitchYaw = Vec2f.ZERO
109+
private var motionPrev = Vec2f(0.0f, 0.0f)
110+
111+
private var scheduleBaritoneJob: Job? = null
112+
113+
enum class State {
114+
FLYING, TAKEOFF, PAUSED, WALKING
115+
}
116+
117+
override fun getHudInfo() = currentState.name
118+
119+
init {
120+
onEnable {
121+
currentState = State.PAUSED
122+
timer.reset()
123+
shouldStartBoosting = false
124+
lastRubberband = Long.MIN_VALUE
125+
if (autoViewLockManage) configureViewLock()
126+
}
127+
128+
onDisable {
129+
currentState = State.PAUSED
130+
resetFlightSpeed()
131+
BaritoneUtils.cancelEverything()
132+
shouldStartBoosting = false
133+
resetTimer()
134+
wasInLiquid = false
135+
isFlying = false
136+
if (autoViewLockManage) ViewLock.disable()
137+
}
138+
139+
safeListener<ConnectionEvent.Disconnect> {
140+
disable()
141+
}
142+
143+
safeListener<TickEvent.ClientTickEvent>(priority = 9999) {
144+
if (it.phase != TickEvent.Phase.END) return@safeListener
145+
when (currentState) {
146+
State.PAUSED -> {
147+
val armorSlot = player.inventory.armorInventory[2]
148+
elytraIsEquipped = armorSlot.item == Items.ELYTRA
149+
if (!elytraIsEquipped) {
150+
MessageSendHelper.sendChatMessage("No Elytra equipped")
151+
disable()
152+
return@safeListener
153+
}
154+
if (armorSlot.maxDamage <= 1) {
155+
MessageSendHelper.sendChatMessage("Equipped Elytra broken or almost broken")
156+
disable()
157+
return@safeListener
158+
}
159+
currentState = State.TAKEOFF
160+
}
161+
State.WALKING -> {
162+
if (autoViewLockManage && ViewLock.isEnabled) ViewLock.disable()
163+
if (scheduleBaritoneJob?.isActive == true) return@safeListener
164+
if (BaritoneUtils.isActive) {
165+
isBaritoning = true
166+
return@safeListener
167+
}
168+
// delay takeoff if we were pathing
169+
if (isBaritoning) {
170+
baritoneEndPathingTime = System.currentTimeMillis()
171+
player.rotationPitch = beforePathingPlayerPitchYaw.x
172+
player.rotationYaw = beforePathingPlayerPitchYaw.y
173+
isBaritoning = false
174+
return@safeListener
175+
}
176+
if (System.currentTimeMillis() - baritoneEndPathingTime < baritoneEndDelayMs) return@safeListener
177+
currentState = State.TAKEOFF
178+
}
179+
State.TAKEOFF -> {
180+
if (autoViewLockManage && ViewLock.isDisabled) ViewLock.enable()
181+
resetTimer()
182+
shouldStartBoosting = false
183+
resetFlightSpeed()
184+
if (baritoneBlockagePathing && player.onGround && timer.tick(JUMP_DELAY.toLong())) player.jump()
185+
if ((withinRange(player.motionY)) && !player.isElytraFlying) {
186+
timer.reset()
187+
currentState = State.FLYING
188+
} else if (midairFallFly && player.isElytraFlying) {
189+
connection.sendPacket(CPacketPlayer(true))
190+
}
191+
}
192+
State.FLYING -> {
193+
if (autoViewLockManage && ViewLock.isDisabled) ViewLock.enable()
194+
if (!player.isElytraFlying && flyTickCount++ > 30) {
195+
pathForward()
196+
currentState = State.WALKING
197+
} else flyTickCount = 0
198+
val playerCurrentPos = player.positionVector
199+
if (!avoidUnloaded || (avoidUnloaded && nextBlockMoveLoaded)) {
200+
if (playerCurrentPos.distanceTo(flyPlayerLastPos) < 2.0) {
201+
if (flyBlockedTickCount++ > 20) {
202+
pathForward()
203+
currentState = State.WALKING
204+
}
205+
} else flyBlockedTickCount = 0
206+
}
207+
flyPlayerLastPos = playerCurrentPos
208+
if (!enableBoost) return@safeListener
209+
if (shouldStartBoosting) {
210+
if (avoidUnloaded) {
211+
if (nextBlockMoveLoaded && isFlying) {
212+
setFlightSpeed(currentFlightSpeed + boostSpeedIncrease)
213+
}
214+
} else setFlightSpeed(currentFlightSpeed + boostSpeedIncrease)
215+
} else if (timer.tick(boostDelayTicks, true)) shouldStartBoosting = true
216+
}
217+
}
218+
}
219+
220+
safeListener<PacketEvent.Receive> {
221+
if (it.packet !is SPacketPlayerPosLook || currentState != State.FLYING) return@safeListener
222+
timer.reset()
223+
if (System.currentTimeMillis() - lastSPacketPlayerPosLook < rubberBandDetectionTime.toLong()) {
224+
resetFlightSpeed()
225+
shouldStartBoosting = false
226+
resetTimer()
227+
wasInLiquid = false
228+
isFlying = false
229+
currentState = if (baritoneBlockagePathing) {
230+
pathForward()
231+
State.WALKING
232+
} else State.TAKEOFF
233+
lastRubberband = System.currentTimeMillis()
234+
}
235+
lastSPacketPlayerPosLook = System.currentTimeMillis()
236+
}
237+
238+
safeListener<PacketEvent.Send> {
239+
if (avoidUnloaded && !nextBlockMoveLoaded && it.packet is CPacketPlayer) it.cancel()
240+
}
241+
242+
safeListener<PlayerTravelEvent> {
243+
stateUpdate()
244+
if (currentState == State.FLYING && elytraIsEquipped && elytraDurability > 1) {
245+
if (stoppedFlying) setFlightSpeed(currentFlightSpeed / redeploySpeedDecreaseFactor)
246+
if (isFlying) {
247+
resetTimer()
248+
player.isSprinting = false
249+
} else takeoff(it)
250+
}
251+
// rotation spoof also kicks us out of elytra during glide takeoffs due to rotation not matching flight speed
252+
spoofRotation()
253+
}
254+
255+
safeListener<PlayerMoveEvent> {
256+
if (currentState == State.FLYING) {
257+
if (avoidUnloaded) {
258+
if (nextBlockMoveLoaded && !world.isBlockLoaded(BlockPos(player.posX + it.x, player.posY, player.posZ + it.z), false)) {
259+
nextBlockMoveLoaded = false
260+
motionPrev = Vec2f(it.x.toFloat(), it.z.toFloat())
261+
setSpeed(0.0)
262+
player.motionY = 0.0
263+
return@safeListener
264+
} else if (!nextBlockMoveLoaded) {
265+
if (!world.isBlockLoaded(BlockPos(player.posX + motionPrev.x, 1.0, player.posZ + motionPrev.y), false)) {
266+
setSpeed(0.0)
267+
player.motionY = 0.0
268+
return@safeListener
269+
}
270+
}
271+
}
272+
setSpeed(currentFlightSpeed / 10.0)
273+
player.motionY = 0.0
274+
}
275+
nextBlockMoveLoaded = true
276+
}
277+
278+
safeListener<InputUpdateEvent> {
279+
if (autoFlyForward && (currentState == State.FLYING || currentState == State.TAKEOFF) && !player.onGround) {
280+
it.movementInput.moveStrafe = 0.0f
281+
it.movementInput.moveForward = 1.0f
282+
}
283+
}
284+
}
285+
286+
private fun withinRange(motion: Double) = motion >= TAKE_OFF_Y_VELOCITY - 0.05 && motion <= TAKE_OFF_Y_VELOCITY + 0.05
287+
288+
private fun resetFlightSpeed() {
289+
setFlightSpeed(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+
elytraDurability = if (elytraIsEquipped) {
303+
armorSlot.maxDamage - armorSlot.itemDamage
304+
} else 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+
328+
if (player.motionY >= -0.02) return
329+
if (closeToGround) {
330+
resetTimer()
331+
return
332+
}
333+
if (!wasInLiquid && !mc.isSingleplayer) {
334+
event.cancel()
335+
player.setVelocity(0.0, -0.02, 0.0)
336+
}
337+
338+
if (!mc.isSingleplayer) modifyTimer(timerSpeed * 2.0f)
339+
connection.sendPacket(CPacketEntityAction(player, CPacketEntityAction.Action.START_FALL_FLYING))
340+
}
341+
342+
private fun SafeClientEvent.spoofRotation() {
343+
if (player.isSpectator || !elytraIsEquipped || elytraDurability <= 1 || !isFlying) return
344+
var rotation = com.lambda.client.util.math.Vec2f(player)
345+
if (!isStandingStill) rotation = com.lambda.client.util.math.Vec2f(rotation.x, MAGIC_PITCH)
346+
/* Cancels rotation packets if player is not moving and not clicking */
347+
val cancelRotation = isStandingStill
348+
&& ((!mc.gameSettings.keyBindUseItem.isKeyDown && !mc.gameSettings.keyBindAttack.isKeyDown))
349+
sendPlayerPacket {
350+
if (cancelRotation) {
351+
cancelRotate()
352+
} else {
353+
rotate(rotation)
354+
}
355+
}
356+
}
357+
358+
private fun SafeClientEvent.pathForward() {
359+
beforePathingPlayerPitchYaw = player.pitchYaw
360+
if (scheduleBaritoneJob?.isActive == true) return
361+
baritoneStartTime = System.currentTimeMillis()
362+
scheduleBaritoneJob = defaultScope.launch {
363+
delay(baritoneStartDelayMs.toLong())
364+
BaritoneUtils.primary?.playerContext?.let {
365+
BaritoneUtils.primary?.customGoalProcess?.setGoalAndPath(GoalXZ.fromDirection(
366+
it.playerFeetAsVec(),
367+
it.player().rotationYawHead,
368+
baritonePathForwardBlocks.toDouble()
369+
))
370+
}
371+
}
372+
}
373+
374+
private fun configureViewLock() {
375+
ViewLock.mode.value = ViewLock.Mode.TRADITIONAL
376+
ViewLock.yaw.value = true
377+
ViewLock.autoYaw.value = true
378+
ViewLock.hardAutoYaw.value = true
379+
ViewLock.disableMouseYaw.value = true
380+
ViewLock.yawSlice.value = 8
381+
ViewLock.pitch.value = false
382+
}
383+
}

0 commit comments

Comments
 (0)