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 507d38a8e7b643712fe235c73f440c0a52b6d8b2..b6f2be487720e31a548a3cee4cd73319f402f6ff 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 2e5619a581d18008df31f4b2a279e7418264aa4f..7bec92f343d5c79fdff43b36272c0e979c6879d4 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java @@ -113,6 +113,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 65967fd834d8aadf9a6af3ee26164819488dc680..de235aadb3aebcd173fea7ea4783c1e8aa8f4c6a 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 ac17877ea6e210acfb54961a2818ca1ae7f6c738..6e998ca50d07e1ecb0cd0639b81cc07e8be71cb8 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -287,12 +287,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 10848c41b7f2f83717df650bd1fac7149c3a32af..92a42aea3f54c49e2055e8000645d91da9471e09 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) {