From b7a1e0ede8a8ad47748a9b64280e27c2a5974315 Mon Sep 17 00:00:00 2001 From: Phoenix616 Date: Mon, 13 Jan 2020 15:40:32 +0100 Subject: [PATCH] Seed based feature search This fixes the issue where the server will load surrounding chunks up to a radius of 100 chunks in order to search for features e.g. when running the /locate command or for treasure maps (issue #2312). This is done by using the same seed checking functionality that is used by the server when generating these features before actually attempting to load the chunk to check if a feature is available in it. The only downside of this is that it breaks once the seed or generator changes but this should usually not happen. A config option to disable this improvement is added though in case that should ever be necessary. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java index 3b8488d3ff..bce502181f 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -359,6 +359,12 @@ public class PaperWorldConfig { } } + public boolean seedBasedFeatureSearch = true; + private void seedBasedFeatureSearch() { + seedBasedFeatureSearch = getBoolean("seed-based-feature-search", seedBasedFeatureSearch); + log("Feature search is based on seed: " + seedBasedFeatureSearch); + } + public int maxCollisionsPerEntity; private void maxEntityCollision() { maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); diff --git a/src/main/java/net/minecraft/server/BiomeManager.java b/src/main/java/net/minecraft/server/BiomeManager.java index e96f544f12..68423645df 100644 --- a/src/main/java/net/minecraft/server/BiomeManager.java +++ b/src/main/java/net/minecraft/server/BiomeManager.java @@ -12,10 +12,12 @@ public class BiomeManager { this.c = genlayerzoomer; } + public BiomeManager withProvider(WorldChunkManager worldchunkmanager) { return a(worldchunkmanager); } // Paper - OBFHELPER public BiomeManager a(WorldChunkManager worldchunkmanager) { return new BiomeManager(worldchunkmanager, this.b, this.c); } + public BiomeBase getBiome(BlockPosition blockposition) { return a(blockposition); } // Paper - OBFHELPER public BiomeBase a(BlockPosition blockposition) { return this.c.a(this.b, blockposition.getX(), blockposition.getY(), blockposition.getZ(), this.a); } diff --git a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java index f2a19acd84..09f1308b0d 100644 --- a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java +++ b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java @@ -64,10 +64,12 @@ public class ChunkCoordIntPair { } } + public int getBlockX() { return d(); } // Paper - OBFHELPER public int d() { return this.x << 4; } + public int getBlockZ() { return e(); } // Paper - OBFHELPER public int e() { return this.z << 4; } diff --git a/src/main/java/net/minecraft/server/StructureGenerator.java b/src/main/java/net/minecraft/server/StructureGenerator.java index e8ce2ecf23..acfe732af5 100644 --- a/src/main/java/net/minecraft/server/StructureGenerator.java +++ b/src/main/java/net/minecraft/server/StructureGenerator.java @@ -109,6 +109,15 @@ public abstract class StructureGenerator if (flag1 || flag2) { ChunkCoordIntPair chunkcoordintpair = this.a(chunkgenerator, seededrandom, j, k, i1, j1); if (!world.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper + // Paper start - seed based feature search + if (world.paperConfig.seedBasedFeatureSearch) { + BiomeManager biomeManager = world.getBiomeManager().withProvider(chunkgenerator.getWorldChunkManager()); + BiomeBase biomeBase = biomeManager.getBiome(new BlockPosition(chunkcoordintpair.getBlockX() + 9, 0, chunkcoordintpair.getBlockZ() + 9)); + if (!shouldGenerate(biomeManager, chunkgenerator, seededrandom, chunkcoordintpair.x, chunkcoordintpair.z, biomeBase)) { + continue; + } + } + // Paper end StructureStart structurestart = world.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS).a(this.b()); if (structurestart != null && structurestart.e()) { @@ -165,6 +174,7 @@ public abstract class StructureGenerator return new ChunkCoordIntPair(i + k, j + l); } + public boolean shouldGenerate(BiomeManager biomemanager, ChunkGenerator chunkgenerator, Random random, int chunkX, int chunkZ, BiomeBase biomebase) { return a(biomemanager, chunkgenerator, random, chunkX, chunkZ, biomebase); } // Paper - OBFHELPER public abstract boolean a(BiomeManager biomemanager, ChunkGenerator chunkgenerator, Random random, int i, int j, BiomeBase biomebase); public abstract StructureGenerator.a a(); diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java index 1cbd50450d..803fe43be1 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java @@ -1561,8 +1561,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { return this.methodProfiler; } - @Override - public BiomeManager d() { + public BiomeManager getBiomeManager() { return d(); } // Paper - OBFHELPER + @Override public BiomeManager d() { return this.biomeManager; } } -- 2.25.1