From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar 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 1b29c6872ebe54351f28c1f1f38b22561ba785ee..40950db0c242c65dfd4de247c86249354d12108f 100644 --- a/src/main/java/net/minecraft/core/Vec3i.java +++ b/src/main/java/net/minecraft/core/Vec3i.java @@ -31,6 +31,12 @@ public class Vec3i implements Comparable { }); } + // 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 3b3da7340af0b97f900b5eb7fc2ba90f39c4c503..6d6145de1db2d57aa7f342e2467401231c3e38ae 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -285,7 +285,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 1b7496cec0ba5a95615a069e3168bd46308d0b40..508c2fff8d8e0c6f37b6c4e3b72ba772c2ab2ee5 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java @@ -160,6 +160,7 @@ public abstract class ChunkAccess implements BlockGetter, BiomeManager.NoiseBiom return GameEventListenerRegistry.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 2eb92dde607d7c8968cb07c6f3c24e1c45e9990f..908f71721daf4305692f424d7712cbfdddddae83 100644 --- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java @@ -55,6 +55,12 @@ public class EmptyLevelChunk extends LevelChunk { public void setBlockEmptinessMap(final boolean[] emptinessMap) {} // Paper end - starlight + // 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 8033c8741a0f73919a357893652592b317bfb417..9a1cffd51aaf97f759a9057aefbf50bd6f5ed028 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java @@ -89,6 +89,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 03f7394057c927f55fa962a65988d03553c6a642..a37377f1b8eba0a86cdeb31026c5e7fe790b898a 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -335,12 +335,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 bc707432af738ad39de9f8df253913db941a4850..becc4c101e40d9b11e5e89a69e25dc0160bfaa32 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java @@ -21,7 +21,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 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 0b67858f8d6689b34816f9556f3424af512a7401..c24b4c6a560aab2df07783b3481981deb8571a50 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java @@ -94,14 +94,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) {