From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Thu, 3 Mar 2016 02:07:55 -0600 Subject: [PATCH] Optimize isValidLocation, getType and getBlockData 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 543d5a67e76a3114f6eac29a053ff04ceecb6256..c33bac27edfdab4c3ee618c9ed39c629b1513f09 100644 --- a/src/main/java/net/minecraft/core/Vec3i.java +++ b/src/main/java/net/minecraft/core/Vec3i.java @@ -33,6 +33,15 @@ public class Vec3i implements Comparable { return CODEC.flatXmap(checkOffsetAxes(maxAbsValue), checkOffsetAxes(maxAbsValue)); } + // Paper start + public boolean isValidLocation(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) { 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 de1bb9ecb8891b66b2c469f2ee52b9eee9d7ddea..7ee958e6a4f16780aa746ce0eb8cb8ee27df08e1 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -263,7 +263,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { } public boolean isInWorldBounds(BlockPos pos) { - return !this.isOutsideBuildHeight(pos) && Level.isInWorldBoundsHorizontal(pos); + return pos.isValidLocation(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..046afe19aa30f466a08461e3a504c9bbf78f7a3c 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 getType(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..25e9cc39d748dfd99d38f504c14f40f9ec7bdd2d 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,11 @@ public class EmptyLevelChunk extends LevelChunk { super(world, pos); } + // Paper start + @Override public BlockState getType(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..7c5b3acd299c5b021bd20f17ff0b89c8208a6623 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,11 @@ public class ImposterProtoChunk extends ProtoChunk { public BlockState getBlockState(BlockPos pos) { 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); + } + // 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 d207e54019360f7f94bfa5301462fe3c8ac6758e..327b513c75e75d4b07d3c3b6deda9d1d00b6cd7f 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,28 @@ 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.getBlockData(pos.getX(), pos.getY(), pos.getZ()); + } + + public BlockState getType(final int x, final int y, final int z) { + return this.getBlockData(x, y, z); + } + public final BlockState getBlockData(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) { + 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 getBlockData_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 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 b7dbdcb0ce7948c6f98ec67d0cf2033a8e348085..568dc3c9cbf009a3892766cacdd00667556e27c5 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 getType(pos.getX(), pos.getY(), pos.getZ()); + } + public BlockState getType(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) {