Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ElytraFlight2b2t Module #577

Merged
merged 2 commits into from
Aug 7, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,383 @@
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.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
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, 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", 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", 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.", unit = "ms")
private val enableBoost by setting("Enable Boost", true,
description = "Enable boost during mid-air flight.")
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,
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 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 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 wasInLiquid = false
private var isStandingStill = false
private var startedFlying = false
private var stoppedFlying = false
private var nextBlockMoveLoaded = true

private var elytraDurability = 0
private var flyTickCount = 0
private var flyBlockedTickCount = 0
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

enum class State {
FLYING, TAKEOFF, PAUSED, WALKING
}

override fun getHudInfo() = 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
resetTimer()
wasInLiquid = false
isFlying = false
if (autoViewLockManage) ViewLock.disable()
}

safeListener<ConnectionEvent.Disconnect> {
disable()
}

safeListener<TickEvent.ClientTickEvent>(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()
player.rotationPitch = beforePathingPlayerPitchYaw.x
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()
resetTimer()
shouldStartBoosting = false
resetFlightSpeed()
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 && player.isElytraFlying) {
connection.sendPacket(CPacketPlayer(true))
}
}
State.FLYING -> {
if (autoViewLockManage && ViewLock.isDisabled) ViewLock.enable()
if (!player.isElytraFlying && flyTickCount++ > 30) {
pathForward()
currentState = State.WALKING
} else flyTickCount = 0
val playerCurrentPos = 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<PacketEvent.Receive> {
if (it.packet !is SPacketPlayerPosLook || currentState != State.FLYING) return@safeListener
timer.reset()
if (System.currentTimeMillis() - lastSPacketPlayerPosLook < rubberBandDetectionTime.toLong()) {
resetFlightSpeed()
shouldStartBoosting = false
resetTimer()
wasInLiquid = false
isFlying = false
currentState = if (baritoneBlockagePathing) {
pathForward()
State.WALKING
} else State.TAKEOFF
lastRubberband = System.currentTimeMillis()
}
lastSPacketPlayerPosLook = System.currentTimeMillis()
}

safeListener<PacketEvent.Send> {
if (avoidUnloaded && !nextBlockMoveLoaded && it.packet is CPacketPlayer) it.cancel()
}

safeListener<PlayerTravelEvent> {
stateUpdate()
if (currentState == State.FLYING && elytraIsEquipped && elytraDurability > 1) {
if (stoppedFlying) setFlightSpeed(currentFlightSpeed / redeploySpeedDecreaseFactor)
if (isFlying) {
resetTimer()
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<PlayerMoveEvent> {
if (currentState == State.FLYING) {
if (avoidUnloaded) {
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 (!world.isBlockLoaded(BlockPos(player.posX + motionPrev.x, 1.0, 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<InputUpdateEvent> {
if (autoFlyForward && (currentState == State.FLYING || currentState == State.TAKEOFF) && !player.onGround) {
it.movementInput.moveStrafe = 0.0f
it.movementInput.moveForward = 1.0f
}
}
}

private fun withinRange(motion: Double) = motion >= TAKE_OFF_Y_VELOCITY - 0.05 && motion <= TAKE_OFF_Y_VELOCITY + 0.05

private fun resetFlightSpeed() {
setFlightSpeed(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 */
elytraDurability = if (elytraIsEquipped) {
armorSlot.maxDamage - armorSlot.itemDamage
} else 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) {
resetTimer()
return
}
if (!wasInLiquid && !mc.isSingleplayer) {
event.cancel()
player.setVelocity(0.0, -0.02, 0.0)
}

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, MAGIC_PITCH)
/* Cancels rotation packets if player is not moving and not clicking */
val cancelRotation = isStandingStill
&& ((!mc.gameSettings.keyBindUseItem.isKeyDown && !mc.gameSettings.keyBindAttack.isKeyDown))
sendPlayerPacket {
if (cancelRotation) {
cancelRotate()
} else {
rotate(rotation)
}
}
}

private fun SafeClientEvent.pathForward() {
beforePathingPlayerPitchYaw = player.pitchYaw
if (scheduleBaritoneJob?.isActive == true) return
baritoneStartTime = System.currentTimeMillis()
scheduleBaritoneJob = defaultScope.launch {
delay(baritoneStartDelayMs.toLong())
BaritoneUtils.primary?.playerContext?.let {
BaritoneUtils.primary?.customGoalProcess?.setGoalAndPath(GoalXZ.fromDirection(
it.playerFeetAsVec(),
it.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
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,70 @@
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(
name = "AntiForceLook",
description = "Stops server packets from turning your head",
category = Category.PLAYER
) {

init {
safeListener<PacketEvent.Receive> {
if (it.packet !is SPacketPlayerPosLook) return@safeListener
it.packet.playerPosLookYaw = player.rotationYaw
it.packet.playerPosLookPitch = player.rotationPitch
safeListener<PacketEvent.Receive>(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)
)

val connection = (player.connection as? AccessorNetHandlerPlayClient) ?: return

if (!connection.isDoneLoadingTerrain) {
player.prevPosX = player.posX
player.prevPosY = player.posY
player.prevPosZ = player.posZ
connection.isDoneLoadingTerrain = true
mc.displayGuiScreen(null)
}
}
}
68 changes: 36 additions & 32 deletions src/main/kotlin/com/lambda/client/module/modules/player/ViewLock.kt
Original file line number Diff line number Diff line change
@@ -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<TickEvent.ClientTickEvent> {
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,27 +89,27 @@ 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
}
}
}

@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)
}
}
1 change: 1 addition & 0 deletions src/main/resources/mixins.lambda.json
Original file line number Diff line number Diff line change
@@ -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",