8888import org .spongepowered .asm .mixin .injection .At ;
8989import org .spongepowered .asm .mixin .injection .Inject ;
9090import org .spongepowered .asm .mixin .injection .Redirect ;
91+ import org .spongepowered .asm .mixin .injection .Slice ;
9192import org .spongepowered .asm .mixin .injection .callback .CallbackInfo ;
9293import org .spongepowered .common .SpongeCommon ;
94+ import org .spongepowered .common .accessor .network .protocol .game .ServerboundMovePlayerPacketAccessor ;
9395import org .spongepowered .common .accessor .network .protocol .game .ServerboundMoveVehiclePacketAccessor ;
9496import org .spongepowered .common .accessor .server .level .ServerPlayerGameModeAccessor ;
9597import org .spongepowered .common .adventure .SpongeAdventure ;
@@ -197,9 +199,11 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack
197199 }
198200
199201 @ Inject (method = "handleMovePlayer" ,
200- at = @ At (value = "INVOKE" , target = "Lnet/minecraft/server/level/ServerPlayer;isPassenger()Z" ),
201- cancellable = true
202- )
202+ at = @ At (value = "INVOKE" , target = "Lnet/minecraft/network/protocol/game/ServerboundMovePlayerPacket;getYRot(F)F" ),
203+ cancellable = true ,
204+ slice = @ Slice (
205+ from = @ At (value = "INVOKE" , target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;updateAwaitingTeleport()Z" ),
206+ to = @ At (value = "INVOKE" , target = "Lnet/minecraft/server/level/ServerPlayer;isPassenger()Z" )))
203207 private void impl$callMoveEntityEvent (final ServerboundMovePlayerPacket packetIn , final CallbackInfo ci ) {
204208 final boolean fireMoveEvent = packetIn .hasPosition ();
205209 final boolean fireRotationEvent = packetIn .hasRotation ();
@@ -266,7 +270,7 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack
266270 }
267271
268272 // Handle event results
269- if (!toPosition .equals (originalToPosition ) || ! toRotation . equals ( originalToRotation ) ) {
273+ if (!toPosition .equals (originalToPosition )) {
270274 // Notify the client about the new position and new rotation.
271275 // Both are relatives so the client will keep its momentum.
272276 // The client thinks its current position is originalToPosition so the new position is relative to that.
@@ -278,6 +282,20 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack
278282 (float ) toRotation .y (), (float ) toRotation .x (),
279283 EnumSet .allOf (RelativeMovement .class ));
280284 ci .cancel ();
285+ } else if (!toRotation .equals (originalToRotation )) {
286+ // Notify the client about the new rotation.
287+ // Both are relatives so the client will keep its momentum.
288+ // The rotation values can be out of "valid" range so set them directly to the same value the client has.
289+ this .player .setXRot ((float ) originalToRotation .x ());
290+ this .player .setYRot ((float ) originalToRotation .y ());
291+ this .shadow$teleport (fromPosition .x (), fromPosition .y (), fromPosition .z (),
292+ (float ) toRotation .y (), (float ) toRotation .x (),
293+ EnumSet .allOf (RelativeMovement .class ));
294+
295+ // Let MC handle the movement but override the rotation.
296+ ((ServerboundMovePlayerPacketAccessor ) packetIn ).accessor$yRot ((float ) toRotation .y ());
297+ ((ServerboundMovePlayerPacketAccessor ) packetIn ).accessor$xRot ((float ) toRotation .x ());
298+ ((ServerboundMovePlayerPacketAccessor ) packetIn ).accessor$hasRot (true );
281299 }
282300 }
283301
0 commit comments