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 4587a3668b6be9222cdd74a38229f89f611d1af6..9f32861d791f7e4cb39d2ad01f48e1916fc2b4b1 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 { 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 cccce52ef5a1ac7284bc878c7b8f0d2a312fac57..f1f713c892e1843fdf5adec6714dc72f8fd4d354 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -261,7 +261,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 847ac56f20ab9c5745f9c0fa0e6f16743ba5e471..eea6816c52e6c0329f3bea0e7789cda9dd4a5a08 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java @@ -122,6 +122,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 80e383e9a2d12f9f1b0b0d9ae71a0add9b51c9d4..a9c65c8d36e5c7080133706df1363b3ce52e3370 100644 --- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java @@ -21,6 +21,12 @@ public class EmptyLevelChunk extends LevelChunk { this.biome = holder; } + // 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 82a4f5fb84884d229d258134fbfe62d34ad30d80..37e7f766e0de7b47c7240c9365bb134fda26a756 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java @@ -47,6 +47,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 108c7ec010f826f9b9bb2db0987d2bcc18266482..aa8524af06132096cf593614301cde6a814ff41f 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 a17d38d08a1f4b3e7ba4ef233a4acaf75177ac4c..c696358102086257033b55adbef84b1a259cb46e 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 ee0be5163811ea39efcb2092e5f126c3fd9b1523..d3d2bd5ea57254a4af0572d5dab460127718ce09 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java @@ -88,14 +88,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) {