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 f4b5792e080d5181184eb661d005ce6cab649bf3..35b26f4a4554541affbf76df38fed0f7e555c9b9 100644 --- a/src/main/java/net/minecraft/core/Vec3i.java +++ b/src/main/java/net/minecraft/core/Vec3i.java @@ -21,6 +21,15 @@ public class Vec3i implements Comparable { private int y; private int z; + // 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 aee97243cc3e73f9e07ba8ed5d6dbe8c73ba016e..fdab998241a682bc3d75094e0893f98886e06266 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -259,7 +259,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 6a3f98edbc2b4056c5baf00277caee327e444a77..974ab04b08bbd3c27a394b37c1af112be5f28f43 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java @@ -29,6 +29,7 @@ public interface ChunkAccess extends BlockGetter, FeatureAccess { return GameEventDispatcher.NOOP; } + BlockState getType(final int x, final int y, final int z); // Paper @Nullable 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 84ebfdfc4350fb57ca2959e000b33b8d5efa6e0b..69c2454533e6f21c70792b555ec02c6bc6d169b3 100644 --- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java @@ -19,6 +19,11 @@ public class EmptyLevelChunk extends LevelChunk { super(world, pos, new EmptyLevelChunk.EmptyChunkBiomeContainer(world)); } + // 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 c1beb6d5fc3cabfeacf0ffbf563e53ff7984c5d3..452b513e8b89d865a396066adaf4feb1140e1c62 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java @@ -40,6 +40,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 b36a893ded952d1a5ed1a55eae9c3c406848e1f3..092f2cd5806e8609b952e7678c0c38b235c52264 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -337,12 +337,28 @@ public class LevelChunk implements ChunkAccess { return this.sections; } + // 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 03fd5684aec8fa0d87963f2adcd8244e92840917..5fd66020a937b641e2a060cf38df731a43f3bf55 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java @@ -15,10 +15,10 @@ public class LevelChunkSection { public static final int SECTION_SIZE = 4096; public static final Palette GLOBAL_BLOCKSTATE_PALETTE = new GlobalPalette<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState()); private final int bottomBlockY; - private short nonEmptyBlockCount; + short nonEmptyBlockCount; // Paper - package-private private short tickingBlockCount; private short tickingFluidCount; - private final PalettedContainer states; + final PalettedContainer states; // Paper - package-private public LevelChunkSection(int yOffset) { this(yOffset, (short)0, (short)0, (short)0); @@ -37,7 +37,7 @@ public class LevelChunkSection { } public BlockState getBlockState(int x, int y, int z) { - return this.states.get(x, y, z); + return this.states.get(y << 8 | z << 4 | x); // Paper - inline } public FluidState getFluidState(int x, int y, int z) { diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java index 4a6781919eb78abc33f549693d88019b42ef6e95..5ea60bbb56450502f1ceb41959239ab579458ac2 100644 --- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java @@ -136,7 +136,7 @@ public class PalettedContainer implements PaletteResize { } public T get(int x, int y, int z) { - return this.get(getIndex(x, y, z)); + return this.get(y << 8 | z << 4 | x); // Paper - inline } protected T get(int index) { 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 39fe8f64528ad08594aaaa88e5c989c82e4e29d3..da36e6d40ad3e8b7cdbe09ef911d1e5b8c28670f 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java @@ -104,14 +104,18 @@ public class ProtoChunk implements 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.getSections()[this.getSectionIndex(i)]; - return LevelChunkSection.isEmpty(levelChunkSection) ? Blocks.AIR.defaultBlockState() : levelChunkSection.getBlockState(pos.getX() & 15, i & 15, pos.getZ() & 15); + LevelChunkSection chunksection = this.getSections()[this.getSectionIndex(y)]; + return chunksection == LevelChunk.EMPTY_CHUNK_SECTION || chunksection.isEmpty() ? Blocks.AIR.defaultBlockState() : chunksection.getBlockState(x & 15, y & 15, z & 15); } } + // Paper end @Override public FluidState getFluidState(BlockPos pos) {