Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ void onTargetUpdate(Rotation rotation, boolean blockInteract, CallbackInfo ci) {
LookBehavior instance = ((LookBehavior) (Object) this);
if (instance.baritone != BaritoneUtils.getPrimary()) return;

RotationManager.BaritoneProcessor.handleBaritoneRotation(rotation.getYaw(), rotation.getPitch());
RotationManager.handleBaritoneRotation(rotation.getYaw(), rotation.getPitch());
ci.cancel();
}

Expand Down
65 changes: 17 additions & 48 deletions 65 src/main/java/com/lambda/mixin/entity/ClientPlayerEntityMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.MovementType;
import net.minecraft.util.Hand;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
Expand All @@ -60,80 +59,50 @@ public ClientPlayerEntityMixin(ClientWorld world, GameProfile profile) {
super(world, profile);
}

@Shadow protected abstract void autoJump(float dx, float dz);

/**
* Post movement events and applies the modified player velocity
*/
@Inject(method = "move", at = @At("HEAD"), cancellable = true)
void onMove(MovementType movementType, Vec3d movement, CallbackInfo ci) {
ClientPlayerEntity self = (ClientPlayerEntity) (Object) this;
if (self != Lambda.getMc().player) return;

ci.cancel();

float prevX = (float) self.getX();
float prevZ = (float) self.getZ();

@Redirect(method = "move", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/AbstractClientPlayerEntity;move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V"))
private void emitMovementEvents(AbstractClientPlayerEntity instance, MovementType movementType, Vec3d movement) {
EventFlow.post(new MovementEvent.Player.Pre(movementType, movement));
super.move(movementType, movement);
EventFlow.post(new MovementEvent.Player.Post(movementType, movement));

float deltaX = (float) self.getX() - prevX;
float deltaZ = (float) self.getZ() - prevZ;

this.autoJump(deltaX, deltaZ);
this.distanceMoved = this.distanceMoved + MathHelper.hypot(deltaX, deltaZ) * 0.6F;
}

@Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/input/Input;tick()V"))
void processMovement(Input input) {
input.tick();
RotationManager.processRotations();
RotationManager.BaritoneProcessor.processPlayerMovement(input);
RotationManager.redirectStrafeInputs(input);
EventFlow.post(new MovementEvent.InputUpdate(input));
}

/**
* Posts the {@link MovementEvent.Sprint} event
* <pre>{@code
* if (this.isSprinting()) {
* boolean bl8 = !this.input.hasForwardMovement() || !this.canSprint();
* boolean bl9 = bl8 || this.horizontalCollision && !this.collidedSoftly || this.isTouchingWater() && !this.isSubmergedInWater();
* if (this.isSwimming()) {
* if (!this.isOnGround() && !this.input.sneaking && bl8 || !this.isTouchingWater()) {
* this.setSprinting(false);
* }
* } else if (bl9) {
* this.setSprinting(false);
* }
* }
* }</pre>
* Overwrites the movement packet update function to use our code
*/
@Inject(method = "sendMovementPackets", at = @At(value = "HEAD"), cancellable = true)
void sendLambdaMovement(CallbackInfo ci) {
ci.cancel();
PlayerPacketManager.sendPlayerPackets();
autoJumpEnabled = Lambda.getMc().options.getAutoJump().getValue();
}

@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;sendSneakingPacket()V"))
void sendSneakingPacket(ClientPlayerEntity entity) {
PlayerPacketManager.sendSneakPackets();
}

@Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isSprinting()Z"))
boolean isSprinting(ClientPlayerEntity entity) {
return EventFlow.post(new MovementEvent.Sprint(entity.isSprinting())).getSprint();
}

@Inject(method = "isSneaking", at = @At(value = "HEAD"), cancellable = true)
void redirectSneaking(CallbackInfoReturnable<Boolean> cir) {
void injectSneakingInput(CallbackInfoReturnable<Boolean> cir) {
ClientPlayerEntity self = (ClientPlayerEntity) (Object) this;
if (self != Lambda.getMc().player) return;

if (self.input == null) return;
cir.setReturnValue(EventFlow.post(new MovementEvent.Sneak(self.input.playerInput.sneak())).getSneak());
}

/**
* Overwrites the movement packet update function to use our code
*/
@Inject(method = "sendMovementPackets", at = @At(value = "HEAD"), cancellable = true)
void sendBegin(CallbackInfo ci) {
ci.cancel();
PlayerPacketManager.sendPlayerPackets();
autoJumpEnabled = Lambda.getMc().options.getAutoJump().getValue();
}

@WrapMethod(method = "tick")
void onTick(Operation<Void> original) {
EventFlow.post(TickEvent.Player.Pre.INSTANCE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.client.render.entity.LivingEntityRenderer;
import net.minecraft.entity.LivingEntity;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

import java.util.Objects;
import static com.lambda.util.math.LinearKt.lerp;

// This mixin's purpose is to set the player's pitch the current render pitch to correctly show the rotation
// regardless of the camera position
Expand All @@ -48,9 +49,12 @@ public class LivingEntityRendererMixin {
* }</pre>
*/
@WrapOperation(method = "updateRenderState(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/client/render/entity/state/LivingEntityRenderState;F)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getLerpedPitch(F)F"))
private float wrapGetLerpedPitch(LivingEntity instance, float v, Operation<Float> original) {
return (instance == Lambda.getMc().player)
? Objects.requireNonNullElse(RotationManager.getHeadPitch(), original.call(instance, v))
: original.call(instance, v);
private float wrapGetLerpedPitch(LivingEntity livingEntity, float v, Operation<Float> original) {
Float headPitch = RotationManager.getHeadPitch();
if (livingEntity != Lambda.getMc().player || headPitch == null) {
return original.call(livingEntity, v);
}

return lerp(v, RotationManager.getPrevServerRotation().getPitchF(), headPitch);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ sealed class PlayerPacketEvent {
var rotation: Rotation,
var onGround: Boolean,
var isSprinting: Boolean,
var isSneaking: Boolean,
var isCollidingHorizontally: Boolean,
) : ICancellable by Cancellable()

Expand Down
90 changes: 30 additions & 60 deletions 90 src/main/kotlin/com/lambda/interaction/PlayerPacketManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,11 @@ import com.lambda.event.EventFlow.post
import com.lambda.event.EventFlow.postChecked
import com.lambda.event.events.PlayerPacketEvent
import com.lambda.interaction.request.rotating.Rotation
import com.lambda.interaction.request.rotating.Rotation.Companion.rotation
import com.lambda.interaction.request.rotating.RotationManager
import com.lambda.threading.runSafe
import com.lambda.util.collections.LimitedOrderedSet
import com.lambda.util.math.approximate
import com.lambda.util.math.component1
import com.lambda.util.math.component2
import com.lambda.util.math.component3
import com.lambda.util.player.MovementUtils.motionX
import com.lambda.util.player.MovementUtils.motionZ
import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket.Full
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket.LookAndOnGround
Expand All @@ -46,6 +42,7 @@ object PlayerPacketManager {
var lastSprint = false
var lastSneak = false
var lastOnGround = false
var lastHorizontalCollision = false

private var sendTicks = 0

Expand All @@ -57,80 +54,66 @@ object PlayerPacketManager {
RotationManager.activeRotation,
player.isOnGround,
player.isSprinting,
player.isSneaking,
player.horizontalCollision,
).post {
updatePlayerPackets(this)
}
}
}

@JvmStatic
fun sendSneakPackets() {
runSafe {
val sneaking = player.isSneaking
if (sneaking == lastSneak) return@runSafe
val mode = if (sneaking) {
ClientCommandC2SPacket.Mode.PRESS_SHIFT_KEY
} else {
ClientCommandC2SPacket.Mode.RELEASE_SHIFT_KEY
}
connection.sendPacket(ClientCommandC2SPacket(player, mode))
lastSneak = sneaking
}
}

private fun SafeContext.updatePlayerPackets(new: PlayerPacketEvent.Pre) {
configurations.add(new)

reportSprint(lastSprint, new.isSprinting)
reportSneak(lastSneak, new.isSneaking)

if (mc.cameraEntity != player) return

val rotation = new.rotation
val position = new.position
val (yaw, pitch) = rotation.float
val (yaw, pitch) = new.rotation
val onGround = new.onGround
val isCollidingHorizontally = new.isCollidingHorizontally

if (player.hasVehicle()) {
connection.sendPacket(
Full(
player.motionX,
-999.0,
player.motionZ,
yaw,
pitch,
onGround,
isCollidingHorizontally,
)
)

return
}

val updatePosition = position.approximate(lastPosition, 2.0E-4) || ++sendTicks >= 20
// has to be different in float precision
val updateRotation = !rotation.equalFloat(lastRotation)

val (x, y, z) = position

val packet = when {
updatePosition && updateRotation ->
Full(x, y, z, yaw, pitch, onGround, isCollidingHorizontally)

updatePosition ->
PositionAndOnGround(x, y, z, onGround, isCollidingHorizontally)
val updatePosition = position.approximate(lastPosition) || ++sendTicks >= 20
val updateRotation = lastRotation.yaw != yaw || lastRotation.pitch != pitch

updateRotation ->
LookAndOnGround(yaw, pitch, onGround, isCollidingHorizontally)

lastOnGround != onGround ->
when {
updatePosition && updateRotation -> Full(position, yaw.toFloat(), pitch.toFloat(), onGround, isCollidingHorizontally)
updatePosition -> PositionAndOnGround(position, onGround, isCollidingHorizontally)
updateRotation -> LookAndOnGround(yaw.toFloat(), pitch.toFloat(), onGround, isCollidingHorizontally)
lastOnGround != onGround || lastHorizontalCollision != isCollidingHorizontally -> {
OnGroundOnly(onGround, isCollidingHorizontally)

}
else -> null
}

packet?.let {
}?.let {
PlayerPacketEvent.Send(it).postChecked {
connection.sendPacket(this.packet)

if (updatePosition) {
sendTicks = 0
lastPosition = position
sendTicks = 0
}

if (updateRotation) {
lastRotation = rotation
lastRotation = new.rotation
}

lastOnGround = onGround
lastHorizontalCollision = isCollidingHorizontally
}
}

Expand All @@ -152,19 +135,6 @@ object PlayerPacketManager {
connection.sendPacket(ClientCommandC2SPacket(player, state))
lastSprint = new
}

fun SafeContext.reportSneak(previous: Boolean, new: Boolean) {
if (previous == new) return

val state = if (new) {
ClientCommandC2SPacket.Mode.PRESS_SHIFT_KEY
} else {
ClientCommandC2SPacket.Mode.RELEASE_SHIFT_KEY
}

connection.sendPacket(ClientCommandC2SPacket(player, state))
lastSneak = new
}
}


34 changes: 12 additions & 22 deletions 34 src/main/kotlin/com/lambda/interaction/request/rotating/Rotation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -108,42 +108,31 @@ data class Rotation(val yaw: Double, val pitch: Double) {
fun Rotation.lerp(other: Rotation, delta: Double): Rotation {
// Calculate the wrapped difference to ensure we take the shortest path
val yawDiff = wrap(other.yaw - this.yaw)
val pitchDiff = wrap(other.pitch - this.pitch)
val pitchDiff = other.pitch - this.pitch

// Apply the delta to the wrapped difference
val yaw = wrap(this.yaw + delta * yawDiff)
val pitch = wrap(this.pitch + delta * pitchDiff)
// Apply without wrapping the absolute yaw (keep it continuous)
val yaw = this.yaw + delta * yawDiff
val pitch = (this.pitch + delta * pitchDiff).coerceIn(-90.0, 90.0)

return Rotation(yaw, pitch)
}

fun Rotation.slerp(other: Rotation, speed: Double): Rotation {
val yawDiff = wrap(other.yaw - yaw)
val pitchDiff = wrap(other.pitch - pitch)
val pitchDiff = other.pitch - pitch

val diff = hypot(yawDiff, pitchDiff)
val diff = hypot(yawDiff, pitchDiff).let { if (it == 0.0) 1.0 else it }

val yawSpeed = abs(yawDiff / diff) * speed
val pitchSpeed = abs(pitchDiff / diff) * speed

val yaw = wrap(yaw + yawDiff.coerceIn(-yawSpeed, yawSpeed))
val pitch = wrap(pitch + pitchDiff.coerceIn(-pitchSpeed, pitchSpeed))
// Apply without wrapping the absolute yaw (keep it continuous)
val yaw = yaw + yawDiff.coerceIn(-yawSpeed, yawSpeed)
val pitch = (pitch + pitchDiff.coerceIn(-pitchSpeed, pitchSpeed)).coerceIn(-90.0, 90.0)

return Rotation(yaw, pitch)
}

fun Rotation.fixSensitivity(prev: Rotation): Rotation {
val f = mc.options.mouseSensitivity.value * 0.6 + 0.2
val gcd = f * f * f * 8.0 * 0.15F

val r1 = Vec2d(prev.yaw, prev.pitch)
val r2 = Vec2d(this.yaw, this.pitch)
val delta = ((r2 - r1) / gcd).roundToInt() * gcd
val fixed = r1 + delta

return Rotation(fixed.x, fixed.y.coerceIn(-90.0, 90.0))
}

fun Vec3d.rotationTo(vec: Vec3d): Rotation {
val diffX = vec.x - x
val diffY = vec.y - y
Expand All @@ -152,8 +141,9 @@ data class Rotation(val yaw: Double, val pitch: Double) {
val yawRad = atan2(diffZ, diffX)
val pitchRad = -atan2(diffY, hypot(diffX, diffZ))

val yaw = wrap(yawRad.toDegree() - 90.0)
val pitch = wrap(pitchRad.toDegree())
// Target yaw can be normalized; our slerp keeps absolute yaw continuous
val yaw = yawRad.toDegree() - 90.0
val pitch = pitchRad.toDegree().coerceIn(-90.0, 90.0)

return Rotation(yaw, pitch)
}
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.