Skip to content

Commit 468bd09

Browse files
committed
Fix sneak flags and rotation flags
1 parent acd6b95 commit 468bd09

File tree

6 files changed

+64
-140
lines changed

6 files changed

+64
-140
lines changed

src/main/java/com/lambda/mixin/entity/ClientPlayerEntityMixin.java

Lines changed: 17 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import net.minecraft.client.world.ClientWorld;
3838
import net.minecraft.entity.MovementType;
3939
import net.minecraft.util.Hand;
40-
import net.minecraft.util.math.MathHelper;
4140
import net.minecraft.util.math.Vec3d;
4241
import org.spongepowered.asm.mixin.Final;
4342
import org.spongepowered.asm.mixin.Mixin;
@@ -60,80 +59,50 @@ public ClientPlayerEntityMixin(ClientWorld world, GameProfile profile) {
6059
super(world, profile);
6160
}
6261

63-
@Shadow protected abstract void autoJump(float dx, float dz);
64-
65-
/**
66-
* Post movement events and applies the modified player velocity
67-
*/
68-
@Inject(method = "move", at = @At("HEAD"), cancellable = true)
69-
void onMove(MovementType movementType, Vec3d movement, CallbackInfo ci) {
70-
ClientPlayerEntity self = (ClientPlayerEntity) (Object) this;
71-
if (self != Lambda.getMc().player) return;
72-
73-
ci.cancel();
74-
75-
float prevX = (float) self.getX();
76-
float prevZ = (float) self.getZ();
77-
62+
@Redirect(method = "move", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/AbstractClientPlayerEntity;move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V"))
63+
private void emitMovementEvents(AbstractClientPlayerEntity instance, MovementType movementType, Vec3d movement) {
7864
EventFlow.post(new MovementEvent.Player.Pre(movementType, movement));
7965
super.move(movementType, movement);
8066
EventFlow.post(new MovementEvent.Player.Post(movementType, movement));
81-
82-
float deltaX = (float) self.getX() - prevX;
83-
float deltaZ = (float) self.getZ() - prevZ;
84-
85-
this.autoJump(deltaX, deltaZ);
86-
this.distanceMoved = this.distanceMoved + MathHelper.hypot(deltaX, deltaZ) * 0.6F;
8767
}
8868

8969
@Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/input/Input;tick()V"))
9070
void processMovement(Input input) {
9171
input.tick();
9272
RotationManager.processRotations();
93-
RotationManager.BaritoneProcessor.processPlayerMovement(input);
73+
RotationManager.BaritoneProcessor.processInputs(input);
9474
EventFlow.post(new MovementEvent.InputUpdate(input));
9575
}
9676

9777
/**
98-
* Posts the {@link MovementEvent.Sprint} event
99-
* <pre>{@code
100-
* if (this.isSprinting()) {
101-
* boolean bl8 = !this.input.hasForwardMovement() || !this.canSprint();
102-
* boolean bl9 = bl8 || this.horizontalCollision && !this.collidedSoftly || this.isTouchingWater() && !this.isSubmergedInWater();
103-
* if (this.isSwimming()) {
104-
* if (!this.isOnGround() && !this.input.sneaking && bl8 || !this.isTouchingWater()) {
105-
* this.setSprinting(false);
106-
* }
107-
* } else if (bl9) {
108-
* this.setSprinting(false);
109-
* }
110-
* }
111-
* }</pre>
78+
* Overwrites the movement packet update function to use our code
11279
*/
80+
@Inject(method = "sendMovementPackets", at = @At(value = "HEAD"), cancellable = true)
81+
void sendLambdaMovement(CallbackInfo ci) {
82+
ci.cancel();
83+
PlayerPacketManager.sendPlayerPackets();
84+
autoJumpEnabled = Lambda.getMc().options.getAutoJump().getValue();
85+
}
86+
87+
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;sendSneakingPacket()V"))
88+
void sendSneakingPacket(ClientPlayerEntity entity) {
89+
PlayerPacketManager.sendSneakPackets();
90+
}
91+
11392
@Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isSprinting()Z"))
11493
boolean isSprinting(ClientPlayerEntity entity) {
11594
return EventFlow.post(new MovementEvent.Sprint(entity.isSprinting())).getSprint();
11695
}
11796

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

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

127-
/**
128-
* Overwrites the movement packet update function to use our code
129-
*/
130-
@Inject(method = "sendMovementPackets", at = @At(value = "HEAD"), cancellable = true)
131-
void sendBegin(CallbackInfo ci) {
132-
ci.cancel();
133-
PlayerPacketManager.sendPlayerPackets();
134-
autoJumpEnabled = Lambda.getMc().options.getAutoJump().getValue();
135-
}
136-
137106
@WrapMethod(method = "tick")
138107
void onTick(Operation<Void> original) {
139108
EventFlow.post(TickEvent.Player.Pre.INSTANCE);

src/main/kotlin/com/lambda/event/events/PlayerPacketEvent.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ sealed class PlayerPacketEvent {
3030
var rotation: Rotation,
3131
var onGround: Boolean,
3232
var isSprinting: Boolean,
33-
var isSneaking: Boolean,
3433
var isCollidingHorizontally: Boolean,
3534
) : ICancellable by Cancellable()
3635

src/main/kotlin/com/lambda/interaction/PlayerPacketManager.kt

Lines changed: 28 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,6 @@ import com.lambda.interaction.request.rotating.RotationManager
2626
import com.lambda.threading.runSafe
2727
import com.lambda.util.collections.LimitedOrderedSet
2828
import com.lambda.util.math.approximate
29-
import com.lambda.util.math.component1
30-
import com.lambda.util.math.component2
31-
import com.lambda.util.math.component3
32-
import com.lambda.util.player.MovementUtils.motionX
33-
import com.lambda.util.player.MovementUtils.motionZ
3429
import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket
3530
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket.Full
3631
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket.LookAndOnGround
@@ -46,6 +41,7 @@ object PlayerPacketManager {
4641
var lastSprint = false
4742
var lastSneak = false
4843
var lastOnGround = false
44+
var lastHorizontalCollision = false
4945

5046
private var sendTicks = 0
5147

@@ -57,80 +53,66 @@ object PlayerPacketManager {
5753
RotationManager.activeRotation,
5854
player.isOnGround,
5955
player.isSprinting,
60-
player.isSneaking,
6156
player.horizontalCollision,
6257
).post {
6358
updatePlayerPackets(this)
6459
}
6560
}
6661
}
6762

63+
@JvmStatic
64+
fun sendSneakPackets() {
65+
runSafe {
66+
val sneaking = player.isSneaking
67+
if (sneaking == lastSneak) return@runSafe
68+
val mode = if (sneaking) {
69+
ClientCommandC2SPacket.Mode.PRESS_SHIFT_KEY
70+
} else {
71+
ClientCommandC2SPacket.Mode.RELEASE_SHIFT_KEY
72+
}
73+
connection.sendPacket(ClientCommandC2SPacket(player, mode))
74+
lastSneak = sneaking
75+
}
76+
}
77+
6878
private fun SafeContext.updatePlayerPackets(new: PlayerPacketEvent.Pre) {
6979
configurations.add(new)
7080

7181
reportSprint(lastSprint, new.isSprinting)
72-
reportSneak(lastSneak, new.isSneaking)
7382

7483
if (mc.cameraEntity != player) return
7584

76-
val rotation = new.rotation
7785
val position = new.position
78-
val (yaw, pitch) = rotation.float
86+
val (yaw, pitch) = new.rotation
7987
val onGround = new.onGround
8088
val isCollidingHorizontally = new.isCollidingHorizontally
8189

82-
if (player.hasVehicle()) {
83-
connection.sendPacket(
84-
Full(
85-
player.motionX,
86-
-999.0,
87-
player.motionZ,
88-
yaw,
89-
pitch,
90-
onGround,
91-
isCollidingHorizontally,
92-
)
93-
)
94-
95-
return
96-
}
97-
9890
val updatePosition = position.approximate(lastPosition, 2.0E-4) || ++sendTicks >= 20
99-
// has to be different in float precision
100-
val updateRotation = !rotation.equalFloat(lastRotation)
101-
102-
val (x, y, z) = position
103-
104-
val packet = when {
105-
updatePosition && updateRotation ->
106-
Full(x, y, z, yaw, pitch, onGround, isCollidingHorizontally)
107-
108-
updatePosition ->
109-
PositionAndOnGround(x, y, z, onGround, isCollidingHorizontally)
91+
val updateRotation = lastRotation.yaw != yaw || lastRotation.pitch != pitch
11092

111-
updateRotation ->
112-
LookAndOnGround(yaw, pitch, onGround, isCollidingHorizontally)
113-
114-
lastOnGround != onGround ->
93+
when {
94+
updatePosition && updateRotation -> Full(position, yaw.toFloat(), pitch.toFloat(), onGround, isCollidingHorizontally)
95+
updatePosition -> PositionAndOnGround(position, onGround, isCollidingHorizontally)
96+
updateRotation -> LookAndOnGround(yaw.toFloat(), pitch.toFloat(), onGround, isCollidingHorizontally)
97+
lastOnGround != onGround || lastHorizontalCollision != isCollidingHorizontally -> {
11598
OnGroundOnly(onGround, isCollidingHorizontally)
116-
99+
}
117100
else -> null
118-
}
119-
120-
packet?.let {
101+
}?.let {
121102
PlayerPacketEvent.Send(it).postChecked {
122103
connection.sendPacket(this.packet)
123104

124105
if (updatePosition) {
125-
sendTicks = 0
126106
lastPosition = position
107+
sendTicks = 0
127108
}
128109

129110
if (updateRotation) {
130-
lastRotation = rotation
111+
lastRotation = new.rotation
131112
}
132113

133114
lastOnGround = onGround
115+
lastHorizontalCollision = isCollidingHorizontally
134116
}
135117
}
136118

@@ -152,19 +134,6 @@ object PlayerPacketManager {
152134
connection.sendPacket(ClientCommandC2SPacket(player, state))
153135
lastSprint = new
154136
}
155-
156-
fun SafeContext.reportSneak(previous: Boolean, new: Boolean) {
157-
if (previous == new) return
158-
159-
val state = if (new) {
160-
ClientCommandC2SPacket.Mode.PRESS_SHIFT_KEY
161-
} else {
162-
ClientCommandC2SPacket.Mode.RELEASE_SHIFT_KEY
163-
}
164-
165-
connection.sendPacket(ClientCommandC2SPacket(player, state))
166-
lastSneak = new
167-
}
168137
}
169138

170139

src/main/kotlin/com/lambda/interaction/request/rotating/Rotation.kt

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -108,42 +108,31 @@ data class Rotation(val yaw: Double, val pitch: Double) {
108108
fun Rotation.lerp(other: Rotation, delta: Double): Rotation {
109109
// Calculate the wrapped difference to ensure we take the shortest path
110110
val yawDiff = wrap(other.yaw - this.yaw)
111-
val pitchDiff = wrap(other.pitch - this.pitch)
111+
val pitchDiff = other.pitch - this.pitch
112112

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

117117
return Rotation(yaw, pitch)
118118
}
119119

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

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

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

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

132133
return Rotation(yaw, pitch)
133134
}
134135

135-
fun Rotation.fixSensitivity(prev: Rotation): Rotation {
136-
val f = mc.options.mouseSensitivity.value * 0.6 + 0.2
137-
val gcd = f * f * f * 8.0 * 0.15F
138-
139-
val r1 = Vec2d(prev.yaw, prev.pitch)
140-
val r2 = Vec2d(this.yaw, this.pitch)
141-
val delta = ((r2 - r1) / gcd).roundToInt() * gcd
142-
val fixed = r1 + delta
143-
144-
return Rotation(fixed.x, fixed.y.coerceIn(-90.0, 90.0))
145-
}
146-
147136
fun Vec3d.rotationTo(vec: Vec3d): Rotation {
148137
val diffX = vec.x - x
149138
val diffY = vec.y - y
@@ -152,8 +141,9 @@ data class Rotation(val yaw: Double, val pitch: Double) {
152141
val yawRad = atan2(diffZ, diffX)
153142
val pitchRad = -atan2(diffY, hypot(diffX, diffZ))
154143

155-
val yaw = wrap(yawRad.toDegree() - 90.0)
156-
val pitch = wrap(pitchRad.toDegree())
144+
// Target yaw can be normalized; our slerp keeps absolute yaw continuous
145+
val yaw = yawRad.toDegree() - 90.0
146+
val pitch = pitchRad.toDegree().coerceIn(-90.0, 90.0)
157147

158148
return Rotation(yaw, pitch)
159149
}

src/main/kotlin/com/lambda/interaction/request/rotating/RotationManager.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import com.lambda.event.listener.SafeListener.Companion.listen
2929
import com.lambda.event.listener.UnsafeListener.Companion.listenUnsafe
3030
import com.lambda.interaction.request.RequestHandler
3131
import com.lambda.interaction.request.rotating.Rotation.Companion.slerp
32-
import com.lambda.interaction.request.rotating.Rotation.Companion.wrap
3332
import com.lambda.interaction.request.rotating.visibilty.lookAt
3433
import com.lambda.module.modules.client.Baritone
3534
import com.lambda.threading.runGameScheduled
@@ -124,7 +123,6 @@ object RotationManager : RequestHandler<RotationRequest>(
124123
prevServerRotation = serverRotation
125124
serverRotation = activeRotation/*.fixSensitivity(prevServerRotation)*/
126125

127-
// Handle LOCK mode
128126
if (activeRequest?.rotationMode == RotationMode.Lock) {
129127
mc.player?.yaw = serverRotation.yawF
130128
mc.player?.pitch = serverRotation.pitchF
@@ -141,7 +139,8 @@ object RotationManager : RequestHandler<RotationRequest>(
141139
val speedMultiplier = if (request.keepTicks < 0) 1.0 else request.speedMultiplier
142140
val turnSpeed = request.turnSpeed * speedMultiplier
143141

144-
serverRotation.slerp(rotationTo, turnSpeed).wrap()
142+
// Important: do NOT wrap the result yaw; keep it continuous to match vanilla packets
143+
serverRotation.slerp(rotationTo, turnSpeed)
145144
} ?: player.rotation
146145
}
147146

@@ -219,10 +218,11 @@ object RotationManager : RequestHandler<RotationRequest>(
219218
}
220219

221220
@JvmStatic
222-
fun processPlayerMovement(input: Input) = runSafe {
221+
fun processInputs(input: Input) = runSafe {
223222
// The yaw relative to which the movement was constructed
224223
val baritoneYaw = baritoneContext?.target?.targetRotation?.value?.yaw
225-
val strafeEvent = RotationEvent.StrafeInput(baritoneYaw ?: player.yaw.toDouble(), input)
224+
val baseYaw = baritoneYaw ?: activeRotation.yaw
225+
val strafeEvent = RotationEvent.StrafeInput(baseYaw, input)
226226
val movementYaw = strafeEvent.post().strafeYaw
227227

228228
// No changes are needed, when we don't modify the yaw used to move the player

src/main/kotlin/com/lambda/module/modules/movement/Speed.kt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,7 @@ object Speed : Module(
139139

140140
if (!input.isInputting) return@listen
141141

142-
run {
143-
if (!diagonal) return@run
144-
if (player.isOnGround && input.playerInput.jump) return@run
145-
142+
if (diagonal || !player.isOnGround || !input.playerInput.jump) {
146143
val forward = input.roundedForward.toFloat()
147144
var strafe = input.roundedStrafing.toFloat()
148145

@@ -155,7 +152,7 @@ object Speed : Module(
155152
val moveYaw = calcMoveYaw(yaw, input.roundedForward, input.roundedStrafing)
156153

157154
lookAt(
158-
Rotation(moveYaw, 0.0)
155+
Rotation(moveYaw, player.pitch.toDouble())
159156
).requestBy(rotationConfig)
160157
}
161158

0 commit comments

Comments
 (0)