From 601b8ccd9ffc815477f336e6c54610f478726e44 Mon Sep 17 00:00:00 2001
From: Jedediah Smith <jedediah@silencegreys.com>
Date: Fri, 3 Apr 2015 17:26:21 -0400
Subject: [PATCH] Send absolute position the first time an entity is seen


diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java
index f0149bf..1fc2388 100644
--- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java
+++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java
@@ -39,7 +39,12 @@ public class EntityTrackerEntry {
     private boolean x;
     private boolean y;
     public boolean n;
-    public Set<EntityPlayer> trackedPlayers = Sets.newHashSet();
+    // PaperSpigot start
+    // Replace trackedPlayers Set with a Map. The value is true until the player receives
+    // their first update (which is forced to have absolute coordinates), false afterward.
+    public java.util.Map<EntityPlayer, Boolean> trackedPlayerMap = new java.util.HashMap<EntityPlayer, Boolean>();
+    public Set<EntityPlayer> trackedPlayers = trackedPlayerMap.keySet();
+    // PaperSpigot end
 
     public EntityTrackerEntry(Entity entity, int i, int j, boolean flag) {
         this.tracker = entity;
@@ -121,20 +126,20 @@ public class EntityTrackerEntry {
                 boolean flag = Math.abs(j1) >= 4 || Math.abs(k1) >= 4 || Math.abs(l1) >= 4 || this.m % 60 == 0;
                 boolean flag1 = Math.abs(l - this.yRot) >= 4 || Math.abs(i1 - this.xRot) >= 4;
 
-                // CraftBukkit start - Code moved from below
-                if (flag) {
-                    this.xLoc = i;
-                    this.yLoc = j;
-                    this.zLoc = k;
-                }
+                if (this.m > 0 || this.tracker instanceof EntityArrow) { // PaperSpigot - Moved up
+                    // CraftBukkit start - Code moved from below
+                    if (flag) {
+                        this.xLoc = i;
+                        this.yLoc = j;
+                        this.zLoc = k;
+                    }
 
-                if (flag1) {
-                    this.yRot = l;
-                    this.xRot = i1;
-                }
-                // CraftBukkit end
+                    if (flag1) {
+                        this.yRot = l;
+                        this.xRot = i1;
+                    }
+                    // CraftBukkit end
 
-                if (this.m > 0 || this.tracker instanceof EntityArrow) {
                     if (j1 >= -128 && j1 < 128 && k1 >= -128 && k1 < 128 && l1 >= -128 && l1 < 128 && this.v <= 400 && !this.x && this.y == this.tracker.onGround) {
                         if ((!flag || !flag1) && !(this.tracker instanceof EntityArrow)) {
                             if (flag) {
@@ -173,7 +178,26 @@ public class EntityTrackerEntry {
                 }
 
                 if (object != null) {
-                    this.broadcast((Packet) object);
+                    // PaperSpigot start - ensure fresh viewers get an absolute position on their first update,
+                    // since we can't be certain what position they received in the spawn packet.
+                    if (object instanceof PacketPlayOutEntityTeleport) {
+                        this.broadcast((Packet) object);
+                    } else {
+                        PacketPlayOutEntityTeleport teleportPacket = null;
+
+                        for (java.util.Map.Entry<EntityPlayer, Boolean> viewer : trackedPlayerMap.entrySet()) {
+                            if (viewer.getValue()) {
+                                viewer.setValue(false);
+                                if (teleportPacket == null) {
+                                    teleportPacket = new PacketPlayOutEntityTeleport(this.tracker.getId(), i, j, k, (byte) l, (byte) i1, this.tracker.onGround);
+                                }
+                                viewer.getKey().playerConnection.sendPacket(teleportPacket);
+                            } else {
+                                viewer.getKey().playerConnection.sendPacket((Packet) object);
+                            }
+                        }
+                    }
+                    // PaperSpigot end
                 }
 
                 this.b();
@@ -324,7 +348,7 @@ public class EntityTrackerEntry {
 
                     entityplayer.removeQueue.remove(Integer.valueOf(this.tracker.getId()));
                     // CraftBukkit end
-                    this.trackedPlayers.add(entityplayer);
+                    this.trackedPlayerMap.put(entityplayer, true); // PaperBukkit
                     Packet packet = this.c();
 
                     entityplayer.playerConnection.sendPacket(packet);
-- 
2.6.4