From 3632491a565580b1e76458472f7a61d5107cd769 Mon Sep 17 00:00:00 2001 From: Chimney Swift <28179563+ChimneySwift@users.noreply.github.com> Date: Sun, 4 Oct 2020 23:29:19 +1000 Subject: [PATCH] Fix incorrect generator settings being used for Nether and End dimensions --- .../internal/WorldGeneratorImpl.java | 79 +++++++++++++++---- 1 file changed, 65 insertions(+), 14 deletions(-) diff --git a/worldgeneratorapi-impl/src/main/java/nl/rutgerkok/worldgeneratorapi/internal/WorldGeneratorImpl.java b/worldgeneratorapi-impl/src/main/java/nl/rutgerkok/worldgeneratorapi/internal/WorldGeneratorImpl.java index 09cce9d..e6d843b 100644 --- a/worldgeneratorapi-impl/src/main/java/nl/rutgerkok/worldgeneratorapi/internal/WorldGeneratorImpl.java +++ b/worldgeneratorapi-impl/src/main/java/nl/rutgerkok/worldgeneratorapi/internal/WorldGeneratorImpl.java @@ -1,14 +1,14 @@ package nl.rutgerkok.worldgeneratorapi.internal; import java.lang.reflect.Field; -import java.util.NoSuchElementException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Objects; import javax.annotation.Nullable; import org.bukkit.World; import org.bukkit.craftbukkit.v1_16_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_16_R2.generator.CustomChunkGenerator; import net.minecraft.server.v1_16_R2.BiomeBase; import net.minecraft.server.v1_16_R2.ChunkGenerator; @@ -17,6 +17,11 @@ import net.minecraft.server.v1_16_R2.GeneratorSettingBase; import net.minecraft.server.v1_16_R2.IRegistry; import net.minecraft.server.v1_16_R2.WorldChunkManager; import net.minecraft.server.v1_16_R2.WorldServer; +import net.minecraft.server.v1_16_R2.StructureSettings; +import net.minecraft.server.v1_16_R2.IBlockData; +import net.minecraft.server.v1_16_R2.MinecraftKey; +import net.minecraft.server.v1_16_R2.ResourceKey; +import net.minecraft.server.v1_16_R2.Blocks; import nl.rutgerkok.worldgeneratorapi.BaseChunkGenerator; import nl.rutgerkok.worldgeneratorapi.BaseNoiseGenerator; import nl.rutgerkok.worldgeneratorapi.BaseTerrainGenerator; @@ -33,19 +38,65 @@ final class WorldGeneratorImpl implements WorldGenerator { return GeneratorSettingBase.i(); } - private static GeneratorSettingBase extractSettings(ChunkGenerator chunkGenerator, long seed) { + private static GeneratorSettingBase createDefaultNetherSettings() { + // Equiv. to `a(e, a(new StructureSettings(false), Blocks.NETHERRACK.getBlockData(), Blocks.LAVA.getBlockData(), e.a()));` + // in GeneratorSettingsBase try { - // First, unwrap Bukkit generator if necessary - if (chunkGenerator instanceof CustomChunkGenerator) { - chunkGenerator = (ChunkGenerator) ReflectionUtil.getFieldOfType(chunkGenerator, ChunkGenerator.class) - .get(chunkGenerator); - } + Method meth1 = GeneratorSettingBase.class.getDeclaredMethod("a", StructureSettings.class, + IBlockData.class, IBlockData.class, MinecraftKey.class); + Method meth2 = GeneratorSettingBase.class.getDeclaredMethod("a", ResourceKey.class, + GeneratorSettingBase.class); - // Then, extract the settings - return (GeneratorSettingBase) ReflectionUtil.getFieldOfType(chunkGenerator, GeneratorSettingBase.class) - .get(chunkGenerator); - } catch (IllegalAccessException | IllegalArgumentException | NoSuchElementException e) { - // Get default settings + meth1.setAccessible(true); + meth2.setAccessible(true); + + StructureSettings genStronghold = new StructureSettings(false); + GeneratorSettingBase generatorSettings = (GeneratorSettingBase)meth1.invoke(null, genStronghold, + Blocks.NETHERRACK.getBlockData(), Blocks.LAVA.getBlockData(), GeneratorSettingBase.e.a()); + + return (GeneratorSettingBase)meth2.invoke(null, GeneratorSettingBase.e, generatorSettings); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + // If something goes wrong just default to Overworld Settings. + e.printStackTrace(); + return createDefaultSettings(); + } + } + + private static GeneratorSettingBase createDefaultEndSettings() { + // Equiv. to `a(f, a(new StructureSettings(false), Blocks.END_STONE.getBlockData(), Blocks.AIR.getBlockData(), f.a(), true, true));` + // in GeneratorSettingsBase + try { + Method meth1 = GeneratorSettingBase.class.getDeclaredMethod("a", StructureSettings.class, + IBlockData.class, IBlockData.class, MinecraftKey.class, boolean.class, boolean.class); + Method meth2 = GeneratorSettingBase.class.getDeclaredMethod("a", ResourceKey.class, + GeneratorSettingBase.class); + + meth1.setAccessible(true); + meth2.setAccessible(true); + + StructureSettings genStronghold = new StructureSettings(false); + GeneratorSettingBase generatorSettings = (GeneratorSettingBase)meth1.invoke(null, genStronghold, + Blocks.END_STONE.getBlockData(), Blocks.AIR.getBlockData(), GeneratorSettingBase.f.a(), true, true); + + return (GeneratorSettingBase)meth2.invoke(null, GeneratorSettingBase.f, generatorSettings); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + // If something goes wrong just default to Overworld Settings. + e.printStackTrace(); + return createDefaultSettings(); + } + } + + private static GeneratorSettingBase extractSettings(CraftWorld world) { + // Get default settings based on environment + // Not sure if there's a new way to extract the existing settings, which may be a better option, since + // ChunkGenerator has no GeneratorSettingBase fields in it (anymore?) + World.Environment env = world.getEnvironment(); + + if (env.equals(World.Environment.THE_END)) { + return createDefaultEndSettings(); + } else if (env.equals(World.Environment.NETHER)) { + return createDefaultNetherSettings(); + } else { return createDefaultSettings(); } } @@ -173,7 +224,7 @@ final class WorldGeneratorImpl implements WorldGenerator { ChunkGenerator chunkGenerator = world.getChunkProvider().getChunkGenerator(); WorldChunkManager worldChunkManager = chunkGenerator.getWorldChunkManager(); long seed = world.getSeed(); - GeneratorSettingBase settings = extractSettings(chunkGenerator, seed); + GeneratorSettingBase settings = extractSettings(world.getWorld()); InjectedChunkGenerator injected = new InjectedChunkGenerator(worldChunkManager, getBiomeRegistry(world), base, seed, settings);