diff --git a/patches/server/Add-World-Util-Methods.patch b/patches/server/Add-World-Util-Methods.patch
index 29ee91d6e1..d32d1351cd 100644
--- a/patches/server/Add-World-Util-Methods.patch
+++ b/patches/server/Add-World-Util-Methods.patch
@@ -23,31 +23,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/level/Level.java
 +++ b/src/main/java/net/minecraft/world/level/Level.java
 @@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
-     }
- 
-     @Override
--    public FluidState getFluidIfLoaded(BlockPos blockposition) {
-+    public final FluidState getFluidIfLoaded(BlockPos blockposition) {
-         ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4);
- 
          return chunk == null ? null : chunk.getFluidState(blockposition);
      }
-+
+ 
 +    public final boolean isLoadedAndInBounds(BlockPos blockposition) { // Paper - final for inline
 +        return getWorldBorder().isWithinBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null;
 +    }
 +
-+    public LevelChunk getChunkIfLoaded(int x, int z) { // Overridden in WorldServer for ABI compat which has final
++    public @Nullable LevelChunk getChunkIfLoaded(int x, int z) { // Overridden in WorldServer for ABI compat which has final
 +        return ((ServerLevel) this).getChunkSource().getChunkAtIfLoadedImmediately(x, z);
 +    }
-+    public final LevelChunk getChunkIfLoaded(BlockPos blockposition) {
++    public final @Nullable LevelChunk getChunkIfLoaded(BlockPos blockposition) {
 +        return ((ServerLevel) this).getChunkSource().getChunkAtIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4);
 +    }
 +
 +    //  reduces need to do isLoaded before getType
-+    public final BlockState getTypeIfLoadedAndInBounds(BlockPos blockposition) {
-+        return getWorldBorder().isWithinBounds(blockposition) ? getTypeIfLoaded(blockposition) : null;
++    public final @Nullable BlockState getBlockStateIfLoadedAndInBounds(BlockPos blockposition) {
++        return getWorldBorder().isWithinBounds(blockposition) ? getBlockStateIfLoaded(blockposition) : null;
 +    }
-     // Paper end
- 
++
      @Override
+     public final ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { // Paper - final for inline
+         // Paper end
diff --git a/patches/server/Anti-Xray.patch b/patches/server/Anti-Xray.patch
index ac6f3902d7..f934762586 100644
--- a/patches/server/Anti-Xray.patch
+++ b/patches/server/Anti-Xray.patch
@@ -882,7 +882,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +
 +    private void updateBlock(Level level, BlockPos blockPos) {
-+        BlockState blockState = level.getTypeIfLoaded(blockPos);
++        BlockState blockState = level.getBlockStateIfLoaded(blockPos);
 +
 +        if (blockState != null && obfuscateGlobal[GLOBAL_BLOCKSTATE_PALETTE.idFor(blockState)]) {
 +            ((ServerLevel) level).getChunkSource().blockChanged(blockPos);
diff --git a/patches/server/Do-not-load-chunks-for-Pathfinding.patch b/patches/server/Do-not-load-chunks-for-Pathfinding.patch
index 40acfa111b..633f6dcd76 100644
--- a/patches/server/Do-not-load-chunks-for-Pathfinding.patch
+++ b/patches/server/Do-not-load-chunks-for-Pathfinding.patch
@@ -14,7 +14,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                          pos.set(i + l, j + m, k + n);
 -                        BlockState blockState = world.getBlockState(pos);
 +                        // Paper start
-+                        BlockState blockState = world.getTypeIfLoaded(pos);
++                        BlockState blockState = world.getBlockStateIfLoaded(pos);
 +                        if (blockState == null) {
 +                            return BlockPathTypes.BLOCKED;
 +                        } else {
@@ -35,7 +35,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
      protected static BlockPathTypes getBlockPathTypeRaw(BlockGetter world, BlockPos pos) {
 -        BlockState blockState = world.getBlockState(pos);
-+        BlockState blockState = world.getTypeIfLoaded(pos); // Paper
++        BlockState blockState = world.getBlockStateIfLoaded(pos); // Paper
 +        if (blockState == null) return BlockPathTypes.BLOCKED; // Paper
          Block block = blockState.getBlock();
          Material material = blockState.getMaterial();
diff --git a/patches/server/Don-t-allow-digging-into-unloaded-chunks.patch b/patches/server/Don-t-allow-digging-into-unloaded-chunks.patch
index a19aadc74b..b7eacd8cfd 100644
--- a/patches/server/Don-t-allow-digging-into-unloaded-chunks.patch
+++ b/patches/server/Don-t-allow-digging-into-unloaded-chunks.patch
@@ -14,7 +14,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          if (this.hasDelayedDestroy) {
 -            iblockdata = this.level.getBlockState(this.delayedDestroyPos);
 -            if (iblockdata.isAir()) {
-+            iblockdata = this.level.getTypeIfLoaded(this.delayedDestroyPos); // Paper
++            iblockdata = this.level.getBlockStateIfLoaded(this.delayedDestroyPos); // Paper
 +            if (iblockdata == null || iblockdata.isAir()) { // Paper
                  this.hasDelayedDestroy = false;
              } else {
@@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          } else if (this.isDestroyingBlock) {
 -            iblockdata = this.level.getBlockState(this.destroyPos);
 +            // Paper start - don't want to do same logic as above, return instead
-+            iblockdata = this.level.getTypeIfLoaded(this.destroyPos);
++            iblockdata = this.level.getBlockStateIfLoaded(this.destroyPos);
 +            if (iblockdata == null) {
 +                this.isDestroyingBlock = false;
 +                return;
@@ -51,7 +51,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                      ServerPlayerGameMode.LOGGER.debug("Mismatch in destroy block pos: {} {}", this.destroyPos, pos); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled
 -                    this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1);
 -                    this.player.connection.send(new ClientboundBlockBreakAckPacket(this.destroyPos, this.level.getBlockState(this.destroyPos), action, true, "aborted mismatched destroying"));
-+                    BlockState type = this.level.getTypeIfLoaded(this.destroyPos); // Paper - don't load unloaded chunks for stale records here
++                    BlockState type = this.level.getBlockStateIfLoaded(this.destroyPos); // Paper - don't load unloaded chunks for stale records here
 +                    if (type != null) this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); // Paper
 +                    if (type != null) this.player.connection.send(new ClientboundBlockBreakAckPacket(this.destroyPos, type, action, true, "aborted mismatched destroying")); // Paper
 +                    this.destroyPos = BlockPos.ZERO; // Paper
diff --git a/patches/server/Don-t-load-Chunks-from-Hoppers-and-other-things.patch b/patches/server/Don-t-load-Chunks-from-Hoppers-and-other-things.patch
index 208b0512cb..c5b316e61c 100644
--- a/patches/server/Don-t-load-Chunks-from-Hoppers-and-other-things.patch
+++ b/patches/server/Don-t-load-Chunks-from-Hoppers-and-other-things.patch
@@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  BlockPos blockPos = pos.relative(function.apply(state));
 -                BlockState blockState = world.getBlockState(blockPos);
 +                // Paper start
-+                BlockState blockState = world.getTypeIfLoaded(blockPos);
++                BlockState blockState = world.getBlockStateIfLoaded(blockPos);
 +                if (blockState == null) {
 +                    return new DoubleBlockCombiner.NeighborCombineResult.Single<>(blockEntity);
 +                }
diff --git a/patches/server/Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/patches/server/Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch
index dff5e447b9..eea7d66488 100644
--- a/patches/server/Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch
+++ b/patches/server/Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch
@@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
      public void blockChanged(BlockPos pos) {
-+        if (!pos.isValidLocation(levelHeightAccessor)) return; // Paper - SPIGOT-6086 for all invalid locations; avoid acquiring locks
++        if (!pos.isInsideBuildHeightAndWorldBoundsHorizontal(levelHeightAccessor)) return; // Paper - SPIGOT-6086 for all invalid locations; avoid acquiring locks
          LevelChunk chunk = this.getTickingChunk();
  
          if (chunk != null) {
diff --git a/patches/server/Highly-optimise-single-and-multi-AABB-VoxelShapes-an.patch b/patches/server/Highly-optimise-single-and-multi-AABB-VoxelShapes-an.patch
index a19c475239..bbfc4c63b0 100644
--- a/patches/server/Highly-optimise-single-and-multi-AABB-VoxelShapes-an.patch
+++ b/patches/server/Highly-optimise-single-and-multi-AABB-VoxelShapes-an.patch
@@ -992,7 +992,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                                    continue;
 +                                }
 +
-+                                BlockState type = chunk.getType(fx, fy, fz);
++                                BlockState type = chunk.getBlockStateFinal(fx, fy, fz);
 +                                if (type.is((Tag) BlockTags.FIRE) || type.is(Blocks.LAVA)) {
 +                                    noneMatch = false;
 +                                    // can't break, we need to retain vanilla behavior by ensuring ALL chunks are loaded
diff --git a/patches/server/MC-Utils.patch b/patches/server/MC-Utils.patch
index dd49540c0e..4987c52607 100644
--- a/patches/server/MC-Utils.patch
+++ b/patches/server/MC-Utils.patch
@@ -6041,13 +6041,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +
 +    @Override
-+    public BlockState getTypeIfLoaded(BlockPos blockposition) {
++    public final BlockState getBlockStateIfLoaded(BlockPos blockposition) {
 +        ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4);
 +        return chunk == null ? null : chunk.getBlockState(blockposition);
 +    }
 +
 +    @Override
-+    public FluidState getFluidIfLoaded(BlockPos blockposition) {
++    public final FluidState getFluidIfLoaded(BlockPos blockposition) {
 +        ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4);
 +        return chunk == null ? null : chunk.getFluidState(blockposition);
 +    }
@@ -6216,17 +6216,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
      BlockState getBlockState(BlockPos pos);
 +    // Paper start - if loaded util
-+    @Nullable BlockState getTypeIfLoaded(BlockPos blockposition);
-+    default Material getMaterialIfLoaded(BlockPos blockposition) {
-+        BlockState type = this.getTypeIfLoaded(blockposition);
++    @Nullable BlockState getBlockStateIfLoaded(BlockPos blockposition);
++    default @Nullable Material getMaterialIfLoaded(BlockPos blockposition) {
++        BlockState type = this.getBlockStateIfLoaded(blockposition);
 +        return type == null ? null : type.getMaterial();
 +    }
 +
-+    default Block getBlockIfLoaded(BlockPos blockposition) {
-+        BlockState type = this.getTypeIfLoaded(blockposition);
++    default @Nullable Block getBlockIfLoaded(BlockPos blockposition) {
++        BlockState type = this.getBlockStateIfLoaded(blockposition);
 +        return type == null ? null : type.getBlock();
 +    }
-+    FluidState getFluidIfLoaded(BlockPos blockposition);
++    @Nullable FluidState getFluidIfLoaded(BlockPos blockposition);
 +    // Paper end
  
      FluidState getFluidState(BlockPos pos);
@@ -6282,13 +6282,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
 +    // Paper start - If loaded util
 +    @Override
-+    public FluidState getFluidIfLoaded(BlockPos blockposition) {
-+        return this.getFluidState(blockposition);
++    public final FluidState getFluidIfLoaded(BlockPos blockposition) {
++        return Fluids.EMPTY.defaultFluidState();
 +    }
 +
 +    @Override
-+    public BlockState getTypeIfLoaded(BlockPos blockposition) {
-+        return this.getBlockState(blockposition);
++    public final BlockState getBlockStateIfLoaded(BlockPos blockposition) {
++        return Blocks.AIR.defaultBlockState();
 +    }
 +    // Paper end
 +
@@ -6333,7 +6333,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +
 +    @Override
 +    @Nullable
-+    public final BlockState getTypeIfLoaded(BlockPos blockposition) {
++    public final BlockState getBlockStateIfLoaded(BlockPos blockposition) {
 +        // CraftBukkit start - tree generation
 +        if (captureTreeGeneration) {
 +            CraftBlockState previous = capturedBlockStates.get(blockposition);
@@ -6351,15 +6351,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +
 +    @Override
-+    public FluidState getFluidIfLoaded(BlockPos blockposition) {
++    public final FluidState getFluidIfLoaded(BlockPos blockposition) {
 +        ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4);
 +
 +        return chunk == null ? null : chunk.getFluidState(blockposition);
 +    }
-+    // Paper end
 +
 +    @Override
 +    public final ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { // Paper - final for inline
++        // Paper end
          ChunkAccess ichunkaccess = this.getChunkSource().getChunk(chunkX, chunkZ, leastStatus, create);
  
          if (ichunkaccess == null && create) {
@@ -6406,35 +6406,45 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  import net.minecraft.world.level.block.Blocks;
  import net.minecraft.world.level.block.entity.BlockEntity;
 @@ -0,0 +0,0 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter {
-         return List.of();
+     private ChunkAccess getChunk(int chunkX, int chunkZ) {
+         int i = chunkX - this.centerX;
+         int j = chunkZ - this.centerZ;
+-        if (i >= 0 && i < this.chunks.length && j >= 0 && j < this.chunks[i].length) {
++        if (i >= 0 && i < this.chunks.length && j >= 0 && j < this.chunks[i].length) { // Paper - if this changes, update getChunkIfLoaded below
+             ChunkAccess chunkAccess = this.chunks[i][j];
+             return (ChunkAccess)(chunkAccess != null ? chunkAccess : new EmptyLevelChunk(this.level, new ChunkPos(chunkX, chunkZ)));
+         } else {
+@@ -0,0 +0,0 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter {
+         }
      }
  
 +    // Paper start - if loaded util
-+    private ChunkAccess getChunkIfLoaded(int x, int z) {
-+        int k = x - this.centerX;
-+        int l = z - this.centerZ;
++    private @Nullable ChunkAccess getChunkIfLoaded(int x, int z) {
++        // Based on getChunk(int, int)
++        int xx = x - this.centerX;
++        int zz = z - this.centerZ;
 +
-+        if (k >= 0 && k < this.chunks.length && l >= 0 && l < this.chunks[k].length) { // Paper - if this changes, update getChunkIfLoaded below
-+            return this.chunks[k][l];
++        if (xx >= 0 && xx < this.chunks.length && zz >= 0 && zz < this.chunks[xx].length) {
++            return this.chunks[xx][zz];
 +        }
 +        return null;
 +    }
 +    @Override
-+    public FluidState getFluidIfLoaded(BlockPos blockposition) {
++    public final FluidState getFluidIfLoaded(BlockPos blockposition) {
 +        ChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4);
 +        return chunk == null ? null : chunk.getFluidState(blockposition);
 +    }
 +
 +    @Override
-+    public BlockState getTypeIfLoaded(BlockPos blockposition) {
++    public final BlockState getBlockStateIfLoaded(BlockPos blockposition) {
 +        ChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4);
 +        return chunk == null ? null : chunk.getBlockState(blockposition);
 +    }
 +    // Paper end
 +
-     @Nullable
      @Override
-     public BlockEntity getBlockEntity(BlockPos pos) {
+     public WorldBorder getWorldBorder() {
+         return this.level.getWorldBorder();
 diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
@@ -6639,12 +6649,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
 +    // Paper start - If loaded util
 +    @Override
-+    public FluidState getFluidIfLoaded(BlockPos blockposition) {
++    public final FluidState getFluidIfLoaded(BlockPos blockposition) {
 +        return this.getFluidState(blockposition);
 +    }
 +
 +    @Override
-+    public BlockState getTypeIfLoaded(BlockPos blockposition) {
++    public final BlockState getBlockStateIfLoaded(BlockPos blockposition) {
 +        return this.getBlockState(blockposition);
 +    }
 +    // Paper end
@@ -6719,12 +6729,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
 +    // Paper start - If loaded util
 +    @Override
-+    public FluidState getFluidIfLoaded(BlockPos blockposition) {
++    public final FluidState getFluidIfLoaded(BlockPos blockposition) {
 +        return this.getFluidState(blockposition);
 +    }
 +
 +    @Override
-+    public BlockState getTypeIfLoaded(BlockPos blockposition) {
++    public final BlockState getBlockStateIfLoaded(BlockPos blockposition) {
 +        return this.getBlockState(blockposition);
 +    }
 +    // Paper end
@@ -7007,7 +7017,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +
 +    @Override
-+    public BlockState getTypeIfLoaded(BlockPos blockposition) {
++    public BlockState getBlockStateIfLoaded(BlockPos blockposition) {
 +        throw new UnsupportedOperationException("Not supported yet.");
 +    }
  
diff --git a/patches/server/Optimise-BlockSoil-nearby-water-lookup.patch b/patches/server/Optimise-BlockSoil-nearby-water-lookup.patch
index 9504dce522..305277fb94 100644
--- a/patches/server/Optimise-BlockSoil-nearby-water-lookup.patch
+++ b/patches/server/Optimise-BlockSoil-nearby-water-lookup.patch
@@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                for (int dy = 0; dy <= 1; ++dy) {
 +                    int y = dy + yOff;
 +                    net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk)world.getChunk(x >> 4, z >> 4);
-+                    net.minecraft.world.level.material.FluidState fluid = chunk.getBlockData(x, y, z).getFluidState();
++                    net.minecraft.world.level.material.FluidState fluid = chunk.getBlockStateFinal(x, y, z).getFluidState();
 +                    if (fluid.is(FluidTags.WATER)) {
 +                        return true;
 +                    }
diff --git a/patches/server/Optimise-collision-checking-in-player-move-packet-ha.patch b/patches/server/Optimise-collision-checking-in-player-move-packet-ha.patch
index ee652bef40..7198d70b80 100644
--- a/patches/server/Optimise-collision-checking-in-player-move-packet-ha.patch
+++ b/patches/server/Optimise-collision-checking-in-player-move-packet-ha.patch
@@ -73,7 +73,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            for (int z = minZ; z <= maxZ; ++z) {
 +                for (int x = minX; x <= maxX; ++x) {
 +                    pos.set(x, y, z);
-+                    BlockState type = world.getTypeIfLoaded(pos);
++                    BlockState type = world.getBlockStateIfLoaded(pos);
 +                    if (type != null && !type.isAir()) {
 +                        return false;
 +                    }
diff --git a/patches/server/Optimize-Collision-to-not-load-chunks.patch b/patches/server/Optimize-Collision-to-not-load-chunks.patch
index 088c218b37..d03e71e48d 100644
--- a/patches/server/Optimize-Collision-to-not-load-chunks.patch
+++ b/patches/server/Optimize-Collision-to-not-load-chunks.patch
@@ -72,7 +72,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                } else if ((!far && source instanceof net.minecraft.server.level.ServerPlayer) || (source != null && source.collisionLoadChunks)) {
 +                    blockState = this.collisionGetter.getBlockState(this.pos);
 +                } else {
-+                    blockState = this.collisionGetter.getTypeIfLoaded(this.pos);
++                    blockState = this.collisionGetter.getBlockStateIfLoaded(this.pos);
 +                }
 +
 +                if (blockState == null) {
diff --git a/patches/server/Optimize-isValidLocation-getType-and-getBlockData-fo.patch b/patches/server/Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch
similarity index 85%
rename from patches/server/Optimize-isValidLocation-getType-and-getBlockData-fo.patch
rename to patches/server/Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch
index 91d26a6630..fb31aad9a8 100644
--- a/patches/server/Optimize-isValidLocation-getType-and-getBlockData-fo.patch
+++ b/patches/server/Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch
@@ -1,8 +1,7 @@
 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 isValidLocation, getType and getBlockData for
- inlining
+Subject: [PATCH] Optimize isInWorldBounds and getBlockState for inlining
 
 Hot methods, so reduce # of instructions for the method.
 
@@ -21,12 +20,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
 +    // Paper start
-+    public boolean isValidLocation(net.minecraft.world.level.LevelHeightAccessor levelHeightAccessor) {
++    public final boolean isInsideBuildHeightAndWorldBoundsHorizontal(net.minecraft.world.level.LevelHeightAccessor levelHeightAccessor) {
 +        return getX() >= -30000000 && getZ() >= -30000000 && getX() < 30000000 && getZ() < 30000000 && !levelHeightAccessor.isOutsideBuildHeight(getY());
 +    }
-+    public boolean isInvalidYLocation(net.minecraft.world.level.LevelHeightAccessor levelHeightAccessor) {
-+        return levelHeightAccessor.isOutsideBuildHeight(getY());
-+    }
 +    // Paper end
 +
      public Vec3i(int x, int y, int z) {
@@ -41,7 +37,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
      public boolean isInWorldBounds(BlockPos pos) {
 -        return !this.isOutsideBuildHeight(pos) && Level.isInWorldBoundsHorizontal(pos);
-+        return pos.isValidLocation(this); // Paper - use better/optimized check
++        return pos.isInsideBuildHeightAndWorldBoundsHorizontal(this); // Paper - use better/optimized check
      }
  
      public static boolean isInSpawnableBounds(BlockPos pos) {
@@ -53,7 +49,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          return GameEventDispatcher.NOOP;
      }
  
-+    public abstract BlockState getType(final int x, final int y, final int z); // Paper
++    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);
  
@@ -66,7 +62,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
 +    // Paper start
-+    @Override public BlockState getType(int x, int y, int z) {
++    @Override
++    public BlockState getBlockState(int x, int y, int z) {
 +        return Blocks.VOID_AIR.defaultBlockState();
 +    }
 +    // Paper end
@@ -82,8 +79,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          return this.wrapped.getBlockState(pos);
      }
 +    // Paper start
-+    public final BlockState getType(final int x, final int y, final int z) {
-+        return this.wrapped.getBlockData(x, y, z);
++    @Override
++    public final BlockState getBlockState(final int x, final int y, final int z) {
++        return this.wrapped.getBlockStateFinal(x, y, z);
 +    }
 +    // Paper end
  
@@ -103,16 +101,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -        int i = pos.getX();
 -        int j = pos.getY();
 -        int k = pos.getZ();
-+        return this.getBlockData(pos.getX(), pos.getY(), pos.getZ());
++        return this.getBlockStateFinal(pos.getX(), pos.getY(), pos.getZ());
 +    }
 +
-+    public BlockState getType(final int x, final int y, final int z) {
-+        return this.getBlockData(x, y, z);
++    @Override
++    public BlockState getBlockState(final int x, final int y, final int z) {
++        return this.getBlockStateFinal(x, y, z);
 +    }
-+    public final BlockState getBlockData(final int x, final int y, final int 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] == null || this.sections[i].nonEmptyBlockCount == 0) {
++        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)
@@ -120,7 +119,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
 +    }
 +
-+    public BlockState getBlockData_unused(int i, int j, int k) {
++    public BlockState getBlockState_unused(int i, int j, int k) {
 +        // Paper end
          if (this.level.isDebug()) {
              BlockState iblockdata = null;
@@ -149,9 +148,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -        int i = pos.getY();
 -        if (this.isOutsideBuildHeight(i)) {
 +        // Paper start
-+        return getType(pos.getX(), pos.getY(), pos.getZ());
++        return getBlockState(pos.getX(), pos.getY(), pos.getZ());
 +    }
-+    public BlockState getType(final int x, final int y, final int z) {
++    public BlockState getBlockState(final int x, final int y, final int z) {
 +        if (this.isOutsideBuildHeight(y)) {
              return Blocks.VOID_AIR.defaultBlockState();
          } else {
diff --git a/patches/server/Prevent-Enderman-from-loading-chunks.patch b/patches/server/Prevent-Enderman-from-loading-chunks.patch
index 244c267f68..3b98fe6b0e 100644
--- a/patches/server/Prevent-Enderman-from-loading-chunks.patch
+++ b/patches/server/Prevent-Enderman-from-loading-chunks.patch
@@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              int k = Mth.floor(this.enderman.getZ() - 1.0D + random.nextDouble() * 2.0D);
              BlockPos blockposition = new BlockPos(i, j, k);
 -            BlockState iblockdata = world.getBlockState(blockposition);
-+            BlockState iblockdata = world.getTypeIfLoaded(blockposition); // Paper
++            BlockState iblockdata = world.getBlockStateIfLoaded(blockposition); // Paper
 +            if (iblockdata == null) return; // Paper
              BlockPos blockposition1 = blockposition.below();
              BlockState iblockdata1 = world.getBlockState(blockposition1);
@@ -23,7 +23,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              int k = Mth.floor(this.enderman.getZ() - 2.0D + random.nextDouble() * 4.0D);
              BlockPos blockposition = new BlockPos(i, j, k);
 -            BlockState iblockdata = world.getBlockState(blockposition);
-+            BlockState iblockdata = world.getTypeIfLoaded(blockposition); // Paper
++            BlockState iblockdata = world.getBlockStateIfLoaded(blockposition); // Paper
 +            if (iblockdata == null) return; // Paper
              Vec3 vec3d = new Vec3((double) this.enderman.getBlockX() + 0.5D, (double) j + 0.5D, (double) this.enderman.getBlockZ() + 0.5D);
              Vec3 vec3d1 = new Vec3((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D);
diff --git a/patches/server/Prevent-Frosted-Ice-from-loading-holding-chunks.patch b/patches/server/Prevent-Frosted-Ice-from-loading-holding-chunks.patch
index cf547eecb7..ab30261e51 100644
--- a/patches/server/Prevent-Frosted-Ice-from-loading-holding-chunks.patch
+++ b/patches/server/Prevent-Frosted-Ice-from-loading-holding-chunks.patch
@@ -14,7 +14,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              for(Direction direction : Direction.values()) {
                  mutableBlockPos.setWithOffset(pos, direction);
 -                BlockState blockState = world.getBlockState(mutableBlockPos);
-+                BlockState blockState = world.getTypeIfLoaded(mutableBlockPos); // Paper
++                BlockState blockState = world.getBlockStateIfLoaded(mutableBlockPos); // Paper
 +                if (blockState == null) { continue; } // Paper
                  if (blockState.is(this) && !this.slightlyMelt(blockState, world, mutableBlockPos)) {
                      world.scheduleTick(mutableBlockPos, this, Mth.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay
@@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              mutableBlockPos.setWithOffset(pos, direction);
 -            if (world.getBlockState(mutableBlockPos).is(this)) {
 +            // Paper start
-+            BlockState blockState = world.getTypeIfLoaded(mutableBlockPos);
++            BlockState blockState = world.getBlockStateIfLoaded(mutableBlockPos);
 +            if (blockState != null && blockState.is(this)) {
 +                // Paper end
                  ++i;
diff --git a/patches/server/Prevent-Mob-AI-Rules-from-Loading-Chunks.patch b/patches/server/Prevent-Mob-AI-Rules-from-Loading-Chunks.patch
index ac69a2264c..c2f17fad31 100644
--- a/patches/server/Prevent-Mob-AI-Rules-from-Loading-Chunks.patch
+++ b/patches/server/Prevent-Mob-AI-Rules-from-Loading-Chunks.patch
@@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      @Nullable
      private BlockPos getPosWithBlock(BlockPos pos, BlockGetter world) {
 -        if (world.getBlockState(pos).is(this.blockToRemove)) {
-+        net.minecraft.world.level.block.state.BlockState block = world.getTypeIfLoaded(pos); // Paper
++        net.minecraft.world.level.block.state.BlockState block = world.getBlockStateIfLoaded(pos); // Paper
 +        if (block == null) return null; // Paper
 +        if (block.is(this.blockToRemove)) { // Paper
              return pos;
@@ -24,7 +24,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  BlockPos blockposition1 = ablockposition1[j];
  
 -                if (world.getBlockState(blockposition1).is(this.blockToRemove)) {
-+                net.minecraft.world.level.block.state.BlockState block2 = world.getTypeIfLoaded(blockposition1); // Paper
++                net.minecraft.world.level.block.state.BlockState block2 = world.getBlockStateIfLoaded(blockposition1); // Paper
 +                if (block2 != null && block2.is(this.blockToRemove)) { // Paper
                      return blockposition1;
                  }
diff --git a/patches/server/Prevent-chunk-loading-from-Fluid-Flowing.patch b/patches/server/Prevent-chunk-loading-from-Fluid-Flowing.patch
index 434e53ef2b..9fb4af40fa 100644
--- a/patches/server/Prevent-chunk-loading-from-Fluid-Flowing.patch
+++ b/patches/server/Prevent-chunk-loading-from-Fluid-Flowing.patch
@@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  FluidState fluid1 = (FluidState) entry.getValue();
                  BlockPos blockposition1 = pos.relative(enumdirection);
 -                BlockState iblockdata1 = world.getBlockState(blockposition1);
-+                BlockState iblockdata1 = world.getTypeIfLoaded(blockposition1); // Paper
++                BlockState iblockdata1 = world.getBlockStateIfLoaded(blockposition1); // Paper
 +                if (iblockdata1 == null) continue; // Paper
  
                  if (this.canSpreadTo(world, pos, blockState, enumdirection, blockposition1, iblockdata1, world.getFluidState(blockposition1), fluid1.getType())) {
@@ -24,7 +24,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              BlockPos blockposition1 = pos.relative(enumdirection);
 -            BlockState iblockdata1 = world.getBlockState(blockposition1);
 +
-+            BlockState iblockdata1 = world.getTypeIfLoaded(blockposition1); // Paper
++            BlockState iblockdata1 = world.getBlockStateIfLoaded(blockposition1); // Paper
 +            if (iblockdata1 == null) continue; // Paper
              FluidState fluid = iblockdata1.getFluidState();
  
@@ -38,7 +38,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                // Paper start - avoid loading chunks
 +                Pair<BlockState, FluidState> pair = short2objectmap.get(short0);
 +                if (pair == null) {
-+                    BlockState iblockdatax = world.getTypeIfLoaded(blockposition2);
++                    BlockState iblockdatax = world.getBlockStateIfLoaded(blockposition2);
 +                    if (iblockdatax == null) {
 +                        continue;
 +                    }
@@ -64,7 +64,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            // Paper start
 +            Pair pair = (Pair) short2objectmap.get(short0);
 +            if (pair == null) {
-+                BlockState iblockdatax = world.getTypeIfLoaded(blockposition1);
++                BlockState iblockdatax = world.getBlockStateIfLoaded(blockposition1);
 +                if (iblockdatax == null) continue;
 +
 +                pair = Pair.of(iblockdatax, iblockdatax.getFluidState());
diff --git a/patches/server/Prevent-mob-spawning-from-loading-generating-chunks.patch b/patches/server/Prevent-mob-spawning-from-loading-generating-chunks.patch
index 706a5a9398..bd415097ad 100644
--- a/patches/server/Prevent-mob-spawning-from-loading-generating-chunks.patch
+++ b/patches/server/Prevent-mob-spawning-from-loading-generating-chunks.patch
@@ -14,7 +14,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator();
          int i = pos.getY();
 -        BlockState iblockdata = chunk.getBlockState(pos);
-+        BlockState iblockdata = world.getTypeIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn
++        BlockState iblockdata = world.getBlockStateIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn
  
 -        if (!iblockdata.isRedstoneConductor(chunk, pos)) {
 +        if (iblockdata != null && !iblockdata.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn
diff --git a/patches/server/Prevent-rayTrace-from-loading-chunks.patch b/patches/server/Prevent-rayTrace-from-loading-chunks.patch
index bdac6a8986..4b99d196db 100644
--- a/patches/server/Prevent-rayTrace-from-loading-chunks.patch
+++ b/patches/server/Prevent-rayTrace-from-loading-chunks.patch
@@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition) {
 -            BlockState iblockdata = this.getBlockState(blockposition);
 +            // Paper start - Prevent raytrace from loading chunks
-+            BlockState iblockdata = this.getTypeIfLoaded(blockposition);
++            BlockState iblockdata = this.getBlockStateIfLoaded(blockposition);
 +            if (iblockdata == null) {
 +                // copied the last function parameter (listed below)
 +                Vec3 vec3d = raytrace1.getFrom().subtract(raytrace1.getTo());
diff --git a/patches/server/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch b/patches/server/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch
index fc67e01e55..d2ff17dfe7 100644
--- a/patches/server/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch
+++ b/patches/server/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch
@@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  }
  
 -                BlockState blockState = world.getBlockState(globalPos.pos());
-+                BlockState blockState = world.getTypeIfLoaded(globalPos.pos()); // Paper
++                BlockState blockState = world.getBlockStateIfLoaded(globalPos.pos()); // Paper
 +                if (blockState == null) { return false; } // Paper
                  return globalPos.pos().closerThan(entity.position(), 2.0D) && blockState.is(BlockTags.BEDS) && !blockState.getValue(BedBlock.OCCUPIED);
              }
diff --git a/patches/server/Rewrite-the-light-engine.patch b/patches/server/Rewrite-the-light-engine.patch
index 09591baebd..ff1e0afb51 100644
--- a/patches/server/Rewrite-the-light-engine.patch
+++ b/patches/server/Rewrite-the-light-engine.patch
@@ -4893,8 +4893,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    public void setBlockEmptinessMap(final boolean[] emptinessMap) {}
 +
      // Paper start
-     @Override public BlockState getType(int x, int y, int z) {
-         return Blocks.VOID_AIR.defaultBlockState();
+     @Override
+     public BlockState getBlockState(int x, int y, int z) {
 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
diff --git a/patches/server/implement-optional-per-player-mob-spawns.patch b/patches/server/implement-optional-per-player-mob-spawns.patch
index faae7fc5f8..b0455a4baf 100644
--- a/patches/server/implement-optional-per-player-mob-spawns.patch
+++ b/patches/server/implement-optional-per-player-mob-spawns.patch
@@ -740,7 +740,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          StructureFeatureManager structuremanager = world.structureFeatureManager();
          ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator();
          int i = pos.getY();
-         BlockState iblockdata = world.getTypeIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn
+         BlockState iblockdata = world.getBlockStateIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn
 +        int j = 0; // Paper - moved up
  
          if (iblockdata != null && !iblockdata.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn