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/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java index 59a5f82c9f57d760ba4959a040ce8cbf0f49e4aa..d1bc927c8b429f43de2cdad98f8b329ff4c8b4db 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -1301,10 +1301,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider private final Entity entity; private final int range; private SectionPos lastSectionPos; - public final Set seenBy = 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 seenBy = trackedPlayerMap.keySet(); public TrackedEntity(Entity entity, int i, int j, boolean flag) { - this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, seenBy); // CraftBukkit + this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, trackedPlayerMap); // CraftBukkit // Paper this.entity = entity; this.range = i; this.lastSectionPos = SectionPos.of(entity); @@ -1386,7 +1390,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider player.entitiesToRemove.remove(Integer.valueOf(this.entity.getId())); // CraftBukkit end - if (flag1 && this.seenBy.add(player)) { + if (flag1 && this.trackedPlayerMap.putIfAbsent(player, true) == null) { // Paper this.serverEntity.addPairing(player); } } else if (this.seenBy.remove(player)) { diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java index 3d386627b6d3d33da76372e4a14d0c5000eb8ffc..fa6893055fa5617742bfb4b7eff60c8139395cb6 100644 --- a/src/main/java/net/minecraft/server/level/ServerEntity.java +++ b/src/main/java/net/minecraft/server/level/ServerEntity.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; @@ -51,7 +52,7 @@ public class ServerEntity { private final Entity entity; private final int updateInterval; private final boolean trackDelta; - private final Consumer> broadcast; + private final Consumer> broadcast; private Consumer> getPacketConsumer() { return broadcast; } // Paper - OBFHELPER private long xp; private long yp; private long zp; @@ -66,8 +67,23 @@ public class ServerEntity { private boolean wasOnGround; // 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(ServerPlayer player, Packet packet) { + player.connection.send(packet); + } + + public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer> consumer, java.util.Map trackedPlayers) { + this(worldserver, entity, i, flag, consumer, trackedPlayers.keySet()); + trackedPlayerMap = trackedPlayers; + } public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer> consumer, Set trackedPlayers) { + // Paper end this.trackedPlayers = trackedPlayers; // CraftBukkit end this.ap = Vec3.ZERO; @@ -188,7 +204,25 @@ public class ServerEntity { } if (packet1 != null) { - this.broadcast.accept(packet1); + // paper start + if (trackedPlayerMap == null || packet1 instanceof ClientboundTeleportEntityPacket) { + this.broadcast.accept((packet1)); + } else { + ClientboundTeleportEntityPacket teleportPacket = null; + + for (java.util.Map.Entry viewer : trackedPlayerMap.entrySet()) { + if (viewer.getValue()) { + viewer.setValue(false); + if (teleportPacket == null) { + teleportPacket = new ClientboundTeleportEntityPacket(this.entity); + } + sendPlayerPacket(viewer.getKey(), teleportPacket); + } else { + sendPlayerPacket(viewer.getKey(), packet1); + } + } + } + // Paper end } this.sendDirtyEntityData();