Fix incorrect generator settings being used for Nether and End dimensions

master
Chimney Swift 2020-10-04 23:29:19 +10:00
parent ef415dcf57
commit 3632491a56
1 changed files with 65 additions and 14 deletions

View File

@ -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);