PaperMC/patches/server/0069-Optimize-isValidLocation-getType-and-getBlockData-fo.patch
2021-06-12 09:26:16 +02:00

193 lines
9.5 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
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..c66ae4d9eea993f3b7fcc6e253259db3346229d1 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<Vec3i> {
private int y;
private int z;
+ // Paper start
+ public boolean isValidLocation(net.minecraft.world.level.Level level) {
+ return getX() >= -30000000 && getZ() >= -30000000 && getX() < 30000000 && getZ() < 30000000 && !level.isOutsideBuildHeight(getY());
+ }
+ public boolean isInvalidYLocation(net.minecraft.world.level.Level level) {
+ return level.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 9939c4c39549771afe971a6433dfd57e36050dd8..7e5e16fd61b39d2093459766e8aaa10bb05f6763 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<BlockState> 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<BlockState> states;
+ final PalettedContainer<BlockState> 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<T> implements PaletteResize<T> {
}
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) {