From 88092fef13d45c7178d597818a74130ac380c135 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Thu, 16 Apr 2020 20:47:15 -0700
Subject: [PATCH] Optimize ChunkProviderServer's chunk level checking helper
 methods

These can be hot functions (i.e entity ticking and block ticking),
so inline where possible, and avoid the abstraction of the
Either class.
---
 ...72-Reduce-Either-Optional-allocation.patch | 30 ++++-----
 ...oviderServer-s-chunk-level-checking-.patch | 65 +++++++++++++++++++
 2 files changed, 76 insertions(+), 19 deletions(-)
 create mode 100644 Spigot-Server-Patches/0480-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch

diff --git a/Spigot-Server-Patches/0472-Reduce-Either-Optional-allocation.patch b/Spigot-Server-Patches/0472-Reduce-Either-Optional-allocation.patch
index b6c6837ec1..78fe328c7c 100644
--- a/Spigot-Server-Patches/0472-Reduce-Either-Optional-allocation.patch
+++ b/Spigot-Server-Patches/0472-Reduce-Either-Optional-allocation.patch
@@ -1,4 +1,4 @@
-From f05a44606eb3f3467c092da8ade51d8de1220561 Mon Sep 17 00:00:00 2001
+From 4e4969fe0412b6f2a2989a35215096c24266180a Mon Sep 17 00:00:00 2001
 From: Spottedleaf <spottedleaf@spottedleaf.dev>
 Date: Mon, 6 Apr 2020 18:35:09 -0700
 Subject: [PATCH] Reduce Either Optional allocation
@@ -7,53 +7,45 @@ In order to get chunk values, we shouldn't need to create
 an optional each time.
 
 diff --git a/src/main/java/com/mojang/datafixers/util/Either.java b/src/main/java/com/mojang/datafixers/util/Either.java
-index a90adac7b..4bb621d57 100644
+index a90adac7b..3f65fe710 100644
 --- a/src/main/java/com/mojang/datafixers/util/Either.java
 +++ b/src/main/java/com/mojang/datafixers/util/Either.java
