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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -0,0 +0,0 @@ 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); @@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/ServerEntity.java +++ b/src/main/java/net/minecraft/server/level/ServerEntity.java @@ -0,0 +0,0 @@ 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; @@ -0,0 +0,0 @@ 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; @@ -0,0 +0,0 @@ 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; @@ -0,0 +0,0 @@ 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();