Skip to content

Commit 66e934c

Browse files
authored
fix client rotations compatibility (#239)
1 parent 30a7a84 commit 66e934c

File tree

6 files changed

+69
-82
lines changed

6 files changed

+69
-82
lines changed

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

Lines changed: 36 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -17,60 +17,67 @@
1717

1818
package com.lambda.mixin.entity;
1919

20-
import com.lambda.Lambda;
2120
import com.lambda.event.EventFlow;
2221
import com.lambda.event.events.MovementEvent;
2322
import com.lambda.event.events.PlayerEvent;
2423
import com.lambda.event.events.PlayerPacketEvent;
2524
import com.lambda.event.events.TickEvent;
26-
import com.lambda.interaction.managers.rotating.Rotation;
2725
import com.lambda.interaction.managers.rotating.RotationManager;
2826
import com.lambda.module.modules.movement.ElytraFly;
2927
import com.lambda.module.modules.movement.NoJumpCooldown;
3028
import com.lambda.module.modules.player.PortalGui;
3129
import com.lambda.module.modules.render.ViewModel;
32-
import com.llamalad7.mixinextras.expression.Definition;
33-
import com.llamalad7.mixinextras.expression.Expression;
3430
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
3531
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
3632
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
3733
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
3834
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
39-
import com.llamalad7.mixinextras.sugar.Local;
35+
import com.llamalad7.mixinextras.sugar.Share;
36+
import com.llamalad7.mixinextras.sugar.ref.LocalRef;
4037
import com.mojang.authlib.GameProfile;
4138
import net.minecraft.client.gui.screen.Screen;
4239
import net.minecraft.client.input.Input;
4340
import net.minecraft.client.network.AbstractClientPlayerEntity;
41+
import net.minecraft.client.network.ClientPlayNetworkHandler;
4442
import net.minecraft.client.network.ClientPlayerEntity;
4543
import net.minecraft.client.world.ClientWorld;
4644
import net.minecraft.entity.MovementType;
45+
import net.minecraft.network.packet.Packet;
4746
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
4847
import net.minecraft.util.Hand;
48+
import net.minecraft.util.math.Vec2f;
4949
import net.minecraft.util.math.Vec3d;
5050
import org.objectweb.asm.Opcodes;
5151
import org.spongepowered.asm.mixin.Mixin;
52-
import org.spongepowered.asm.mixin.Shadow;
53-
import org.spongepowered.asm.mixin.Unique;
5452
import org.spongepowered.asm.mixin.injection.At;
5553
import org.spongepowered.asm.mixin.injection.Inject;
5654
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
57-
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
5855

5956
import java.util.Objects;
6057

58+
import static com.lambda.Lambda.getMc;
59+
6160
@Mixin(value = ClientPlayerEntity.class, priority = Integer.MAX_VALUE)
6261
public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity {
63-
@Shadow
64-
private float lastYawClient;
65-
@Shadow
66-
private float lastPitchClient;
67-
@Unique
68-
private PlayerPacketEvent.Pre moveEvent;
69-
7062
public ClientPlayerEntityMixin(ClientWorld world, GameProfile profile) {
7163
super(world, profile);
7264
}
7365

66+
@WrapMethod(method = "tick")
67+
void onTick(Operation<Void> original) {
68+
EventFlow.post(TickEvent.Player.Pre.INSTANCE);
69+
original.call();
70+
EventFlow.post(TickEvent.Player.Post.INSTANCE);
71+
}
72+
73+
@Inject(method = "tick", at = @At("HEAD"))
74+
private void injectTick(CallbackInfo ci, @Share(namespace = "shared_rotations", value = "target_rotation") final LocalRef<Vec2f> targetRotation) {
75+
if (RotationManager.getRequests().stream().anyMatch(Objects::nonNull)) {
76+
final var activeRotation = RotationManager.getActiveRotation();
77+
targetRotation.set(new Vec2f(activeRotation.getYawF(), activeRotation.getPitchF()));
78+
}
79+
}
80+
7481
@WrapOperation(method = "move", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/AbstractClientPlayerEntity;move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V"))
7582
private void wrapMove(ClientPlayerEntity instance, MovementType movementType, Vec3d vec3d, Operation<Void> original) {
7683
EventFlow.post(new MovementEvent.Player.Pre(movementType, vec3d));
@@ -91,43 +98,23 @@ private void injectTickMovement(CallbackInfo ci) {
9198
if (NoJumpCooldown.INSTANCE.isEnabled() || (ElytraFly.INSTANCE.isEnabled() && ElytraFly.getMode() == ElytraFly.FlyMode.Bounce)) jumpingCooldown = 0;
9299
}
93100

94-
@Inject(method = "sendMovementPackets", at = @At("HEAD"))
95-
private void injectSendMovementPacketsHead(CallbackInfo ci) {
96-
moveEvent = EventFlow.post(new PlayerPacketEvent.Pre(pos, RotationManager.getActiveRotation(), isOnGround(), isSprinting(), horizontalCollision));
97-
}
98-
99-
@Definition(id = "g", local = @Local(type = double.class, ordinal = 3))
100-
@Expression("g != 0.0")
101-
@ModifyExpressionValue(method = "sendMovementPackets", at = @At("MIXINEXTRAS:EXPRESSION"))
102-
private boolean modifyHasRotated(boolean original) {
103-
return !RotationManager.getActiveRotation().equalFloat(RotationManager.getServerRotation()) || original;
101+
@ModifyExpressionValue(method = "sendMovementPackets", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;getYaw()F"))
102+
private float modifyGetYaw(float original) {
103+
final var yaw = RotationManager.getHeadYaw();
104+
return yaw != null ? yaw : original;
104105
}
105106

106-
@Inject(method = "sendMovementPackets", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;)V", shift = At.Shift.BEFORE), locals = LocalCapture.CAPTURE_FAILEXCEPTION)
107-
private void injectSendPacket(CallbackInfo ci, double d, double e, double f, double g, double h, boolean bl, boolean bl2) {
108-
if (RotationManager.getRequests().stream().allMatch(Objects::isNull)) {
109-
moveEvent.setRotation(new Rotation(g + lastYawClient, h + lastPitchClient));
110-
}
111-
}
112-
113-
@WrapOperation(method = "sendMovementPackets", at = @At(value = "NEW", target = "net/minecraft/network/packet/c2s/play/PlayerMoveC2SPacket$Full"))
114-
private PlayerMoveC2SPacket.Full wrapFullPacket(Vec3d pos, float yaw, float pitch, boolean onGround, boolean horizontalCollision, Operation<PlayerMoveC2SPacket.Full> original) {
115-
return original.call(moveEvent.getPosition(), moveEvent.getRotation().getYawF(), moveEvent.getRotation().getPitchF(), moveEvent.getOnGround(), moveEvent.isCollidingHorizontally());
116-
}
117-
118-
@WrapOperation(method = "sendMovementPackets", at = @At(value = "NEW", target = "net/minecraft/network/packet/c2s/play/PlayerMoveC2SPacket$PositionAndOnGround"))
119-
private PlayerMoveC2SPacket.PositionAndOnGround wrapPositionAndOnGround(Vec3d pos, boolean onGround, boolean horizontalCollision, Operation<PlayerMoveC2SPacket.PositionAndOnGround> original) {
120-
return original.call(moveEvent.getPosition(), moveEvent.getOnGround(), moveEvent.isCollidingHorizontally());
121-
}
122-
123-
@WrapOperation(method = "sendMovementPackets", at = @At(value = "NEW", target = "net/minecraft/network/packet/c2s/play/PlayerMoveC2SPacket$LookAndOnGround"))
124-
private PlayerMoveC2SPacket.LookAndOnGround wrapLookAndOnGround(float yaw, float pitch, boolean onGround, boolean horizontalCollision, Operation<PlayerMoveC2SPacket.LookAndOnGround> original) {
125-
return original.call(moveEvent.getRotation().getYawF(), moveEvent.getRotation().getPitchF(), moveEvent.getOnGround(), moveEvent.isCollidingHorizontally());
107+
@ModifyExpressionValue(method = "sendMovementPackets", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;getPitch()F"))
108+
private float modifyGetPitch(float original) {
109+
final var pitch = RotationManager.getHeadPitch();
110+
return pitch != null ? pitch : original;
126111
}
127112

128-
@WrapOperation(method = "sendMovementPackets", at = @At(value = "NEW", target = "net/minecraft/network/packet/c2s/play/PlayerMoveC2SPacket$OnGroundOnly"))
129-
private PlayerMoveC2SPacket.OnGroundOnly wrapOnGroundOnly(boolean onGround, boolean horizontalCollision, Operation<PlayerMoveC2SPacket.OnGroundOnly> original) {
130-
return original.call(moveEvent.getOnGround(), moveEvent.isCollidingHorizontally());
113+
@WrapOperation(method = "sendMovementPackets", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;)V"))
114+
private void wrapSendPacket(ClientPlayNetworkHandler instance, Packet packet, Operation<Void> original) {
115+
var event = EventFlow.post(new PlayerPacketEvent.Send((PlayerMoveC2SPacket) packet));
116+
if (event.isCanceled()) return;
117+
original.call(instance, event.getPacket());
131118
}
132119

133120
@Inject(method = "sendMovementPackets", at = @At("TAIL"))
@@ -144,19 +131,11 @@ boolean modifyIsSprinting(boolean original) {
144131
@ModifyReturnValue(method = "isSneaking", at = @At("RETURN"))
145132
boolean injectSneakingInput(boolean original) {
146133
ClientPlayerEntity self = (ClientPlayerEntity) (Object) this;
147-
if (self != Lambda.getMc().player ||
148-
self.input == null) return original;
134+
if (self != getMc().player || self.input == null) return original;
149135

150136
return EventFlow.post(new MovementEvent.Sneak(self.input.playerInput.sneak())).getSneak();
151137
}
152138

153-
@WrapMethod(method = "tick")
154-
void onTick(Operation<Void> original) {
155-
EventFlow.post(TickEvent.Player.Pre.INSTANCE);
156-
original.call();
157-
EventFlow.post(TickEvent.Player.Post.INSTANCE);
158-
}
159-
160139
@WrapOperation(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;getYaw()F"))
161140
float wrapGetYaw(ClientPlayerEntity instance, Operation<Float> original) {
162141
return Objects.requireNonNullElse(RotationManager.getHandYaw(), original.call(instance));

src/main/kotlin/com/lambda/config/groups/OutlineSettings.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class OutlineSettings(
2929
vararg baseGroup: NamedEnum,
3030
override val visibility: () -> Boolean = { true },
3131
) : SettingGroup(c) {
32-
val thicknessSetting by c.setting("${prefix}Line Width", 10, 1..100, 1, "The width of the outline", visibility = visibility).group(*baseGroup).index()
32+
val thicknessSetting by c.setting("${prefix}Line Width", 40, 1..100, 1, "The width of the outline", visibility = visibility).group(*baseGroup).index()
3333
val thickness get() = thicknessSetting * 0.00005f
3434

3535
val glowIntensitySetting by c.setting("${prefix}Glow Intensity", 50, 0..100, 1, "Intensity of the outline glow", visibility = visibility).group(*baseGroup).index()

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

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,11 @@ package com.lambda.event.events
2020
import com.lambda.event.Event
2121
import com.lambda.event.callback.Cancellable
2222
import com.lambda.event.callback.ICancellable
23-
import com.lambda.interaction.managers.rotating.Rotation
2423
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket
25-
import net.minecraft.util.math.Vec3d
2624

2725
sealed class PlayerPacketEvent {
28-
data class Pre(
29-
var position: Vec3d,
30-
var rotation: Rotation,
31-
var onGround: Boolean,
32-
var isSprinting: Boolean,
33-
var isCollidingHorizontally: Boolean,
34-
) : Event
35-
3626
data class Send(
37-
val packet: PlayerMoveC2SPacket,
27+
var packet: PlayerMoveC2SPacket,
3828
) : ICancellable by Cancellable()
3929

4030
class Post : Event

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

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,12 @@ import com.lambda.module.tag.ModuleTag
2828
import com.lambda.util.NamedEnum
2929
import com.lambda.util.extension.isElytraFlying
3030
import com.lambda.util.math.MathUtils.toInt
31-
import com.lambda.util.math.minus
3231
import com.lambda.util.player.MovementUtils.isInputting
3332
import com.lambda.util.player.MovementUtils.motionY
3433
import com.lambda.util.player.MovementUtils.setSpeed
3534
import net.minecraft.block.Blocks
35+
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket.Full
36+
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket.PositionAndOnGround
3637
import net.minecraft.util.math.BlockPos
3738
import net.minecraft.util.math.Vec3d
3839
import net.minecraft.util.shape.VoxelShapes
@@ -54,6 +55,8 @@ object Jesus : Module(
5455
private var goUp = true
5556
private var swimmingTicks = 0
5657

58+
private var prevPos = Vec3d.ZERO
59+
5760
enum class Mode(override val displayName: String, val collision: Boolean) : NamedEnum {
5861
Ncp("NCP", true),
5962
NcpDolphin("NCP Dolphin", false),
@@ -63,22 +66,17 @@ object Jesus : Module(
6366
private var shouldWork = false
6467

6568
init {
66-
listen<PlayerPacketEvent.Pre> { event ->
69+
listen<PlayerPacketEvent.Send> { event ->
6770
if (!shouldWork || !waterAt(-0.0001)) return@listen
68-
event.onGround = false
6971

7072
if (!player.isOnGround) return@listen
7173

7274
when (mode) {
7375
Mode.Ncp -> {
7476
val offset = if (player.age % 2 == 0) 0.001 else 0.002
75-
event.position -= Vec3d(0.0, offset, 0.0)
77+
event.lowerPosition(offset)
7678
}
77-
78-
Mode.NcpNew -> {
79-
event.position -= Vec3d(0.0, 0.02 + 0.0001 * swimmingTicks, 0.0)
80-
}
81-
79+
Mode.NcpNew -> event.lowerPosition(0.02 + 0.0001 * swimmingTicks)
8280
else -> {}
8381
}
8482
}
@@ -151,6 +149,19 @@ object Jesus : Module(
151149
}
152150
}
153151

152+
private fun PlayerPacketEvent.Send.lowerPosition(amount: Double) {
153+
with(packet) {
154+
val newPos = Vec3d(x, y - amount, z)
155+
when(this) {
156+
is Full -> packet = Full(newPos, yaw, pitch, isOnGround, horizontalCollision())
157+
is PositionAndOnGround -> packet = PositionAndOnGround(newPos, isOnGround, horizontalCollision())
158+
else -> if (newPos != prevPos) packet = PositionAndOnGround(newPos, isOnGround, horizontalCollision())
159+
}
160+
161+
prevPos = newPos
162+
}
163+
}
164+
154165
private fun SafeContext.waterAt(yOffset: Double): Boolean {
155166
val b = player.boundingBox
156167
val y = b.minY + yOffset

src/main/kotlin/com/lambda/module/modules/network/Rubberband.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ import com.lambda.util.math.distSq
2929
import com.lambda.util.text.buildText
3030
import com.lambda.util.text.color
3131
import com.lambda.util.text.literal
32+
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket
3233
import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket
34+
import net.minecraft.util.math.Vec3d
3335
import java.awt.Color
3436

3537
// ToDo: Should also include last packet info as HUD element and connection state.
@@ -44,7 +46,7 @@ object Rubberband : Module(
4446
private val showConnectionState by setting("Show Connection State", true)
4547
private val showRubberbandInfo by setting("Show Rubberband Info", true)
4648

47-
val configurations = LimitedOrderedSet<PlayerPacketEvent.Pre>(100)
49+
val configurations = LimitedOrderedSet<Vec3d>(100)
4850

4951
init {
5052
listen<PacketEvent.Receive.Pre> { event ->
@@ -58,7 +60,7 @@ object Rubberband : Module(
5860

5961
val newPos = event.packet.change.position
6062
val last = configurations.minBy {
61-
it.position distSq newPos
63+
it distSq newPos
6264
}
6365

6466
this@Rubberband.warn(buildText {
@@ -68,12 +70,12 @@ object Rubberband : Module(
6870
}
6971
literal(" ticks (deviation: ")
7072
color(Color.YELLOW) {
71-
literal("%.3f".format(last.position dist newPos))
73+
literal("%.3f".format(last dist newPos))
7274
}
7375
literal(")")
7476
})
7577
}
7678

77-
listen<PlayerPacketEvent.Pre> { configurations.add(it) }
79+
listen<PlayerPacketEvent.Send> { configurations.add(with(it.packet) { Vec3d(x, y, z) }) }
7880
}
7981
}

src/main/resources/lambda.accesswidener

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,11 @@ transitive-accessible field net/minecraft/network/packet/c2s/play/PlayerInteract
129129
transitive-accessible method net/minecraft/network/packet/BrandCustomPayload write (Lnet/minecraft/network/PacketByteBuf;)V
130130
transitive-accessible method net/minecraft/client/network/ClientPlayerInteractionManager sendSequencedPacket (Lnet/minecraft/client/world/ClientWorld;Lnet/minecraft/client/network/SequencedPacketCreator;)V
131131
transitive-accessible field net/minecraft/client/world/ClientWorld pendingUpdateManager Lnet/minecraft/client/network/PendingUpdateManager;
132+
transitive-accessible field net/minecraft/network/packet/c2s/play/PlayerMoveC2SPacket x D
133+
transitive-accessible field net/minecraft/network/packet/c2s/play/PlayerMoveC2SPacket y D
134+
transitive-accessible field net/minecraft/network/packet/c2s/play/PlayerMoveC2SPacket z D
135+
transitive-accessible field net/minecraft/network/packet/c2s/play/PlayerMoveC2SPacket yaw F
136+
transitive-accessible field net/minecraft/network/packet/c2s/play/PlayerMoveC2SPacket pitch F
132137

133138
# Math
134139
transitive-accessible method net/minecraft/util/math/Vec3i setX (I)Lnet/minecraft/util/math/Vec3i;

0 commit comments

Comments
 (0)