From 46c2fbfb74af896176f9ae7b61b9cb3e58e642c9 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Mon, 27 Apr 2020 00:04:16 -0700
Subject: [PATCH] Reduce allocation of Vec3D by entity tracker

---
 .../protocol/game/VecDeltaCodec.java.patch    |  7 +++++-
 .../server/level/ChunkMap.java.patch          | 21 ++++++++++------
 .../server/level/ServerEntity.java.patch      | 25 +++++++++++++++----
 3 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/paper-server/patches/sources/net/minecraft/network/protocol/game/VecDeltaCodec.java.patch b/paper-server/patches/sources/net/minecraft/network/protocol/game/VecDeltaCodec.java.patch
index 4f21ea170d..ca1a2126c9 100644
--- a/paper-server/patches/sources/net/minecraft/network/protocol/game/VecDeltaCodec.java.patch
+++ b/paper-server/patches/sources/net/minecraft/network/protocol/game/VecDeltaCodec.java.patch
@@ -1,6 +1,11 @@
 --- a/net/minecraft/network/protocol/game/VecDeltaCodec.java
 +++ b/net/minecraft/network/protocol/game/VecDeltaCodec.java
-@@ -9,12 +9,12 @@
+@@ -5,16 +5,16 @@
+ 
+ public class VecDeltaCodec {
+     private static final double TRUNCATION_STEPS = 4096.0;
+-    private Vec3 base = Vec3.ZERO;
++    public Vec3 base = Vec3.ZERO; // Paper
  
      @VisibleForTesting
      static long encode(double value) {
diff --git a/paper-server/patches/sources/net/minecraft/server/level/ChunkMap.java.patch b/paper-server/patches/sources/net/minecraft/server/level/ChunkMap.java.patch
index e5a756b76a..9a5c5895b8 100644
--- a/paper-server/patches/sources/net/minecraft/server/level/ChunkMap.java.patch
+++ b/paper-server/patches/sources/net/minecraft/server/level/ChunkMap.java.patch
@@ -11,11 +11,10 @@
  public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider, GeneratingChunkMap {
  
      private static final ChunkResult<List<ChunkAccess>> UNLOADED_CHUNK_LIST_RESULT = ChunkResult.error("Unloaded chunks found in range");
-@@ -148,7 +152,34 @@
-     private final AtomicInteger activeChunkWrites;
+@@ -149,6 +153,33 @@
      public int serverViewDistance;
      private final WorldGenContext worldGenContext;
-+
+ 
 +    // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback()
 +    public final CallbackExecutor callbackExecutor = new CallbackExecutor();
 +    public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable {
@@ -36,7 +35,7 @@
 +        }
 +    };
 +    // CraftBukkit end
- 
++
 +    // Paper start
 +    public final ChunkHolder getUnloadingChunkHolder(int chunkX, int chunkZ) {
 +        return this.pendingUnloads.get(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(chunkX, chunkZ));
@@ -379,16 +378,22 @@
              if (this.seenBy.remove(player.connection)) {
                  this.serverEntity.removePairing(player);
              }
-@@ -1476,17 +1564,37 @@
+@@ -1476,17 +1564,41 @@
          }
  
          public void updatePlayer(ServerPlayer player) {
 +            org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot
              if (player != this.entity) {
-                 Vec3 vec3d = player.position().subtract(this.entity.position());
+-                Vec3 vec3d = player.position().subtract(this.entity.position());
++                // Paper start - remove allocation of Vec3D here
++                // Vec3 vec3d = player.position().subtract(this.entity.position());
++                double vec3d_dx = player.getX() - this.entity.getX();
++                double vec3d_dz = player.getZ() - this.entity.getZ();
++                // Paper end - remove allocation of Vec3D here
                  int i = ChunkMap.this.getPlayerViewDistance(player);
                  double d0 = (double) Math.min(this.getEffectiveRange(), i * 16);
-                 double d1 = vec3d.x * vec3d.x + vec3d.z * vec3d.z;
+-                double d1 = vec3d.x * vec3d.x + vec3d.z * vec3d.z;
++                double d1 = vec3d_dx * vec3d_dx + vec3d_dz * vec3d_dz; // Paper
                  double d2 = d0 * d0;
 -                boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z);
 +                // Paper start - Configurable entity tracking range by Y
@@ -418,7 +423,7 @@
                      }
                  } else if (this.seenBy.remove(player.connection)) {
                      this.serverEntity.removePairing(player);
-@@ -1506,6 +1614,7 @@
+@@ -1506,6 +1618,7 @@
              while (iterator.hasNext()) {
                  Entity entity = (Entity) iterator.next();
                  int j = entity.getType().clientTrackingRange() * 16;
diff --git a/paper-server/patches/sources/net/minecraft/server/level/ServerEntity.java.patch b/paper-server/patches/sources/net/minecraft/server/level/ServerEntity.java.patch
index fe02477162..13eeb27d07 100644
--- a/paper-server/patches/sources/net/minecraft/server/level/ServerEntity.java.patch
+++ b/paper-server/patches/sources/net/minecraft/server/level/ServerEntity.java.patch
@@ -86,7 +86,22 @@
  
                              worldmap.tickCarriedBy(entityplayer, itemstack);
                              Packet<?> packet = worldmap.getUpdatePacket(mapid, entityplayer);
-@@ -248,6 +258,27 @@
+@@ -168,7 +178,13 @@
+ 
+                     ++this.teleportDelay;
+                     Vec3 vec3d = this.entity.trackingPosition();
+-                    boolean flag1 = this.positionCodec.delta(vec3d).lengthSqr() >= 7.62939453125E-6D;
++                    // Paper start - reduce allocation of Vec3D here
++                    Vec3 base = this.positionCodec.base;
++                    double vec3d_dx = vec3d.x - base.x;
++                    double vec3d_dy = vec3d.y - base.y;
++                    double vec3d_dz = vec3d.z - base.z;
++                    boolean flag1 = (vec3d_dx * vec3d_dx + vec3d_dy * vec3d_dy + vec3d_dz * vec3d_dz) >= 7.62939453125E-6D;
++                    // Paper end - reduce allocation of Vec3D here
+                     Packet<?> packet1 = null;
+                     boolean flag2 = flag1 || this.tickCount % 60 == 0;
+                     boolean flag3 = false;
+@@ -248,6 +264,27 @@
  
          ++this.tickCount;
          if (this.entity.hurtMarked) {
@@ -114,7 +129,7 @@
              this.entity.hurtMarked = false;
              this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity));
          }
-@@ -298,7 +329,10 @@
+@@ -298,7 +335,10 @@
  
      public void sendPairingData(ServerPlayer player, Consumer<Packet<ClientGamePacketListener>> sender) {
          if (this.entity.isRemoved()) {
@@ -126,7 +141,7 @@
          }
  
          Packet<ClientGamePacketListener> packet = this.entity.getAddEntityPacket(this);
-@@ -313,6 +347,12 @@
+@@ -313,6 +353,12 @@
          if (this.entity instanceof LivingEntity) {
              Collection<AttributeInstance> collection = ((LivingEntity) this.entity).getAttributes().getSyncableAttributes();
  
@@ -139,7 +154,7 @@
              if (!collection.isEmpty()) {
                  sender.accept(new ClientboundUpdateAttributesPacket(this.entity.getId(), collection));
              }
-@@ -344,6 +384,7 @@
+@@ -344,6 +390,7 @@
              if (!list.isEmpty()) {
                  sender.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), list));
              }
@@ -147,7 +162,7 @@
          }
  
          if (!this.entity.getPassengers().isEmpty()) {
-@@ -396,6 +437,11 @@
+@@ -396,6 +443,11 @@
              Set<AttributeInstance> set = ((LivingEntity) this.entity).getAttributes().getAttributesToSync();
  
              if (!set.isEmpty()) {