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 65095b7d91fb4549ef67593054c54ca81b77debe..50df43653933e3bdeb3fd514a1c6c3b9ac3b15ab 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.a; @@ -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 d98b6ef44e1836920956754dfcb6654fec23b673..b40f6b7d45028b5bc58a222e2d54cb8693273325 100644 --- a/src/main/java/net/minecraft/server/PlayerChunkMap.java +++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java @@ -1249,10 +1249,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); @@ -1334,7 +1338,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)) {