From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Thu, 3 Mar 2016 02:07:55 -0600
Subject: [PATCH] Optimize isInWorldBounds and getBlockState for inlining

Hot methods, so reduce # of instructions for the method.

Move is valid location test to the BlockPosition class so that it can access local variables.

Replace all calls to the new place to the unnecessary forward.

Optimize getType and getBlockData to manually inline and optimize the calls

diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java
index dba7872cf337a5c3dc5a6fe508dd50b93462fae5..75aa5df03c162fa10046fbad806b81051fb5765b 100644
--- a/src/main/java/net/minecraft/core/Vec3i.java
+++ b/src/main/java/net/minecraft/core/Vec3i.java
@@ -33,6 +33,12 @@ public class Vec3i implements Comparable<Vec3i> {
         return CODEC.flatXmap(checkOffsetAxes(maxAbsValue), checkOffsetAxes(maxAbsValue));
     }
 
+    // Paper start
+    public final boolean isInsideBuildHeightAndWorldBoundsHorizontal(net.minecraft.world.level.LevelHeightAccessor levelHeightAccessor) {
+        return getX() >= -30000000 && getZ() >= -30000000 && getX() < 30000000 && getZ() < 30000000 && !levelHeightAccessor.isOutsideBuildHeight(getY());
+    }
+    // Paper end
+
     public Vec3i(int x, int y, int z) {
         this.x = x;
         this.y = y;
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index c2fe955b23383effca7a8d712a08e346d648d2a8..85d3ece733d78897f85a7a02d323fdb025193622 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -262,7 +262,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
     }
 
     public boolean isInWorldBounds(BlockPos pos) {
-        return !this.isOutsideBuildHeight(pos) && Level.isInWorldBoundsHorizontal(pos);
+        return pos.isInsideBuildHeightAndWorldBoundsHorizontal(this); // Paper - use better/optimized check
     }
 
     public static boolean isInSpawnableBounds(BlockPos pos) {
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
index 0ea0690ab1d45f60a2b13cf8a69e580256992cdc..b3b3fa7ece66e1ab467c8ed550d150db541fd02a 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
@@ -119,6 +119,7 @@ public abstract class ChunkAccess implements BlockGetter, BiomeManager.NoiseBiom
         return GameEventDispatcher.NOOP;
     }
 
+    public abstract BlockState getBlockState(final int x, final int y, final int z); // Paper
     @Nullable
     public abstract BlockState setBlockState(BlockPos pos, BlockState state, boolean moved);
 
diff --git a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java
index 31d01f8df394e718f1f2a268ddccee77b6706eb9..7b0da3956be23e974d3bc2f50f9004046923635f 100644
--- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java
@@ -18,6 +18,12 @@ public class EmptyLevelChunk extends LevelChunk {
         super(world, pos);
     }
 
+    // Paper start
+    @Override
+    public BlockState getBlockState(int x, int y, int z) {
+        return Blocks.VOID_AIR.defaultBlockState();
+    }
+    // Paper end
     @Override
     public BlockState getBlockState(BlockPos pos) {
         return Blocks.VOID_AIR.defaultBlockState();
diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
index ef74f37cae96e61d5648fce7bbd793fb67ba9e4a..e15263a152c88371ebc65b47f0be938f7c19a8f2 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
@@ -46,6 +46,12 @@ public class ImposterProtoChunk extends ProtoChunk {
     public BlockState getBlockState(BlockPos pos) {
         return this.wrapped.getBlockState(pos);
     }
+    // Paper start
+    @Override
+    public final BlockState getBlockState(final int x, final int y, final int z) {
+        return this.wrapped.getBlockStateFinal(x, y, z);
+    }
+    // Paper end
 
     @Override
     public FluidState getFluidState(BlockPos pos) {
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
index 3ba9f8d7dc12709670dcd94df5d82b8d44f983fa..cbffb4eb93ba1888666d4b0de98b2fb05c1400a0 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -288,12 +288,29 @@ public class LevelChunk extends ChunkAccess {
         });
     }
 
+    // Paper start - Optimize getBlockData to reduce instructions
     @Override
     public BlockState getBlockState(BlockPos pos) {
-        int i = pos.getX();
-        int j = pos.getY();
-        int k = pos.getZ();
+        return this.getBlockStateFinal(pos.getX(), pos.getY(), pos.getZ());
+    }
+
+    @Override
+    public BlockState getBlockState(final int x, final int y, final int z) {
+        return this.getBlockStateFinal(x, y, z);
+    }
+    public final BlockState getBlockStateFinal(final int x, final int y, final int z) {
+        // Method body / logic copied from below
+        final int i = this.getSectionIndex(y);
+        if (i < 0 || i >= this.sections.length || this.sections[i].nonEmptyBlockCount == 0 || this.sections[i].hasOnlyAir()) {
+            return Blocks.AIR.defaultBlockState();
+        }
+        // Inlined ChunkSection.getType() and DataPaletteBlock.a(int,int,int)
+        return this.sections[i].states.get((y & 15) << 8 | (z & 15) << 4 | x & 15);
 
+    }
+
+    public BlockState getBlockState_unused(int i, int j, int k) {
+        // Paper end
         if (this.level.isDebug()) {
             BlockState iblockdata = null;
 
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
index 6abd3cf0a388b158252628d8031b92bb8a6d65fb..50b6ecfea7a342be0d21e37ae87777a4b4860026 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
@@ -20,7 +20,7 @@ public class LevelChunkSection {
     public static final int SECTION_SIZE = 4096;
     public static final int BIOME_CONTAINER_BITS = 2;
     private final int bottomBlockY;
-    private short nonEmptyBlockCount;
+    short nonEmptyBlockCount; // Paper - package-private
     private short tickingBlockCount;
     private short tickingFluidCount;
     public final PalettedContainer<BlockState> states;
diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
index 7c2e3331fac1de2e20974c8eed8aeeb9f2c92789..acfd46c7035b4009d61bda8a7c8dd6953e4836e6 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
@@ -87,14 +87,18 @@ public class ProtoChunk extends ChunkAccess {
 
     @Override
     public BlockState getBlockState(BlockPos pos) {
-        int i = pos.getY();
-        if (this.isOutsideBuildHeight(i)) {
+        // Paper start
+        return getBlockState(pos.getX(), pos.getY(), pos.getZ());
+    }
+    public BlockState getBlockState(final int x, final int y, final int z) {
+        if (this.isOutsideBuildHeight(y)) {
             return Blocks.VOID_AIR.defaultBlockState();
         } else {
-            LevelChunkSection levelChunkSection = this.getSection(this.getSectionIndex(i));
-            return levelChunkSection.hasOnlyAir() ? Blocks.AIR.defaultBlockState() : levelChunkSection.getBlockState(pos.getX() & 15, i & 15, pos.getZ() & 15);
+            LevelChunkSection levelChunkSection = this.getSections()[this.getSectionIndex(y)];
+            return levelChunkSection.hasOnlyAir() ? Blocks.AIR.defaultBlockState() : levelChunkSection.getBlockState(x & 15, y & 15, z & 15);
         }
     }
+    // Paper end
 
     @Override
     public FluidState getFluidState(BlockPos pos) {
