package net.glowstone.net.handler.play.player;

import com.flowpowered.networking.MessageHandler;
import net.glowstone.EventFactory;
import net.glowstone.entity.GlowPlayer;
import net.glowstone.net.GlowSession;
import net.glowstone.net.message.play.game.PositionRotationMessage;
import net.glowstone.net.message.play.player.PlayerUpdateMessage;
import org.bukkit.Location;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerTeleportEvent;

public final class PlayerUpdateHandler implements MessageHandler<GlowSession, PlayerUpdateMessage> {

    @Override
    public void handle(GlowSession session, PlayerUpdateMessage message) {

        GlowPlayer player = session.getPlayer();

        Location oldLocation = player.getLocation();
        Location newLocation = oldLocation.clone();
        message.update(newLocation);

        // don't let players move more than 16 blocks in a single packet.
        // this is NOT robust hack prevention - only to prevent client
        // confusion about where its actual location is (e.g. during login)
        if (newLocation.distanceSquared(oldLocation) > 16 * 16) {
            return;
        }


        // call move event if movement actually occurred and there are handlers registered
        if (!oldLocation.equals(newLocation) && PlayerMoveEvent.getHandlerList().getRegisteredListeners().length > 0) {
            final PlayerMoveEvent event = EventFactory.callEvent(new PlayerMoveEvent(player, oldLocation, newLocation));
            if (event.isCancelled()) {
                // tell client they're back where they started
                session.send(new PositionRotationMessage(oldLocation));
                return;
            }

            if (!event.getTo().equals(newLocation)) {
                // teleport to the set destination: fires PlayerTeleportEvent and
                // handles if the destination is in another world
                player.teleport(event.getTo(), PlayerTeleportEvent.TeleportCause.PLUGIN);
                return;
            }
        }

        // do stuff with onGround if we need to
        if (player.isOnGround() != message.isOnGround()) {
            player.setOnGround(message.isOnGround());
        }

        player.addMoveExhaustion(newLocation);

        // move event was not fired or did nothing, simply update location
        player.setRawLocation(newLocation);
    }
}

@@ -126,16 +126,49 @@
 actory;%0A
+import net.glowstone.GlowServer;%0A
 import n
@@ -500,16 +500,43 @@
 Event;%0A%0A
+import java.util.Objects;%0A%0A
 public f
@@ -922,16 +922,284 @@
       //
+ don't let players reach an illegal position%0A        if (Math.abs(newLocation.getBlockX()) %3E 32000000 %7C%7C Math.abs(newLocation.getBlockZ()) %3E 32000000) %7B%0A            session.getPlayer().kickPlayer(%22Illegal position%22);%0A            return;%0A        %7D%0A%0A        /*%0A         
  don't l
@@ -1225,17 +1225,18 @@
 e than 1
-6
+00
  blocks 
@@ -1253,17 +1253,16 @@
 e packet
-.
 %0A       
@@ -1262,18 +1262,93 @@
         
-//
+  if they move greater than 10 blocks, but less than 100, just warn%0A         
  this is
@@ -1408,18 +1408,17 @@
         
-//
+ 
  confusi
@@ -1475,16 +1475,27 @@
  login)%0A
+        */%0A
         
@@ -1546,14 +1546,16 @@
  %3E 1
-6
+00
  * 1
-6
+00
 ) %7B%0A
@@ -1558,38 +1558,388 @@
 ) %7B%0A            
-return
+GlowServer.logger.warning(session.getPlayer().getName() + %22 moved too quickly! (hacking)%22);%0A            session.getPlayer().kickPlayer(%22You moved too quickly :( (Hacking?)%22);%0A            return;%0A        %7D else if (newLocation.distanceSquared(oldLocation) %3E 100) %7B%0A            GlowServer.logger.warning(session.getPlayer().getName() + %22 moved too quickly!%22)
 ;%0A        %7D%0A%0A%0A  
@@ -2810,16 +2810,195 @@
        %7D
+%0A%0A            if (!Objects.equals(session.getPlayer().getLocation(), oldLocation)) %7B%0A                // plugin changed location on move event%0A                return;%0A            %7D
 %0A       

Fix some movement issues