-@@ -22,10 +22,10 @@ public abstract class Either<L, R> implements App<Either.Mu<R>, L> {
+@@ -22,7 +22,7 @@ public abstract class Either<L, R> implements App<Either.Mu<R>, L> {
      }
  
      private static final class Left<L, R> extends Either<L, R> {
 -        private final L value;
-+        private final L value; private final Optional<L> valueOptional; // Paper - reduce the optional allocation...
++        private final L value; private Optional<L> valueOptional; // Paper - reduce the optional allocation...
  
          public Left(final L value) {
--            this.value = value;
-+            this.value = value; this.valueOptional = value != null ? Optional.of(value) : Optional.empty();  // Paper - reduce the optional allocation...
-         }
- 
-         @Override
+             this.value = value;
 @@ -51,7 +51,7 @@ public abstract class Either<L, R> implements App<Either.Mu<R>, L> {
  
          @Override
          public Optional<L> left() {
 -            return Optional.of(value);
-+            return this.valueOptional; // Paper - reduce the optional allocation...
++            return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - reduce the optional allocation...
          }
  
          @Override
-@@ -83,10 +83,10 @@ public abstract class Either<L, R> implements App<Either.Mu<R>, L> {
+@@ -83,7 +83,7 @@ public abstract class Either<L, R> implements App<Either.Mu<R>, L> {
      }
  
      private static final class Right<L, R> extends Either<L, R> {
 -        private final R value;
-+        private final R value; private final Optional<R> valueOptional; // Paper - reduce the optional allocation...
++        private final R value; private Optional<R> valueOptional; // Paper - reduce the optional allocation...
  
          public Right(final R value) {
--            this.value = value;
-+            this.value = value; this.valueOptional = value != null ? Optional.of(value) : Optional.empty(); // Paper - reduce the optional allocation...
-         }
- 
-         @Override
+             this.value = value;
 @@ -117,7 +117,7 @@ public abstract class Either<L, R> implements App<Either.Mu<R>, L> {
  
          @Override
          public Optional<R> right() {
 -            return Optional.of(value);
-+            return this.valueOptional; // Paper - reduce the optional allocation...
++            return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - reduce the optional allocation...
          }
  
          @Override
 -- 
-2.25.1
+2.26.0
 
diff --git a/Spigot-Server-Patches/0480-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch b/Spigot-Server-Patches/0480-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch
new file mode 100644
index 0000000000..c62cd7131c
--- /dev/null
+++ b/Spigot-Server-Patches/0480-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch
@@ -0,0 +1,65 @@
+From 9f57d53bd92a3c87603dc929b6490a8501a18c0d Mon Sep 17 00:00:00 2001
+From: Spottedleaf <Spottedleaf@users.noreply.github.com>
+Date: Thu, 16 Apr 2020 16:13:59 -0700
+Subject: [PATCH] Optimize ChunkProviderServer's chunk level checking helper
+ methods
+
+These can be hot functions (i.e entity ticking and block ticking),
+so inline where possible, and avoid the abstraction of the
+Either class.
+
+diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
+index f741a034e..664a244dd 100644
+--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
++++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
+@@ -534,27 +534,37 @@ public class ChunkProviderServer extends IChunkProvider {
+ 
+     public final boolean isInEntityTickingChunk(Entity entity) { return this.a(entity); } // Paper - OBFHELPER
+     @Override public boolean a(Entity entity) {
+-        long i = ChunkCoordIntPair.pair(MathHelper.floor(entity.locX()) >> 4, MathHelper.floor(entity.locZ()) >> 4);
+-
+-        return this.a(i, PlayerChunk::b);
++        // Paper start - optimize is ticking ready type functions
++        // entity ticking
++        PlayerChunk playerChunk = this.getChunk(MCUtil.getCoordinateKey(entity));
++        return playerChunk != null && playerChunk.isEntityTickingReady();
++        // Paper end - optimize is ticking ready type functions
+     }
+ 
+     public final boolean isEntityTickingChunk(ChunkCoordIntPair chunkcoordintpair) { return this.a(chunkcoordintpair); } // Paper - OBFHELPER
+     @Override public boolean a(ChunkCoordIntPair chunkcoordintpair) {
+-        return this.a(chunkcoordintpair.pair(), PlayerChunk::b);
++        // Paper start - optimize is ticking ready type functions
++        // is entity ticking ready
++        PlayerChunk playerChunk = this.getChunk(MCUtil.getCoordinateKey(chunkcoordintpair));
++        return playerChunk != null && playerChunk.isEntityTickingReady();
++        // Paper end - optimize is ticking ready type functions
+     }
+ 
+     @Override
+     public boolean a(BlockPosition blockposition) {
+-        long i = ChunkCoordIntPair.pair(blockposition.getX() >> 4, blockposition.getZ() >> 4);
+-
+-        return this.a(i, PlayerChunk::a);
++        // Paper start - optimize is ticking ready type functions
++        // is ticking ready
++        PlayerChunk playerChunk = this.getChunk(MCUtil.getCoordinateKey(blockposition));
++        return playerChunk != null && playerChunk.isTickingReady();
++        // Paper end - optimize is ticking ready type functions
+     }
+ 
+     public boolean b(Entity entity) {
+-        long i = ChunkCoordIntPair.pair(MathHelper.floor(entity.locX()) >> 4, MathHelper.floor(entity.locZ()) >> 4);
+-
+-        return this.a(i, PlayerChunk::c);
++        // Paper start - optimize is ticking ready type functions
++        // is full chunk ready
++        PlayerChunk playerChunk = this.getChunk(MCUtil.getCoordinateKey(entity));
++        return playerChunk != null && playerChunk.isFullChunkReady();
++        // Paper end - optimize is ticking ready type functions
+     }
+ 
+     private boolean a(long i, Function<PlayerChunk, CompletableFuture<Either<Chunk, PlayerChunk.Failure>>> function) {
+-- 
+2.26.0
+