From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Jedediah Smith Date: Wed, 2 Mar 2016 23:13:07 -0600 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 62a7db8c7d2604d248ec5c1efb3c43356c3d513c..dec48226d713ef0198ef3c679daf553a9d05a099 100644 --- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java +++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java @@ -4,6 +4,7 @@ import com.google.common.collect.Lists; import com.mojang.datafixers.util.Pair; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; @@ -23,7 +24,7 @@ public class EntityTrackerEntry { private final Entity tracker; private final int d; private final boolean e; - private final Consumer> f; + private final Consumer> f; private Consumer> getPacketConsumer() { return f; } // Paper - OBFHELPER private long xLoc; private long yLoc; private long zLoc; @@ -38,8 +39,23 @@ public class EntityTrackerEntry { private boolean r; // CraftBukkit start private final Set trackedPlayers; + // Paper start + private java.util.Map trackedPlayerMap = null; + + /** + * Requested in https://github.com/PaperMC/Paper/issues/1537 to allow intercepting packets + */ + public void sendPlayerPacket(EntityPlayer player, Packet packet) { + player.playerConnection.sendPacket(packet); + } + + public EntityTrackerEntry(WorldServer worldserver, Entity entity, int i, boolean flag, Consumer> consumer, java.util.Map trackedPlayers) { + this(worldserver, entity, i, flag, consumer, trackedPlayers.keySet()); + trackedPlayerMap = trackedPlayers; + } public EntityTrackerEntry(WorldServer worldserver, Entity entity, int i, boolean flag, Consumer> consumer, Set trackedPlayers) { + // Paper end this.trackedPlayers = trackedPlayers; // CraftBukkit end this.m = Vec3D.ORIGIN; @@ -161,7 +177,25 @@ public class EntityTrackerEntry { } if (packet1 != null) { - this.f.accept(packet1); + // paper start + if (trackedPlayerMap == null || packet1 instanceof PacketPlayOutEntityTeleport) { + this.f.accept((packet1)); + } else { + PacketPlayOutEntityTeleport teleportPacket = null; + + for (java.util.Map.Entry viewer : trackedPlayerMap.entrySet()) { + if (viewer.getValue()) { + viewer.setValue(false); + if (teleportPacket == null) { + teleportPacket = new PacketPlayOutEntityTeleport(this.tracker); + } + sendPlayerPacket(viewer.getKey(), teleportPacket); + } else { + sendPlayerPacket(viewer.getKey(), packet1); + } + } + } + // Paper end } this.c(); diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java index 5ca081e8be411aee98efce3e41876efe3bb2e327..2ba10ed683788219c734a565a163ba553ec72c75 100644 --- a/src/main/java/net/minecraft/server/PlayerChunkMap.java +++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java @@ -1250,10 +1250,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { private final Entity tracker; private final int trackingDistance; private SectionPosition e; - public final Set trackedPlayers = Sets.newHashSet(); + // Paper 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 trackedPlayerMap = new java.util.HashMap<>(); + public Set trackedPlayers = trackedPlayerMap.keySet(); public EntityTracker(Entity entity, int i, int j, boolean flag) { - this.trackerEntry = new EntityTrackerEntry(PlayerChunkMap.this.world, entity, j, flag, this::broadcast, trackedPlayers); // CraftBukkit + this.trackerEntry = new EntityTrackerEntry(PlayerChunkMap.this.world, entity, j, flag, this::broadcast, trackedPlayerMap); // CraftBukkit // Paper this.tracker = entity; this.trackingDistance = i; this.e = SectionPosition.a(entity); @@ -1335,7 +1339,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { entityplayer.removeQueue.remove(Integer.valueOf(this.tracker.getId())); // CraftBukkit end - if (flag1 && this.trackedPlayers.add(entityplayer)) { + if (flag1 && this.trackedPlayerMap.putIfAbsent(entityplayer, true) == null) { // Paper this.trackerEntry.b(entityplayer); } } else if (this.trackedPlayers.remove(entityplayer)) {