From c4a0bb990c1b24de800cfedb64e7d74059543d0c Mon Sep 17 00:00:00 2001 From: rfresh2 <89827146+rfresh2@users.noreply.github.com> Date: Mon, 7 Aug 2023 14:30:18 -0700 Subject: [PATCH 1/2] ElytraFlight2b2t Module --- .../network/AccessorNetHandlerPlayClient.java | 15 + .../modules/movement/ElytraFlight2b2t.kt | 380 ++++++++++++++++++ .../module/modules/player/AntiForceLook.kt | 53 ++- .../client/module/modules/player/ViewLock.kt | 68 ++-- src/main/resources/mixins.lambda.json | 1 + 5 files changed, 479 insertions(+), 38 deletions(-) create mode 100644 src/main/java/com/lambda/mixin/accessor/network/AccessorNetHandlerPlayClient.java create mode 100644 src/main/kotlin/com/lambda/client/module/modules/movement/ElytraFlight2b2t.kt diff --git a/src/main/java/com/lambda/mixin/accessor/network/AccessorNetHandlerPlayClient.java b/src/main/java/com/lambda/mixin/accessor/network/AccessorNetHandlerPlayClient.java new file mode 100644 index 000000000..a389283c8 --- /dev/null +++ b/src/main/java/com/lambda/mixin/accessor/network/AccessorNetHandlerPlayClient.java @@ -0,0 +1,15 @@ +package com.lambda.mixin.accessor.network; + +import net.minecraft.client.network.NetHandlerPlayClient; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(value = NetHandlerPlayClient.class) +public interface AccessorNetHandlerPlayClient { + + @Accessor(value = "doneLoadingTerrain") + boolean isDoneLoadingTerrain(); + + @Accessor(value = "doneLoadingTerrain") + void setDoneLoadingTerrain(boolean loaded); +} diff --git a/src/main/kotlin/com/lambda/client/module/modules/movement/ElytraFlight2b2t.kt b/src/main/kotlin/com/lambda/client/module/modules/movement/ElytraFlight2b2t.kt new file mode 100644 index 000000000..0702aaa9d --- /dev/null +++ b/src/main/kotlin/com/lambda/client/module/modules/movement/ElytraFlight2b2t.kt @@ -0,0 +1,380 @@ +package com.lambda.client.module.modules.movement + +import baritone.api.pathing.goals.GoalXZ +import com.lambda.client.event.SafeClientEvent +import com.lambda.client.event.events.ConnectionEvent +import com.lambda.client.event.events.PacketEvent +import com.lambda.client.event.events.PlayerMoveEvent +import com.lambda.client.event.events.PlayerTravelEvent +import com.lambda.client.manager.managers.PlayerPacketManager.sendPlayerPacket +import com.lambda.client.mixin.extension.tickLength +import com.lambda.client.mixin.extension.timer +import com.lambda.client.module.Category +import com.lambda.client.module.Module +import com.lambda.client.module.modules.player.ViewLock +import com.lambda.client.util.BaritoneUtils +import com.lambda.client.util.MovementUtils.setSpeed +import com.lambda.client.util.TickTimer +import com.lambda.client.util.TimeUnit +import com.lambda.client.util.text.MessageSendHelper +import com.lambda.client.util.threads.defaultScope +import com.lambda.client.util.threads.safeListener +import com.lambda.client.util.world.getGroundPos +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import net.minecraft.init.Items +import net.minecraft.network.play.client.CPacketEntityAction +import net.minecraft.network.play.client.CPacketPlayer +import net.minecraft.network.play.server.SPacketPlayerPosLook +import net.minecraft.util.math.BlockPos +import net.minecraft.util.math.Vec2f +import net.minecraft.util.math.Vec3d +import net.minecraftforge.client.event.InputUpdateEvent +import net.minecraftforge.fml.common.gameevent.TickEvent +import kotlin.math.max +import kotlin.math.min + +object ElytraFlight2b2t : Module( + name = "ElytraFlight2b2t", + description = "Go very fast on 2b2t", + category = Category.MOVEMENT, + modulePriority = 1000 +) { + private val takeoffTimerSpeed by setting("Takeoff Timer Tick Length", 395.0f, 100.0f..1000.0f, 1.0f, + description = "How long each timer tick is during redeploy (ms). Lower length = faster timer. " + + "Try increasing this if experiencing elytra timeout or rubberbands. This value is multiplied by 2 when setting timer") + private val baritoneBlockagePathing by setting("Baritone Blockage Pathing", true, + description = "Use baritone to path around blockages on the highway.") + private val baritonePathForwardBlocks by setting("Baritone Path Distance", 20, 1..50, 1, + visibility = { baritoneBlockagePathing }) + private val baritoneEndDelayMs by setting("Baritone End Pathing Delay Ms", 500, 0..2000, 50, + visibility = { baritoneBlockagePathing }) + private val baritoneStartDelayMs by setting("Baritone Start Delay Ms", 500, 0..2000, 50, + visibility = { baritoneBlockagePathing }) + private val midairFallFly by setting("Mid-flight Packet Deploy", true, + description = "Uses packets to redeploy when mid-flight.") + private val autoFlyForward by setting("Auto Fly Forward", true, + description = "Automatically move forward when flying.") + private val rubberBandDetectionTime by setting("Rubberband Detection Time", 1110, 0..2000, 10, + description = "Time period (ms) between which to detect rubberband teleports. Lower period = more sensitive.") + private val enableBoost by setting("Enable boost", true, + description = "Enable boost during mid-air flight.") + private val boostDelayTicks by setting("Boost delay ticks", 11, 1..200, 1, + visibility = { enableBoost }, + description = "Number of ticks to wait before beginning boost") + private val boostSpeedIncrease by setting("Boost speed increase", 0.65, 0.0..2.0, 0.01, + visibility = { enableBoost }, + description = "Boost speed increase per tick (blocks per second / 2)") + private val initialFlightSpeed by setting("Initial Flight Speed", 39.5, 35.0..80.0, 0.01, + description = "Speed to start at for first successful deployment (blocks per second / 2).") + private val speedMax by setting("Speed Max", 100.0, 40.0..100.0, 0.1, + description = "Max flight speed (blocks per second / 2).") + private val redeploySpeedDecreaseFactor by setting("Redeploy Speed Dec Factor", 1.1, 1.0..2.0, 0.01, + description = "Decreases speed by a set factor during redeploys. Value is a divisor on current speed.") + private val avoidUnloaded by setting("Avoid Unloaded", true, + description = "Preserves speed while flying into unloaded chunks") + private val autoViewLockManage by setting("Auto ViewLock Manage", true, + description = "Automatically configures and toggles viewlock for straight flight on highways.") + + private const val takeOffYVelocity: Double = -0.16976 // magic number - do not question + private const val magicPitch = -2.52f + private var currentState = State.PAUSED + private var timer = TickTimer(TimeUnit.TICKS) + private var currentFlightSpeed: Double = 40.2 + private var shouldStartBoosting: Boolean = false; + private var elytraIsEquipped = false + private var elytraDurability = 0 + private var wasInLiquid: Boolean = false + private var isFlying: Boolean = false + private var isStandingStill = false + private var lastSPacketPlayerPosLook: Long = Long.MIN_VALUE + private var lastRubberband: Long = Long.MIN_VALUE + private var startedFlying: Boolean = false + private var stoppedFlying: Boolean = false + private var nextBlockMoveLoaded: Boolean = true + private var flyTickCount = 0 + private var flyPlayerLastPos: Vec3d = Vec3d.ZERO + private var flyBlockedTickCount = 0 + private var isBaritoning: Boolean = false + private var baritoneStartTime: Long = 0L + private var baritoneEndPathingTime: Long = 0L + private var beforePathingPlayerPitchYaw= Vec2f.ZERO + private var scheduleBaritoneJob: Job? = null + private var motionPrev: Vec2f = Vec2f(0.0f, 0.0f) + private const val jumpDelay: Int = 10 + + enum class State { + FLYING, TAKEOFF, PAUSED, WALKING + } + + override fun getHudInfo(): String { + return currentState.name + } + + init { + + onEnable { + currentState = State.PAUSED + timer.reset() + shouldStartBoosting = false + lastRubberband = Long.MIN_VALUE + if (autoViewLockManage) + configureViewLock() + } + + onDisable { + currentState = State.PAUSED + resetFlightSpeed() + BaritoneUtils.cancelEverything() + shouldStartBoosting = false + mc.timer.tickLength = 50.0f + wasInLiquid = false + isFlying = false + if (autoViewLockManage) + ViewLock.disable() + } + + safeListener { + disable() + } + + safeListener(priority = 9999) { + if (it.phase != TickEvent.Phase.END) return@safeListener + when (currentState) { + State.PAUSED -> { + val armorSlot = player.inventory.armorInventory[2] + elytraIsEquipped = armorSlot.item == Items.ELYTRA + if (!elytraIsEquipped) { + MessageSendHelper.sendChatMessage("No Elytra equipped") + disable() + return@safeListener + } + if (armorSlot.maxDamage <= 1) { + MessageSendHelper.sendChatMessage("Equipped Elytra broken or almost broken") + disable() + return@safeListener + } + currentState = State.TAKEOFF + } + State.WALKING -> { + if (autoViewLockManage && ViewLock.isEnabled) ViewLock.disable() + if (scheduleBaritoneJob?.isActive == true) return@safeListener + if (BaritoneUtils.isActive) { + isBaritoning = true + return@safeListener + } + // delay takeoff if we were pathing + if (isBaritoning) { + baritoneEndPathingTime = System.currentTimeMillis() + mc.player.rotationPitch = beforePathingPlayerPitchYaw.x + mc.player.rotationYaw = beforePathingPlayerPitchYaw.y + isBaritoning = false + return@safeListener + } + if (System.currentTimeMillis() - baritoneEndPathingTime < baritoneEndDelayMs) return@safeListener + currentState = State.TAKEOFF + } + State.TAKEOFF -> { + if (autoViewLockManage && ViewLock.isDisabled) ViewLock.enable() + mc.timer.tickLength = 50.0f + shouldStartBoosting = false + resetFlightSpeed() + if (baritoneBlockagePathing && player.onGround && timer.tick(jumpDelay.toLong())) player.jump() + if ((withinRange(mc.player.motionY, takeOffYVelocity, 0.05)) && !mc.player.isElytraFlying) { + timer.reset() + currentState = State.FLYING + } else if (midairFallFly && mc.player.isElytraFlying) { + connection.sendPacket(CPacketPlayer(true)) + } + } + State.FLYING -> { + if (autoViewLockManage && ViewLock.isDisabled) ViewLock.enable() + if (!mc.player.isElytraFlying && flyTickCount++ > 30) { + pathForward() + currentState = State.WALKING + } else flyTickCount = 0 + val playerCurrentPos = mc.player.positionVector + if (!avoidUnloaded || (avoidUnloaded && nextBlockMoveLoaded)) { + if (playerCurrentPos.distanceTo(flyPlayerLastPos) < 2.0) { + if (flyBlockedTickCount++ > 20) { + pathForward() + currentState = State.WALKING + } + } else flyBlockedTickCount = 0 + } + flyPlayerLastPos = playerCurrentPos + if (!enableBoost) return@safeListener + if (shouldStartBoosting) { + if (avoidUnloaded) { + if (nextBlockMoveLoaded && isFlying) setFlightSpeed(currentFlightSpeed + boostSpeedIncrease) + } else setFlightSpeed(currentFlightSpeed + boostSpeedIncrease) + } else if (timer.tick(boostDelayTicks, true)) shouldStartBoosting = true + } + } + } + + safeListener { + if (it.packet !is SPacketPlayerPosLook || currentState != State.FLYING) return@safeListener + timer.reset() + if (System.currentTimeMillis() - lastSPacketPlayerPosLook < rubberBandDetectionTime.toLong()) { + resetFlightSpeed() + shouldStartBoosting = false + mc.timer.tickLength = 50.0f + wasInLiquid = false + isFlying = false + currentState = if (baritoneBlockagePathing) { + pathForward() + State.WALKING + } else State.TAKEOFF + lastRubberband = System.currentTimeMillis() + } + lastSPacketPlayerPosLook = System.currentTimeMillis() + } + + safeListener { + if (avoidUnloaded && !nextBlockMoveLoaded && it.packet is CPacketPlayer) + it.cancel() + } + + safeListener { + stateUpdate() + if (currentState == State.FLYING && elytraIsEquipped && elytraDurability > 1) { + if (stoppedFlying) setFlightSpeed(currentFlightSpeed / redeploySpeedDecreaseFactor) + if (isFlying) { + mc.timer.tickLength = 50.0f + player.isSprinting = false + } else takeoff(it) + } + // rotation spoof also kicks us out of elytra during glide takeoffs due to rotation not matching flight speed + spoofRotation() + } + + safeListener { + if (currentState == State.FLYING) { + if (avoidUnloaded) { + if (nextBlockMoveLoaded && !mc.world.isBlockLoaded(BlockPos(mc.player.posX + it.x, mc.player.posY, mc.player.posZ + it.z), false)) { + nextBlockMoveLoaded = false + motionPrev = Vec2f(it.x.toFloat(), it.z.toFloat()) + setSpeed(0.0) + player.motionY = 0.0 + return@safeListener + } else if (!nextBlockMoveLoaded) { + if (!mc.world.isBlockLoaded(BlockPos(mc.player.posX + motionPrev.x, 1.0, mc.player.posZ + motionPrev.y), false)) { + setSpeed(0.0) + player.motionY = 0.0 + return@safeListener + } + } + } + setSpeed(currentFlightSpeed / 10.0) + player.motionY = 0.0 + } + nextBlockMoveLoaded = true + } + + safeListener { + if (autoFlyForward && (currentState == State.FLYING || currentState == State.TAKEOFF) && !mc.player.onGround) { + it.movementInput.moveStrafe = 0.0f + it.movementInput.moveForward = 1.0f + } + } + } + + private fun withinRange(num: Double, target: Double, range: Double): Boolean { + return (num >= target - range && num <= target + range) + } + + private fun resetFlightSpeed() { + setFlightSpeed(this.initialFlightSpeed) + } + + private fun setFlightSpeed(speed: Double) { + currentFlightSpeed = max(initialFlightSpeed, min(speed, speedMax)) + } + + private fun SafeClientEvent.stateUpdate() { + /* Elytra Check */ + val armorSlot = player.inventory.armorInventory[2] + elytraIsEquipped = armorSlot.item == Items.ELYTRA + + /* Elytra Durability Check */ + if (elytraIsEquipped) { + elytraDurability = armorSlot.maxDamage - armorSlot.itemDamage + } else elytraDurability = 0 + + /* wasInLiquid check */ + if (player.isInWater || player.isInLava) { + wasInLiquid = true + } else if (player.onGround || isFlying) { + wasInLiquid = false + } + + /* Elytra flying status check */ + startedFlying = !isFlying && player.isElytraFlying + stoppedFlying = isFlying && !player.isElytraFlying + isFlying = player.isElytraFlying + + /* Movement input check */ + val isStandingStillH = player.movementInput.moveForward == 0f && player.movementInput.moveStrafe == 0f + isStandingStill = isStandingStillH && !player.movementInput.jump && !player.movementInput.sneak + } + + private fun SafeClientEvent.takeoff(event: PlayerTravelEvent) { + val timerSpeed = takeoffTimerSpeed + val height = 0.1 + val closeToGround = player.posY <= world.getGroundPos(player).y + height && !wasInLiquid && !mc.isSingleplayer + if (player.motionY >= -0.02) return + if (closeToGround) { + mc.timer.tickLength = 50.0f + return + } + if (!wasInLiquid && !mc.isSingleplayer) { + event.cancel() + player.setVelocity(0.0, -0.02, 0.0) + } + if (!mc.isSingleplayer) mc.timer.tickLength = timerSpeed * 2.0f + connection.sendPacket(CPacketEntityAction(player, CPacketEntityAction.Action.START_FALL_FLYING)) + } + + private fun SafeClientEvent.spoofRotation() { + if (player.isSpectator || !elytraIsEquipped || elytraDurability <= 1 || !isFlying) return + var rotation = com.lambda.client.util.math.Vec2f(player) + if (!isStandingStill) rotation = com.lambda.client.util.math.Vec2f(rotation.x, magicPitch) + /* Cancels rotation packets if player is not moving and not clicking */ + var cancelRotation = isStandingStill + && ((!mc.gameSettings.keyBindUseItem.isKeyDown && !mc.gameSettings.keyBindAttack.isKeyDown)) + sendPlayerPacket { + if (cancelRotation) { + cancelRotate() + } else { + rotate(rotation) + } + } + } + + private fun SafeClientEvent.pathForward() { + beforePathingPlayerPitchYaw = mc.player.pitchYaw + if (scheduleBaritoneJob?.isActive == true) return + baritoneStartTime = System.currentTimeMillis() + scheduleBaritoneJob = defaultScope.launch { + delay(baritoneStartDelayMs.toLong()) + val playerContext = BaritoneUtils.primary?.playerContext!! + BaritoneUtils.primary?.customGoalProcess?.setGoalAndPath(GoalXZ.fromDirection( + playerContext.playerFeetAsVec(), + playerContext.player().rotationYawHead, + baritonePathForwardBlocks.toDouble() + )) + } + } + + private fun configureViewLock() { + ViewLock.mode.value = ViewLock.Mode.TRADITIONAL + ViewLock.yaw.value = true + ViewLock.autoYaw.value = true + ViewLock.hardAutoYaw.value = true + ViewLock.disableMouseYaw.value = true + ViewLock.yawSlice.value = 8 + ViewLock.pitch.value = false + } +} diff --git a/src/main/kotlin/com/lambda/client/module/modules/player/AntiForceLook.kt b/src/main/kotlin/com/lambda/client/module/modules/player/AntiForceLook.kt index 15447139b..0eec40bdc 100644 --- a/src/main/kotlin/com/lambda/client/module/modules/player/AntiForceLook.kt +++ b/src/main/kotlin/com/lambda/client/module/modules/player/AntiForceLook.kt @@ -1,11 +1,13 @@ package com.lambda.client.module.modules.player +import com.lambda.client.event.SafeClientEvent import com.lambda.client.event.events.PacketEvent -import com.lambda.client.mixin.extension.playerPosLookPitch -import com.lambda.client.mixin.extension.playerPosLookYaw import com.lambda.client.module.Category import com.lambda.client.module.Module import com.lambda.client.util.threads.safeListener +import com.lambda.mixin.accessor.network.AccessorNetHandlerPlayClient +import net.minecraft.network.play.client.CPacketConfirmTeleport +import net.minecraft.network.play.client.CPacketPlayer import net.minecraft.network.play.server.SPacketPlayerPosLook object AntiForceLook : Module( @@ -13,11 +15,50 @@ object AntiForceLook : Module( description = "Stops server packets from turning your head", category = Category.PLAYER ) { + init { - safeListener { - if (it.packet !is SPacketPlayerPosLook) return@safeListener - it.packet.playerPosLookYaw = player.rotationYaw - it.packet.playerPosLookPitch = player.rotationPitch + safeListener(priority = -5) { + if (it.packet is SPacketPlayerPosLook) { + it.cancel() + mc.addScheduledTask { handlePosLook(it.packet) } + } + } + } + + private fun SafeClientEvent.handlePosLook(packet: SPacketPlayerPosLook) { + /** {@See NetHandlerPlayClient#handlePlayerPosLook} **/ + var x = packet.x + var y = packet.y + var z = packet.z + var yaw = packet.yaw + var pitch = packet.pitch + + if (packet.flags.contains(SPacketPlayerPosLook.EnumFlags.X)) x += player.posX else player.motionX = 0.0 + if (packet.flags.contains(SPacketPlayerPosLook.EnumFlags.Y)) y += player.posY else player.motionY = 0.0 + if (packet.flags.contains(SPacketPlayerPosLook.EnumFlags.Z)) z += player.posZ else player.motionZ = 0.0 + if (packet.flags.contains(SPacketPlayerPosLook.EnumFlags.X_ROT)) pitch += player.rotationPitch + if (packet.flags.contains(SPacketPlayerPosLook.EnumFlags.Y_ROT)) yaw += player.rotationYaw + + player.setPositionAndRotation(x, y, z, + // retain current yaw and pitch client-side + player.rotationYaw, + player.rotationPitch) + // spoof to server that we are using its rotation + connection.sendPacket(CPacketConfirmTeleport(packet.teleportId)) + connection.sendPacket(CPacketPlayer.PositionRotation( + player.posX, + player.entityBoundingBox.minY, + player.posZ, + yaw, + pitch, + false)) + if (!(player.connection as AccessorNetHandlerPlayClient) + .isDoneLoadingTerrain) { + player.prevPosX = player.posX + player.prevPosY = player.posY + player.prevPosZ = player.posZ + (player.connection as AccessorNetHandlerPlayClient).isDoneLoadingTerrain = true + mc.displayGuiScreen(null) } } } \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/client/module/modules/player/ViewLock.kt b/src/main/kotlin/com/lambda/client/module/modules/player/ViewLock.kt index cc22fec95..29f970d8f 100644 --- a/src/main/kotlin/com/lambda/client/module/modules/player/ViewLock.kt +++ b/src/main/kotlin/com/lambda/client/module/modules/player/ViewLock.kt @@ -21,30 +21,34 @@ object ViewLock : Module( category = Category.PLAYER, alias = arrayOf("YawLock", "PitchLock") ) { - private val mode by setting("Mode", Mode.TRADITIONAL) - private val page by setting("Page", Page.YAW, { mode == Mode.TRADITIONAL }) - - private val yaw by setting("Yaw", true, { mode == Mode.TRADITIONAL && page == Page.YAW }) - private val autoYaw = setting("Auto Yaw", true, { mode == Mode.TRADITIONAL && page == Page.YAW && yaw }) - private val disableMouseYaw by setting("Disable Mouse Yaw", false, { mode == Mode.TRADITIONAL && page == Page.YAW && yaw && yaw }) - private val specificYaw by setting("Specific Yaw", 180.0f, -180.0f..180.0f, 1.0f, { mode == Mode.TRADITIONAL && page == Page.YAW && !autoYaw.value && yaw }) - private val yawSlice = setting("Yaw Slice", 8, 2..32, 1, { mode == Mode.TRADITIONAL && page == Page.YAW && autoYaw.value && yaw }) - - private val pitch by setting("Pitch", true, { mode == Mode.TRADITIONAL && page == Page.PITCH }) - private val autoPitch = setting("Auto Pitch", true, { mode == Mode.TRADITIONAL && page == Page.PITCH && pitch }) - private val disableMousePitch by setting("Disable Mouse Pitch", false, { mode == Mode.TRADITIONAL && page == Page.PITCH && pitch && pitch }) - private val specificPitch by setting("Specific Pitch", 0.0f, -90.0f..90.0f, 1.0f, { mode == Mode.TRADITIONAL && page == Page.PITCH && !autoPitch.value && pitch }) - private val pitchSlice = setting("Pitch Slice", 5, 2..32, 1, { mode == Mode.TRADITIONAL && page == Page.PITCH && autoPitch.value && pitch }) - - private val xCoord by setting("X coordinate", "", { mode == Mode.COORDS }) - private val yCoord by setting("Y coordinate", "", { mode == Mode.COORDS }) - private val zCoord by setting("Z coordinate", "", { mode == Mode.COORDS }) + val mode = setting("Mode", Mode.TRADITIONAL) + private val page by setting("Page", Page.YAW, { mode.value == Mode.TRADITIONAL }) + + val yaw = setting("Yaw", true, { page == Page.YAW && mode.value == Mode.TRADITIONAL }) + val autoYaw = setting("Auto Yaw", true, { page == Page.YAW && yaw.value && mode.value == Mode.TRADITIONAL }) + val hardAutoYaw = setting("Hard Auto Yaw", true, { page == Page.YAW && yaw.value && autoYaw.value && mode.value == Mode.TRADITIONAL }, + description = "Disables mouse movement snapping") + val disableMouseYaw = setting("Disable Mouse Yaw", true, { page == Page.YAW && yaw.value && mode.value == Mode.TRADITIONAL }) + private val specificYaw by setting("Specific Yaw", 180.0f, -180.0f..180.0f, 1.0f, { page == Page.YAW && !autoYaw.value && yaw.value && mode.value == Mode.TRADITIONAL }) + val yawSlice = setting("Yaw Slice", 8, 2..32, 1, { page == Page.YAW && autoYaw.value && yaw.value && mode.value == Mode.TRADITIONAL }) + + val pitch = setting("Pitch", true, { page == Page.PITCH && mode.value == Mode.TRADITIONAL }) + private val autoPitch = setting("Auto Pitch", true, { page == Page.PITCH && pitch.value && mode.value == Mode.TRADITIONAL }) + private val hardAutoPitch by setting("Hard Auto Pitch", true, { page == Page.PITCH && pitch.value && autoPitch.value && mode.value == Mode.TRADITIONAL }, + description = "Disables mouse movement snapping") + private val disableMousePitch by setting("Disable Mouse Pitch", true, { page == Page.PITCH && pitch.value && mode.value == Mode.TRADITIONAL }) + private val specificPitch by setting("Specific Pitch", 0.0f, -90.0f..90.0f, 1.0f, { page == Page.PITCH && !autoPitch.value && pitch.value && mode.value == Mode.TRADITIONAL }) + private val pitchSlice = setting("Pitch Slice", 5, 2..32, 1, { page == Page.PITCH && autoPitch.value && pitch.value && mode.value == Mode.TRADITIONAL }) + + private val xCoord by setting("X coordinate", "", { mode.value == Mode.COORDS }) + private val yCoord by setting("Y coordinate", "", { mode.value == Mode.COORDS }) + private val zCoord by setting("Z coordinate", "", { mode.value == Mode.COORDS }) private enum class Page { YAW, PITCH } - - private enum class Mode { + + enum class Mode { TRADITIONAL, COORDS } @@ -64,8 +68,8 @@ object ViewLock : Module( safeListener { if (it.phase != TickEvent.Phase.END) return@safeListener - - if (mode == Mode.COORDS) { + + if (mode.value == Mode.COORDS) { val x = xCoord.toDoubleOrNull() val y = yCoord.toDoubleOrNull() val z = zCoord.toDoubleOrNull() @@ -74,7 +78,7 @@ object ViewLock : Module( disable() return@safeListener } - + val rotation = getRotationTo(Vec3d(x, y, z)) player.rotationYaw = rotation.x player.rotationPitch = rotation.y @@ -85,11 +89,11 @@ object ViewLock : Module( snapToSlice() } - if (yaw && !autoYaw.value) { + if (yaw.value && !autoYaw.value) { player.rotationYaw = specificYaw } - if (pitch && !autoPitch.value) { + if (pitch.value && !autoPitch.value) { player.rotationPitch = specificPitch } } @@ -97,15 +101,15 @@ object ViewLock : Module( @JvmStatic fun handleTurn(entity: Entity, deltaX: Float, deltaY: Float, ci: CallbackInfo) { - if (isDisabled || mode == Mode.COORDS) return + if (isDisabled || mode.value == Mode.COORDS) return val player = mc.player ?: return if (entity != player) return val multipliedX = deltaX * 0.15f val multipliedY = deltaY * -0.15f - val yawChange = if (yaw && autoYaw.value) handleDelta(multipliedX, deltaXQueue, yawSliceAngle) else 0 - val pitchChange = if (pitch && autoPitch.value) handleDelta(multipliedY, deltaYQueue, pitchSliceAngle) else 0 + val yawChange = if (yaw.value && autoYaw.value && !hardAutoYaw.value) handleDelta(multipliedX, deltaXQueue, yawSliceAngle) else 0 + val pitchChange = if (pitch.value && autoPitch.value && !hardAutoPitch) handleDelta(multipliedY, deltaYQueue, pitchSliceAngle) else 0 turn(player, multipliedX, multipliedY) changeDirection(yawChange, pitchChange) @@ -115,12 +119,12 @@ object ViewLock : Module( } private fun turn(player: EntityPlayerSP, deltaX: Float, deltaY: Float) { - if (!yaw || !disableMouseYaw) { + if (!yaw.value || !disableMouseYaw.value) { player.prevRotationYaw += deltaX player.rotationYaw += deltaX } - if (!pitch || !disableMousePitch) { + if (!pitch.value || !disableMousePitch) { player.prevRotationPitch += deltaY player.rotationPitch += deltaY player.rotationPitch = player.rotationPitch.coerceIn(-90.0f, 90.0f) @@ -159,11 +163,11 @@ object ViewLock : Module( private fun snapToSlice() { mc.player?.let { player -> - if (yaw && autoYaw.value) { + if (yaw.value && autoYaw.value) { player.rotationYaw = (yawSnap * yawSliceAngle).coerceIn(0f, 360f) player.ridingEntity?.let { it.rotationYaw = player.rotationYaw } } - if (pitch && autoPitch.value) { + if (pitch.value && autoPitch.value) { player.rotationPitch = (pitchSnap * pitchSliceAngle - 90).coerceIn(-90f, 90f) } } diff --git a/src/main/resources/mixins.lambda.json b/src/main/resources/mixins.lambda.json index d92b2be59..f35f7716d 100644 --- a/src/main/resources/mixins.lambda.json +++ b/src/main/resources/mixins.lambda.json @@ -24,6 +24,7 @@ "accessor.network.AccessorCPacketPlayer", "accessor.network.AccessorCPacketUseEntity", "accessor.network.AccessorCPacketVehicleMove", + "accessor.network.AccessorNetHandlerPlayClient", "accessor.network.AccessorSPacketChat", "accessor.network.AccessorSPacketEntity", "accessor.network.AccessorSPacketEntityHeadLook", From 55f2528839576fc27953c4e77efdfc770cc615be Mon Sep 17 00:00:00 2001 From: Constructor Date: Tue, 8 Aug 2023 01:06:15 +0200 Subject: [PATCH 2/2] Refactor --- .../modules/movement/ElytraFlight2b2t.kt | 153 +++++++++--------- .../module/modules/player/AntiForceLook.kt | 18 ++- 2 files changed, 90 insertions(+), 81 deletions(-) diff --git a/src/main/kotlin/com/lambda/client/module/modules/movement/ElytraFlight2b2t.kt b/src/main/kotlin/com/lambda/client/module/modules/movement/ElytraFlight2b2t.kt index 0702aaa9d..cede1611f 100644 --- a/src/main/kotlin/com/lambda/client/module/modules/movement/ElytraFlight2b2t.kt +++ b/src/main/kotlin/com/lambda/client/module/modules/movement/ElytraFlight2b2t.kt @@ -7,8 +7,8 @@ import com.lambda.client.event.events.PacketEvent import com.lambda.client.event.events.PlayerMoveEvent import com.lambda.client.event.events.PlayerTravelEvent import com.lambda.client.manager.managers.PlayerPacketManager.sendPlayerPacket -import com.lambda.client.mixin.extension.tickLength -import com.lambda.client.mixin.extension.timer +import com.lambda.client.manager.managers.TimerManager.modifyTimer +import com.lambda.client.manager.managers.TimerManager.resetTimer import com.lambda.client.module.Category import com.lambda.client.module.Module import com.lambda.client.module.modules.player.ViewLock @@ -41,29 +41,29 @@ object ElytraFlight2b2t : Module( category = Category.MOVEMENT, modulePriority = 1000 ) { - private val takeoffTimerSpeed by setting("Takeoff Timer Tick Length", 395.0f, 100.0f..1000.0f, 1.0f, + private val takeoffTimerSpeed by setting("Takeoff Timer Tick Length", 395.0f, 100.0f..1000.0f, 5.0f, description = "How long each timer tick is during redeploy (ms). Lower length = faster timer. " + - "Try increasing this if experiencing elytra timeout or rubberbands. This value is multiplied by 2 when setting timer") + "Try increasing this if experiencing elytra timeout or rubberbands. This value is multiplied by 2 when setting timer", unit = "ms") private val baritoneBlockagePathing by setting("Baritone Blockage Pathing", true, description = "Use baritone to path around blockages on the highway.") private val baritonePathForwardBlocks by setting("Baritone Path Distance", 20, 1..50, 1, visibility = { baritoneBlockagePathing }) - private val baritoneEndDelayMs by setting("Baritone End Pathing Delay Ms", 500, 0..2000, 50, - visibility = { baritoneBlockagePathing }) - private val baritoneStartDelayMs by setting("Baritone Start Delay Ms", 500, 0..2000, 50, - visibility = { baritoneBlockagePathing }) + private val baritoneEndDelayMs by setting("Baritone End Pathing Delay", 500, 0..2000, 50, + visibility = { baritoneBlockagePathing }, unit = "ms") + private val baritoneStartDelayMs by setting("Baritone Start Delay", 500, 0..2000, 50, + visibility = { baritoneBlockagePathing }, unit = "ms") private val midairFallFly by setting("Mid-flight Packet Deploy", true, description = "Uses packets to redeploy when mid-flight.") private val autoFlyForward by setting("Auto Fly Forward", true, description = "Automatically move forward when flying.") private val rubberBandDetectionTime by setting("Rubberband Detection Time", 1110, 0..2000, 10, - description = "Time period (ms) between which to detect rubberband teleports. Lower period = more sensitive.") - private val enableBoost by setting("Enable boost", true, + description = "Time period (ms) between which to detect rubberband teleports. Lower period = more sensitive.", unit = "ms") + private val enableBoost by setting("Enable Boost", true, description = "Enable boost during mid-air flight.") - private val boostDelayTicks by setting("Boost delay ticks", 11, 1..200, 1, - visibility = { enableBoost }, + private val boostDelayTicks by setting("Boost Delay", 11, 1..200, 1, + visibility = { enableBoost }, unit = "ticks", description = "Number of ticks to wait before beginning boost") - private val boostSpeedIncrease by setting("Boost speed increase", 0.65, 0.0..2.0, 0.01, + private val boostSpeedIncrease by setting("Boost Speed Increase", 0.65, 0.0..2.0, 0.01, visibility = { enableBoost }, description = "Boost speed increase per tick (blocks per second / 2)") private val initialFlightSpeed by setting("Initial Flight Speed", 39.5, 35.0..80.0, 0.01, @@ -77,50 +77,52 @@ object ElytraFlight2b2t : Module( private val autoViewLockManage by setting("Auto ViewLock Manage", true, description = "Automatically configures and toggles viewlock for straight flight on highways.") - private const val takeOffYVelocity: Double = -0.16976 // magic number - do not question - private const val magicPitch = -2.52f + private const val TAKE_OFF_Y_VELOCITY = -0.16976 // magic number - do not question + private const val MAGIC_PITCH = -2.52f + private const val JUMP_DELAY = 10 + private var currentState = State.PAUSED + private var isFlying = false + private var isBaritoning = false + private var timer = TickTimer(TimeUnit.TICKS) - private var currentFlightSpeed: Double = 40.2 - private var shouldStartBoosting: Boolean = false; + private var lastSPacketPlayerPosLook = Long.MIN_VALUE + private var lastRubberband = Long.MIN_VALUE + private var baritoneStartTime = 0L + private var baritoneEndPathingTime = 0L + + private var shouldStartBoosting = false private var elytraIsEquipped = false - private var elytraDurability = 0 - private var wasInLiquid: Boolean = false - private var isFlying: Boolean = false + private var wasInLiquid = false private var isStandingStill = false - private var lastSPacketPlayerPosLook: Long = Long.MIN_VALUE - private var lastRubberband: Long = Long.MIN_VALUE - private var startedFlying: Boolean = false - private var stoppedFlying: Boolean = false - private var nextBlockMoveLoaded: Boolean = true + private var startedFlying = false + private var stoppedFlying = false + private var nextBlockMoveLoaded = true + + private var elytraDurability = 0 private var flyTickCount = 0 - private var flyPlayerLastPos: Vec3d = Vec3d.ZERO private var flyBlockedTickCount = 0 - private var isBaritoning: Boolean = false - private var baritoneStartTime: Long = 0L - private var baritoneEndPathingTime: Long = 0L - private var beforePathingPlayerPitchYaw= Vec2f.ZERO + private var currentFlightSpeed = 40.2 + + private var flyPlayerLastPos = Vec3d.ZERO + private var beforePathingPlayerPitchYaw = Vec2f.ZERO + private var motionPrev = Vec2f(0.0f, 0.0f) + private var scheduleBaritoneJob: Job? = null - private var motionPrev: Vec2f = Vec2f(0.0f, 0.0f) - private const val jumpDelay: Int = 10 enum class State { FLYING, TAKEOFF, PAUSED, WALKING } - override fun getHudInfo(): String { - return currentState.name - } + override fun getHudInfo() = currentState.name init { - onEnable { currentState = State.PAUSED timer.reset() shouldStartBoosting = false lastRubberband = Long.MIN_VALUE - if (autoViewLockManage) - configureViewLock() + if (autoViewLockManage) configureViewLock() } onDisable { @@ -128,11 +130,10 @@ object ElytraFlight2b2t : Module( resetFlightSpeed() BaritoneUtils.cancelEverything() shouldStartBoosting = false - mc.timer.tickLength = 50.0f + resetTimer() wasInLiquid = false isFlying = false - if (autoViewLockManage) - ViewLock.disable() + if (autoViewLockManage) ViewLock.disable() } safeListener { @@ -167,8 +168,8 @@ object ElytraFlight2b2t : Module( // delay takeoff if we were pathing if (isBaritoning) { baritoneEndPathingTime = System.currentTimeMillis() - mc.player.rotationPitch = beforePathingPlayerPitchYaw.x - mc.player.rotationYaw = beforePathingPlayerPitchYaw.y + player.rotationPitch = beforePathingPlayerPitchYaw.x + player.rotationYaw = beforePathingPlayerPitchYaw.y isBaritoning = false return@safeListener } @@ -177,24 +178,24 @@ object ElytraFlight2b2t : Module( } State.TAKEOFF -> { if (autoViewLockManage && ViewLock.isDisabled) ViewLock.enable() - mc.timer.tickLength = 50.0f + resetTimer() shouldStartBoosting = false resetFlightSpeed() - if (baritoneBlockagePathing && player.onGround && timer.tick(jumpDelay.toLong())) player.jump() - if ((withinRange(mc.player.motionY, takeOffYVelocity, 0.05)) && !mc.player.isElytraFlying) { + if (baritoneBlockagePathing && player.onGround && timer.tick(JUMP_DELAY.toLong())) player.jump() + if ((withinRange(player.motionY)) && !player.isElytraFlying) { timer.reset() currentState = State.FLYING - } else if (midairFallFly && mc.player.isElytraFlying) { + } else if (midairFallFly && player.isElytraFlying) { connection.sendPacket(CPacketPlayer(true)) } } State.FLYING -> { if (autoViewLockManage && ViewLock.isDisabled) ViewLock.enable() - if (!mc.player.isElytraFlying && flyTickCount++ > 30) { + if (!player.isElytraFlying && flyTickCount++ > 30) { pathForward() currentState = State.WALKING } else flyTickCount = 0 - val playerCurrentPos = mc.player.positionVector + val playerCurrentPos = player.positionVector if (!avoidUnloaded || (avoidUnloaded && nextBlockMoveLoaded)) { if (playerCurrentPos.distanceTo(flyPlayerLastPos) < 2.0) { if (flyBlockedTickCount++ > 20) { @@ -207,7 +208,9 @@ object ElytraFlight2b2t : Module( if (!enableBoost) return@safeListener if (shouldStartBoosting) { if (avoidUnloaded) { - if (nextBlockMoveLoaded && isFlying) setFlightSpeed(currentFlightSpeed + boostSpeedIncrease) + if (nextBlockMoveLoaded && isFlying) { + setFlightSpeed(currentFlightSpeed + boostSpeedIncrease) + } } else setFlightSpeed(currentFlightSpeed + boostSpeedIncrease) } else if (timer.tick(boostDelayTicks, true)) shouldStartBoosting = true } @@ -220,7 +223,7 @@ object ElytraFlight2b2t : Module( if (System.currentTimeMillis() - lastSPacketPlayerPosLook < rubberBandDetectionTime.toLong()) { resetFlightSpeed() shouldStartBoosting = false - mc.timer.tickLength = 50.0f + resetTimer() wasInLiquid = false isFlying = false currentState = if (baritoneBlockagePathing) { @@ -233,8 +236,7 @@ object ElytraFlight2b2t : Module( } safeListener { - if (avoidUnloaded && !nextBlockMoveLoaded && it.packet is CPacketPlayer) - it.cancel() + if (avoidUnloaded && !nextBlockMoveLoaded && it.packet is CPacketPlayer) it.cancel() } safeListener { @@ -242,7 +244,7 @@ object ElytraFlight2b2t : Module( if (currentState == State.FLYING && elytraIsEquipped && elytraDurability > 1) { if (stoppedFlying) setFlightSpeed(currentFlightSpeed / redeploySpeedDecreaseFactor) if (isFlying) { - mc.timer.tickLength = 50.0f + resetTimer() player.isSprinting = false } else takeoff(it) } @@ -253,14 +255,14 @@ object ElytraFlight2b2t : Module( safeListener { if (currentState == State.FLYING) { if (avoidUnloaded) { - if (nextBlockMoveLoaded && !mc.world.isBlockLoaded(BlockPos(mc.player.posX + it.x, mc.player.posY, mc.player.posZ + it.z), false)) { + if (nextBlockMoveLoaded && !world.isBlockLoaded(BlockPos(player.posX + it.x, player.posY, player.posZ + it.z), false)) { nextBlockMoveLoaded = false motionPrev = Vec2f(it.x.toFloat(), it.z.toFloat()) setSpeed(0.0) player.motionY = 0.0 return@safeListener } else if (!nextBlockMoveLoaded) { - if (!mc.world.isBlockLoaded(BlockPos(mc.player.posX + motionPrev.x, 1.0, mc.player.posZ + motionPrev.y), false)) { + if (!world.isBlockLoaded(BlockPos(player.posX + motionPrev.x, 1.0, player.posZ + motionPrev.y), false)) { setSpeed(0.0) player.motionY = 0.0 return@safeListener @@ -274,19 +276,17 @@ object ElytraFlight2b2t : Module( } safeListener { - if (autoFlyForward && (currentState == State.FLYING || currentState == State.TAKEOFF) && !mc.player.onGround) { + if (autoFlyForward && (currentState == State.FLYING || currentState == State.TAKEOFF) && !player.onGround) { it.movementInput.moveStrafe = 0.0f it.movementInput.moveForward = 1.0f } } } - private fun withinRange(num: Double, target: Double, range: Double): Boolean { - return (num >= target - range && num <= target + range) - } + private fun withinRange(motion: Double) = motion >= TAKE_OFF_Y_VELOCITY - 0.05 && motion <= TAKE_OFF_Y_VELOCITY + 0.05 private fun resetFlightSpeed() { - setFlightSpeed(this.initialFlightSpeed) + setFlightSpeed(initialFlightSpeed) } private fun setFlightSpeed(speed: Double) { @@ -299,9 +299,9 @@ object ElytraFlight2b2t : Module( elytraIsEquipped = armorSlot.item == Items.ELYTRA /* Elytra Durability Check */ - if (elytraIsEquipped) { - elytraDurability = armorSlot.maxDamage - armorSlot.itemDamage - } else elytraDurability = 0 + elytraDurability = if (elytraIsEquipped) { + armorSlot.maxDamage - armorSlot.itemDamage + } else 0 /* wasInLiquid check */ if (player.isInWater || player.isInLava) { @@ -324,25 +324,27 @@ object ElytraFlight2b2t : Module( val timerSpeed = takeoffTimerSpeed val height = 0.1 val closeToGround = player.posY <= world.getGroundPos(player).y + height && !wasInLiquid && !mc.isSingleplayer + if (player.motionY >= -0.02) return if (closeToGround) { - mc.timer.tickLength = 50.0f + resetTimer() return } if (!wasInLiquid && !mc.isSingleplayer) { event.cancel() player.setVelocity(0.0, -0.02, 0.0) } - if (!mc.isSingleplayer) mc.timer.tickLength = timerSpeed * 2.0f + + if (!mc.isSingleplayer) modifyTimer(timerSpeed * 2.0f) connection.sendPacket(CPacketEntityAction(player, CPacketEntityAction.Action.START_FALL_FLYING)) } private fun SafeClientEvent.spoofRotation() { if (player.isSpectator || !elytraIsEquipped || elytraDurability <= 1 || !isFlying) return var rotation = com.lambda.client.util.math.Vec2f(player) - if (!isStandingStill) rotation = com.lambda.client.util.math.Vec2f(rotation.x, magicPitch) + if (!isStandingStill) rotation = com.lambda.client.util.math.Vec2f(rotation.x, MAGIC_PITCH) /* Cancels rotation packets if player is not moving and not clicking */ - var cancelRotation = isStandingStill + val cancelRotation = isStandingStill && ((!mc.gameSettings.keyBindUseItem.isKeyDown && !mc.gameSettings.keyBindAttack.isKeyDown)) sendPlayerPacket { if (cancelRotation) { @@ -354,17 +356,18 @@ object ElytraFlight2b2t : Module( } private fun SafeClientEvent.pathForward() { - beforePathingPlayerPitchYaw = mc.player.pitchYaw + beforePathingPlayerPitchYaw = player.pitchYaw if (scheduleBaritoneJob?.isActive == true) return baritoneStartTime = System.currentTimeMillis() scheduleBaritoneJob = defaultScope.launch { delay(baritoneStartDelayMs.toLong()) - val playerContext = BaritoneUtils.primary?.playerContext!! - BaritoneUtils.primary?.customGoalProcess?.setGoalAndPath(GoalXZ.fromDirection( - playerContext.playerFeetAsVec(), - playerContext.player().rotationYawHead, - baritonePathForwardBlocks.toDouble() - )) + BaritoneUtils.primary?.playerContext?.let { + BaritoneUtils.primary?.customGoalProcess?.setGoalAndPath(GoalXZ.fromDirection( + it.playerFeetAsVec(), + it.player().rotationYawHead, + baritonePathForwardBlocks.toDouble() + )) + } } } diff --git a/src/main/kotlin/com/lambda/client/module/modules/player/AntiForceLook.kt b/src/main/kotlin/com/lambda/client/module/modules/player/AntiForceLook.kt index 0eec40bdc..133f3c3a6 100644 --- a/src/main/kotlin/com/lambda/client/module/modules/player/AntiForceLook.kt +++ b/src/main/kotlin/com/lambda/client/module/modules/player/AntiForceLook.kt @@ -26,7 +26,7 @@ object AntiForceLook : Module( } private fun SafeClientEvent.handlePosLook(packet: SPacketPlayerPosLook) { - /** {@See NetHandlerPlayClient#handlePlayerPosLook} **/ + /** {@see NetHandlerPlayClient#handlePlayerPosLook} **/ var x = packet.x var y = packet.y var z = packet.z @@ -42,22 +42,28 @@ object AntiForceLook : Module( player.setPositionAndRotation(x, y, z, // retain current yaw and pitch client-side player.rotationYaw, - player.rotationPitch) + player.rotationPitch + ) + // spoof to server that we are using its rotation connection.sendPacket(CPacketConfirmTeleport(packet.teleportId)) + connection.sendPacket(CPacketPlayer.PositionRotation( player.posX, player.entityBoundingBox.minY, player.posZ, yaw, pitch, - false)) - if (!(player.connection as AccessorNetHandlerPlayClient) - .isDoneLoadingTerrain) { + false) + ) + + val connection = (player.connection as? AccessorNetHandlerPlayClient) ?: return + + if (!connection.isDoneLoadingTerrain) { player.prevPosX = player.posX player.prevPosY = player.posY player.prevPosZ = player.posZ - (player.connection as AccessorNetHandlerPlayClient).isDoneLoadingTerrain = true + connection.isDoneLoadingTerrain = true mc.displayGuiScreen(null) } }