From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Thu, 6 Jan 2022 15:59:06 -0800 Subject: [PATCH] Expose vanilla BiomeProvider from WorldInfo diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java index 8e0bc6559aad75a713e1760ea17e5004686d7e7a..0db44e8205d795cbeca1d6411aca0da5edf40d21 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -625,7 +625,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(iworlddataserver)); LevelStem worlddimension = (LevelStem) dimensions.getValue(dimensionKey); - org.bukkit.generator.WorldInfo worldInfo = new org.bukkit.craftbukkit.generator.CraftWorldInfo(iworlddataserver, worldSession, org.bukkit.World.Environment.getEnvironment(dimension), worlddimension.type().value()); + org.bukkit.generator.WorldInfo worldInfo = new org.bukkit.craftbukkit.generator.CraftWorldInfo(iworlddataserver, worldSession, org.bukkit.World.Environment.getEnvironment(dimension), worlddimension.type().value(), worlddimension.generator(), this.registryAccess()); // Paper - Expose vanilla BiomeProvider from WorldInfo if (biomeProvider == null && gen != null) { biomeProvider = gen.getDefaultBiomeProvider(worldInfo); } diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index 3b3024fcf39266cc6ae61fb77dbffb391dc96c92..2d77e9526917a83987ae0486a669538d5417b781 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -357,7 +357,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.serverLevelData.setWorld(this); if (biomeProvider != null) { - BiomeSource worldChunkManager = new CustomWorldChunkManager(this.getWorld(), biomeProvider, this.server.registryAccess().lookupOrThrow(Registries.BIOME)); + BiomeSource worldChunkManager = new CustomWorldChunkManager(this.getWorld(), biomeProvider, this.server.registryAccess().lookupOrThrow(Registries.BIOME), chunkgenerator.getBiomeSource()); // Paper - add vanillaBiomeProvider if (chunkgenerator instanceof NoiseBasedChunkGenerator cga) { chunkgenerator = new NoiseBasedChunkGenerator(worldChunkManager, cga.settings); } else if (chunkgenerator instanceof FlatLevelSource cpf) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 9ee5c98af55e93e304c157d63f6ef4e5ebdc7fc3..0939d4f1297296efdcc083b2a2b0aa987141d42f 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -1310,7 +1310,7 @@ public final class CraftServer implements Server { List list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(worlddata)); LevelStem worlddimension = iregistry.getValue(actualDimension); - WorldInfo worldInfo = new CraftWorldInfo(worlddata, worldSession, creator.environment(), worlddimension.type().value()); + WorldInfo worldInfo = new CraftWorldInfo(worlddata, worldSession, creator.environment(), worlddimension.type().value(), worlddimension.generator(), this.getHandle().getServer().registryAccess()); // Paper - Expose vanilla BiomeProvider from WorldInfo if (biomeProvider == null && generator != null) { biomeProvider = generator.getDefaultBiomeProvider(worldInfo); } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index d3722ffa822f5716ba46dc620a36ab8b0cd7cafe..f544aa7ce6ab98581c4dacf2a79b05ce80131729 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -208,6 +208,39 @@ public class CraftWorld extends CraftRegionAccessor implements World { public int getPlayerCount() { return world.players().size(); } + + @Override + public BiomeProvider vanillaBiomeProvider() { + net.minecraft.server.level.ServerChunkCache serverCache = this.getHandle().chunkSource; + + final net.minecraft.world.level.chunk.ChunkGenerator gen = serverCache.getGenerator(); + net.minecraft.world.level.biome.BiomeSource biomeSource; + if (gen instanceof org.bukkit.craftbukkit.generator.CustomChunkGenerator custom) { + biomeSource = custom.getDelegate().getBiomeSource(); + } else { + biomeSource = gen.getBiomeSource(); + } + if (biomeSource instanceof org.bukkit.craftbukkit.generator.CustomWorldChunkManager customBiomeSource) { + biomeSource = customBiomeSource.vanillaBiomeSource; + } + final net.minecraft.world.level.biome.BiomeSource finalBiomeSource = biomeSource; + final net.minecraft.world.level.biome.Climate.Sampler sampler = serverCache.randomState().sampler(); + + final List possibleBiomes = finalBiomeSource.possibleBiomes().stream() + .map(CraftBiome::minecraftHolderToBukkit) + .toList(); + return new BiomeProvider() { + @Override + public Biome getBiome(final org.bukkit.generator.WorldInfo worldInfo, final int x, final int y, final int z) { + return CraftBiome.minecraftHolderToBukkit(finalBiomeSource.getNoiseBiome(x >> 2, y >> 2, z >> 2, sampler)); + } + + @Override + public List getBiomes(final org.bukkit.generator.WorldInfo worldInfo) { + return possibleBiomes; + } + }; + } // Paper end private static final Random rand = new Random(); diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftWorldInfo.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftWorldInfo.java index 5d655d6cd3e23e0287069f8bdf77601487e862fd..c81455a4ee9a3185f125ebf8cec325f4ed2e501d 100644 --- a/src/main/java/org/bukkit/craftbukkit/generator/CraftWorldInfo.java +++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftWorldInfo.java @@ -17,8 +17,14 @@ public class CraftWorldInfo implements WorldInfo { private final long seed; private final int minHeight; private final int maxHeight; + // Paper start + private final net.minecraft.world.level.chunk.ChunkGenerator vanillaChunkGenerator; + private final net.minecraft.core.RegistryAccess.Frozen registryAccess; - public CraftWorldInfo(ServerLevelData worldDataServer, LevelStorageSource.LevelStorageAccess session, World.Environment environment, DimensionType dimensionManager) { + public CraftWorldInfo(PrimaryLevelData worldDataServer, LevelStorageSource.LevelStorageAccess session, World.Environment environment, DimensionType dimensionManager, net.minecraft.world.level.chunk.ChunkGenerator chunkGenerator, net.minecraft.core.RegistryAccess.Frozen registryAccess) { + this.registryAccess = registryAccess; + this.vanillaChunkGenerator = chunkGenerator; + // Paper end this.name = worldDataServer.getLevelName(); this.uuid = WorldUUID.getUUID(session.levelDirectory.path().toFile()); this.environment = environment; @@ -27,15 +33,6 @@ public class CraftWorldInfo implements WorldInfo { this.maxHeight = dimensionManager.minY() + dimensionManager.height(); } - public CraftWorldInfo(String name, UUID uuid, World.Environment environment, long seed, int minHeight, int maxHeight) { - this.name = name; - this.uuid = uuid; - this.environment = environment; - this.seed = seed; - this.minHeight = minHeight; - this.maxHeight = maxHeight; - } - @Override public String getName() { return this.name; @@ -65,4 +62,34 @@ public class CraftWorldInfo implements WorldInfo { public int getMaxHeight() { return this.maxHeight; } + + // Paper start + @Override + public org.bukkit.generator.BiomeProvider vanillaBiomeProvider() { + final net.minecraft.world.level.levelgen.RandomState randomState; + if (vanillaChunkGenerator instanceof net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator noiseBasedChunkGenerator) { + randomState = net.minecraft.world.level.levelgen.RandomState.create(noiseBasedChunkGenerator.generatorSettings().value(), + registryAccess.lookupOrThrow(net.minecraft.core.registries.Registries.NOISE), getSeed()); + } else { + randomState = net.minecraft.world.level.levelgen.RandomState.create(net.minecraft.world.level.levelgen.NoiseGeneratorSettings.dummy(), + registryAccess.lookupOrThrow(net.minecraft.core.registries.Registries.NOISE), getSeed()); + } + + final java.util.List possibleBiomes = CraftWorldInfo.this.vanillaChunkGenerator.getBiomeSource().possibleBiomes().stream() + .map(biome -> org.bukkit.craftbukkit.block.CraftBiome.minecraftHolderToBukkit(biome)) + .toList(); + return new org.bukkit.generator.BiomeProvider() { + @Override + public org.bukkit.block.Biome getBiome(final WorldInfo worldInfo, final int x, final int y, final int z) { + return org.bukkit.craftbukkit.block.CraftBiome.minecraftHolderToBukkit( + CraftWorldInfo.this.vanillaChunkGenerator.getBiomeSource().getNoiseBiome(x >> 2, y >> 2, z >> 2, randomState.sampler())); + } + + @Override + public java.util.List getBiomes(final org.bukkit.generator.WorldInfo worldInfo) { + return possibleBiomes; + } + }; + } + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomWorldChunkManager.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomWorldChunkManager.java index 0063c4c17d05a77adf81164fb9307a29860cbe12..0bac128d6faff0063b03f595b82deea78d1ae161 100644 --- a/src/main/java/org/bukkit/craftbukkit/generator/CustomWorldChunkManager.java +++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomWorldChunkManager.java @@ -31,7 +31,11 @@ public class CustomWorldChunkManager extends BiomeSource { return biomeBases; } - public CustomWorldChunkManager(WorldInfo worldInfo, BiomeProvider biomeProvider, Registry registry) { + // Paper start - add vanillaBiomeProvider + public final BiomeSource vanillaBiomeSource; + public CustomWorldChunkManager(WorldInfo worldInfo, BiomeProvider biomeProvider, Registry registry, BiomeSource vanillaBiomeSource) { + this.vanillaBiomeSource = vanillaBiomeSource; + // Paper end - add vanillaBiomeProvider this.worldInfo = worldInfo; this.biomeProvider = biomeProvider; this.registry = registry;