@Inject( method = "processPlayer", at = @At( value = "FIELD", target = "net.minecraft.network.NetHandlerPlayServer.hasMoved:Z", ordinal = 2), cancellable = true) public void proccesPlayerMoved(C03PacketPlayer packetIn, CallbackInfo ci) { if (packetIn.isMoving() || packetIn.getRotating() && !this.playerEntity.isDead) { Player player = (Player) this.playerEntity; Vector3d fromrot = player.getRotation(); // If Sponge used the player's current location, the delta might never be triggered which // could be exploited Location from = player.getLocation(); if (this.lastMoveLocation != null) { from = this.lastMoveLocation; } Vector3d torot = new Vector3d(packetIn.getPitch(), packetIn.getYaw(), 0); Location to = new Location( player.getWorld(), packetIn.getPositionX(), packetIn.getPositionY(), packetIn.getPositionZ()); // Minecraft sends a 0, 0, 0 position when rotation only update occurs, this needs to be // recognized and corrected boolean rotationOnly = !packetIn.isMoving() && packetIn.getRotating(); if (rotationOnly) { // Correct the to location so it's not misrepresented to plugins, only when player rotates // without moving // In this case it's only a rotation update, which isn't related to the to location from = player.getLocation(); to = from; } // Minecraft does the same with rotation when it's only a positional update boolean positionOnly = packetIn.isMoving() && !packetIn.getRotating(); if (positionOnly) { // Correct the new rotation to match the old rotation torot = fromrot; } double deltaSquared = to.getPosition().distanceSquared(from.getPosition()); double deltaAngleSquared = fromrot.distanceSquared(torot); // These magic numbers are sad but help prevent excessive lag from this event. // eventually it would be nice to not have them if (deltaSquared > ((1f / 16) * (1f / 16)) || deltaAngleSquared > (.15f * .15f)) { PlayerMoveEvent event = SpongeEventFactory.createPlayerMove(Sponge.getGame(), player, from, to, torot); Sponge.getGame().getEventManager().post(event); if (event.isCancelled()) { player.setLocationAndRotation(from, fromrot); this.lastMoveLocation = from; ci.cancel(); } else if (!event.getNewLocation().equals(to)) { player.setLocationAndRotation(event.getNewLocation(), event.getRotation()); this.lastMoveLocation = event.getNewLocation(); ci.cancel(); } else if (!from.equals(player.getLocation()) && this.justTeleported) { this.lastMoveLocation = player.getLocation(); // Prevent teleports during the move event from causing odd behaviors this.justTeleported = false; ci.cancel(); } else { this.lastMoveLocation = event.getNewLocation(); } } } }