package net.minecraft.world.level.levelgen; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.stream.Stream; import net.minecraft.Util; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.HolderLookup; import net.minecraft.core.HolderSet; import net.minecraft.server.level.WorldGenRegion; import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.NoiseColumn; import net.minecraft.world.level.StructureManager; import net.minecraft.world.level.biome.BiomeManager; import net.minecraft.world.level.biome.FixedBiomeSource; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGeneratorStructureState; import net.minecraft.world.level.levelgen.blending.Blender; import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings; import net.minecraft.world.level.levelgen.structure.StructureSet; public class FlatLevelSource extends ChunkGenerator { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( instance -> instance.group(FlatLevelGeneratorSettings.CODEC.fieldOf("settings").forGetter(FlatLevelSource::settings)) .apply(instance, instance.stable(FlatLevelSource::new)) ); private final FlatLevelGeneratorSettings settings; public FlatLevelSource(FlatLevelGeneratorSettings settings) { super(new FixedBiomeSource(settings.getBiome()), Util.memoize(settings::adjustGenerationSettings)); this.settings = settings; } @Override public ChunkGeneratorStructureState createState(HolderLookup structureSetLookup, RandomState randomState, long seed) { Stream> stream = (Stream>)this.settings .structureOverrides() .map(HolderSet::stream) .orElseGet(() -> structureSetLookup.listElements().map(reference -> reference)); return ChunkGeneratorStructureState.createForFlat(randomState, seed, this.biomeSource, stream); } @Override protected MapCodec codec() { return CODEC; } public FlatLevelGeneratorSettings settings() { return this.settings; } @Override public void buildSurface(WorldGenRegion level, StructureManager structureManager, RandomState random, ChunkAccess chunk) { } @Override public int getSpawnHeight(LevelHeightAccessor level) { return level.getMinY() + Math.min(level.getHeight(), this.settings.getLayers().size()); } @Override public CompletableFuture fillFromNoise(Blender blender, RandomState randomState, StructureManager structureManager, ChunkAccess chunk) { List list = this.settings.getLayers(); BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); Heightmap heightmap = chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.OCEAN_FLOOR_WG); Heightmap heightmap2 = chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE_WG); for (int i = 0; i < Math.min(chunk.getHeight(), list.size()); i++) { BlockState blockState = (BlockState)list.get(i); if (blockState != null) { int j = chunk.getMinY() + i; for (int k = 0; k < 16; k++) { for (int l = 0; l < 16; l++) { chunk.setBlockState(mutableBlockPos.set(k, j, l), blockState); heightmap.update(k, j, l, blockState); heightmap2.update(k, j, l, blockState); } } } } return CompletableFuture.completedFuture(chunk); } @Override public int getBaseHeight(int x, int z, Heightmap.Types type, LevelHeightAccessor level, RandomState random) { List list = this.settings.getLayers(); for (int i = Math.min(list.size() - 1, level.getMaxY()); i >= 0; i--) { BlockState blockState = (BlockState)list.get(i); if (blockState != null && type.isOpaque().test(blockState)) { return level.getMinY() + i + 1; } } return level.getMinY(); } @Override public NoiseColumn getBaseColumn(int x, int z, LevelHeightAccessor height, RandomState random) { return new NoiseColumn( height.getMinY(), (BlockState[])this.settings .getLayers() .stream() .limit(height.getHeight()) .map(blockState -> blockState == null ? Blocks.AIR.defaultBlockState() : blockState) .toArray(BlockState[]::new) ); } @Override public void addDebugScreenInfo(List info, RandomState random, BlockPos pos) { } @Override public void applyCarvers(WorldGenRegion level, long seed, RandomState random, BiomeManager biomeManager, StructureManager structureManager, ChunkAccess chunk) { } @Override public void spawnOriginalMobs(WorldGenRegion level) { } @Override public int getMinY() { return 0; } @Override public int getGenDepth() { return 384; } @Override public int getSeaLevel() { return -63; } }