#619: Allow delegation of certain elements to Vanilla when using a custom ChunkGenerator

Allows delegation of caves, decorations, mobs and structures to the Vanilla generation algorithms.
Overriding these methods to return true enables that aspect of Vanilla generation, which is applied after the ChunkGenerator's custom generation.
This commit is contained in:
konsolas 2020-02-02 19:27:10 +11:00 committed by md_5
parent c2dc19d385
commit 8a66d4c7ac

View File

@ -8,25 +8,28 @@ import net.minecraft.server.BiomeManager;
import net.minecraft.server.BiomeStorage; import net.minecraft.server.BiomeStorage;
import net.minecraft.server.Block; import net.minecraft.server.Block;
import net.minecraft.server.BlockPosition; import net.minecraft.server.BlockPosition;
import net.minecraft.server.ChunkProviderGenerate;
import net.minecraft.server.ChunkProviderHell;
import net.minecraft.server.ChunkProviderTheEnd;
import net.minecraft.server.ChunkSection; import net.minecraft.server.ChunkSection;
import net.minecraft.server.DefinedStructureManager;
import net.minecraft.server.EnumCreatureType; import net.minecraft.server.EnumCreatureType;
import net.minecraft.server.GeneratorAccess; import net.minecraft.server.GeneratorAccess;
import net.minecraft.server.GeneratorSettingsDefault; import net.minecraft.server.GeneratorSettingsDefault;
import net.minecraft.server.GeneratorSettingsEnd;
import net.minecraft.server.GeneratorSettingsNether;
import net.minecraft.server.GeneratorSettingsOverworld;
import net.minecraft.server.HeightMap; import net.minecraft.server.HeightMap;
import net.minecraft.server.IChunkAccess; import net.minecraft.server.IChunkAccess;
import net.minecraft.server.ITileEntity; import net.minecraft.server.ITileEntity;
import net.minecraft.server.MobSpawnerCat;
import net.minecraft.server.MobSpawnerPatrol;
import net.minecraft.server.MobSpawnerPhantom;
import net.minecraft.server.ProtoChunk; import net.minecraft.server.ProtoChunk;
import net.minecraft.server.RegionLimitedWorldAccess; import net.minecraft.server.RegionLimitedWorldAccess;
import net.minecraft.server.StructureGenerator; import net.minecraft.server.StructureGenerator;
import net.minecraft.server.TileEntity; import net.minecraft.server.TileEntity;
import net.minecraft.server.VillageSiege;
import net.minecraft.server.World; import net.minecraft.server.World;
import net.minecraft.server.WorldChunkManager;
import net.minecraft.server.WorldGenFeatureConfiguration; import net.minecraft.server.WorldGenFeatureConfiguration;
import net.minecraft.server.WorldGenStage; import net.minecraft.server.WorldGenStage;
import net.minecraft.server.WorldGenerator;
import net.minecraft.server.WorldServer; import net.minecraft.server.WorldServer;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.block.CraftBlock; import org.bukkit.craftbukkit.block.CraftBlock;
@ -35,15 +38,11 @@ import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.generator.ChunkGenerator.ChunkData; import org.bukkit.generator.ChunkGenerator.ChunkData;
public class CustomChunkGenerator extends InternalChunkGenerator<GeneratorSettingsDefault> { public class CustomChunkGenerator extends InternalChunkGenerator<GeneratorSettingsDefault> {
private final net.minecraft.server.ChunkGenerator delegate;
private final ChunkGenerator generator; private final ChunkGenerator generator;
private final WorldServer world; private final WorldServer world;
private final long seed; private final long seed;
private final Random random; private final Random random;
private final StructureGenerator strongholdGen = WorldGenerator.STRONGHOLD;
private final MobSpawnerPhantom mobSpawnerPhantom = new MobSpawnerPhantom();
private final MobSpawnerPatrol mobSpawnerPatrol = new MobSpawnerPatrol();
private final MobSpawnerCat mobSpawnerCat = new MobSpawnerCat();
private final VillageSiege villageSiege = new VillageSiege();
private class CustomBiomeGrid implements BiomeGrid { private class CustomBiomeGrid implements BiomeGrid {
@ -78,6 +77,20 @@ public class CustomChunkGenerator extends InternalChunkGenerator<GeneratorSettin
public CustomChunkGenerator(World world, long seed, ChunkGenerator generator) { public CustomChunkGenerator(World world, long seed, ChunkGenerator generator) {
super(world, world.worldProvider.getChunkGenerator().getWorldChunkManager(), new GeneratorSettingsDefault()); super(world, world.worldProvider.getChunkGenerator().getWorldChunkManager(), new GeneratorSettingsDefault());
switch (world.getWorld().getEnvironment()) {
case NORMAL:
this.delegate = new ChunkProviderGenerate(world, world.worldProvider.getChunkGenerator().getWorldChunkManager(), new GeneratorSettingsOverworld());
break;
case NETHER:
this.delegate = new ChunkProviderHell(world, world.worldProvider.getChunkGenerator().getWorldChunkManager(), new GeneratorSettingsNether());
break;
case THE_END:
this.delegate = new ChunkProviderTheEnd(world, world.worldProvider.getChunkGenerator().getWorldChunkManager(), new GeneratorSettingsEnd());
break;
default:
throw new AssertionError("Unknown delegate for environment " + world.getWorld().getEnvironment());
}
this.world = (WorldServer) world; this.world = (WorldServer) world;
this.generator = generator; this.generator = generator;
this.seed = seed; this.seed = seed;
@ -85,8 +98,39 @@ public class CustomChunkGenerator extends InternalChunkGenerator<GeneratorSettin
this.random = new Random(seed); this.random = new Random(seed);
} }
@Override
public void createBiomes(IChunkAccess ichunkaccess) {
// Don't allow the server to override any custom biomes that have been set
}
@Override @Override
public void buildBase(RegionLimitedWorldAccess regionlimitedworldaccess, IChunkAccess ichunkaccess) { public void buildBase(RegionLimitedWorldAccess regionlimitedworldaccess, IChunkAccess ichunkaccess) {
// Disable vanilla generation
}
@Override
public <C extends WorldGenFeatureConfiguration> C getFeatureConfiguration(BiomeBase biomebase, StructureGenerator<C> structuregenerator) {
return (C) delegate.getFeatureConfiguration(biomebase, structuregenerator);
}
@Override
public WorldChunkManager getWorldChunkManager() {
return delegate.getWorldChunkManager();
}
@Override
public void storeStructures(GeneratorAccess generatoraccess, IChunkAccess ichunkaccess) {
delegate.storeStructures(generatoraccess, ichunkaccess);
}
@Override
public int getSeaLevel() {
return delegate.getSeaLevel();
}
@Override
public void createStructures(BiomeManager biomemanager, IChunkAccess ichunkaccess, net.minecraft.server.ChunkGenerator<?> chunkgenerator, DefinedStructureManager definedstructuremanager) {
// Call the bukkit ChunkGenerator before structure generation so correct biome information is available.
int x = ichunkaccess.getPos().x; int x = ichunkaccess.getPos().x;
int z = ichunkaccess.getPos().z; int z = ichunkaccess.getPos().z;
random.setSeed((long) x * 341873128712L + (long) z * 132897987541L); random.setSeed((long) x * 341873128712L + (long) z * 132897987541L);
@ -136,73 +180,94 @@ public class CustomChunkGenerator extends InternalChunkGenerator<GeneratorSettin
} }
} }
} }
if (generator.shouldGenerateStructures()) {
// Vanilla only uses biome at block 9 (see createStructures).
// We don't use BiomeGrid as another aspect of generation may try and get from a chunk somewhere else.
final BiomeBase biome = biomegrid.biome.getBiome(9 >> 2, 0, 9 >> 2);
delegate.createStructures(new BiomeManager(null, 0, null) {
@Override
public BiomeManager a(WorldChunkManager worldchunkmanager) {
return this;
}
@Override
public BiomeBase a(BlockPosition blockposition) {
return biome;
}
}, ichunkaccess, chunkgenerator, definedstructuremanager);
}
} }
@Override @Override
public void doCarving(BiomeManager biomemanager, IChunkAccess ichunkaccess, WorldGenStage.Features worldgenstage_features) { public void doCarving(BiomeManager biomemanager, IChunkAccess ichunkaccess, WorldGenStage.Features worldgenstage_features) {
if (generator.shouldGenerateCaves()) {
delegate.doCarving(biomemanager, ichunkaccess, worldgenstage_features);
}
} }
@Override @Override
public void buildNoise(GeneratorAccess generatoraccess, IChunkAccess ichunkaccess) { public void buildNoise(GeneratorAccess generatoraccess, IChunkAccess ichunkaccess) {
// Disable vanilla generation
} }
@Override @Override
public int getBaseHeight(int i, int j, HeightMap.Type heightmap_type) { public int getBaseHeight(int i, int j, HeightMap.Type heightmap_type) {
return 0; return delegate.getBaseHeight(i, j, heightmap_type);
} }
@Override @Override
public List<BiomeBase.BiomeMeta> getMobsFor(EnumCreatureType type, BlockPosition position) { public List<BiomeBase.BiomeMeta> getMobsFor(EnumCreatureType enumcreaturetype, BlockPosition blockposition) {
BiomeBase biomebase = world.getBiome(position); return delegate.getMobsFor(enumcreaturetype, blockposition);
return biomebase == null ? null : biomebase.getMobs(type);
} }
@Override @Override
public void addDecorations(RegionLimitedWorldAccess regionlimitedworldaccess) { public void addDecorations(RegionLimitedWorldAccess regionlimitedworldaccess) {
if (generator.shouldGenerateDecorations()) {
delegate.addDecorations(regionlimitedworldaccess);
}
} }
@Override @Override
public void addMobs(RegionLimitedWorldAccess regionlimitedworldaccess) { public void addMobs(RegionLimitedWorldAccess regionlimitedworldaccess) {
if (generator.shouldGenerateMobs()) {
delegate.addMobs(regionlimitedworldaccess);
}
} }
@Override @Override
public BlockPosition findNearestMapFeature(World world, String type, BlockPosition position, int i, boolean flag) { public BlockPosition findNearestMapFeature(World world, String s, BlockPosition blockposition, int i, boolean flag) {
return "Stronghold".equals(type) && this.strongholdGen != null ? this.strongholdGen.getNearestGeneratedFeature(world, this, position, i, flag) : null; return delegate.findNearestMapFeature(world, s, blockposition, i, flag);
} }
@Override @Override
public GeneratorSettingsDefault getSettings() { public GeneratorSettingsDefault getSettings() {
return settings; return delegate.getSettings();
} }
@Override @Override
public void doMobSpawning(WorldServer worldserver, boolean flag, boolean flag1) { public void doMobSpawning(WorldServer worldserver, boolean flag, boolean flag1) {
if (worldserver.getWorldProvider().isOverworld()) { delegate.doMobSpawning(worldserver, flag, flag1);
this.mobSpawnerPhantom.a(worldserver, flag, flag1);
this.mobSpawnerPatrol.a(worldserver, flag, flag1);
this.mobSpawnerCat.a(worldserver, flag, flag1);
this.villageSiege.a(worldserver, flag, flag1);
}
} }
@Override @Override
public boolean canSpawnStructure(BiomeBase biomebase, StructureGenerator<? extends WorldGenFeatureConfiguration> structuregenerator) { public boolean canSpawnStructure(BiomeBase biomebase, StructureGenerator<? extends WorldGenFeatureConfiguration> structuregenerator) {
return biomebase.a(structuregenerator); return delegate.canSpawnStructure(biomebase, structuregenerator);
} }
@Override @Override
public long getSeed() { public long getSeed() {
return seed; return delegate.getSeed();
} }
@Override @Override
public int getSpawnHeight() { public int getSpawnHeight() {
return world.getSeaLevel() + 1; return delegate.getSpawnHeight();
} }
@Override @Override
public int getGenerationDepth() { public int getGenerationDepth() {
return world.getHeight(); return delegate.getGenerationDepth();
} }
} }