252 lines
17 KiB
Java
252 lines
17 KiB
Java
package net.minecraft.world.level.levelgen.feature;
|
|
|
|
import com.mojang.serialization.Codec;
|
|
import com.mojang.serialization.MapCodec;
|
|
import java.util.Optional;
|
|
import java.util.function.Function;
|
|
import java.util.function.Predicate;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.core.Registry;
|
|
import net.minecraft.core.registries.BuiltInRegistries;
|
|
import net.minecraft.tags.BlockTags;
|
|
import net.minecraft.tags.TagKey;
|
|
import net.minecraft.util.RandomSource;
|
|
import net.minecraft.world.level.LevelSimulatedReader;
|
|
import net.minecraft.world.level.LevelWriter;
|
|
import net.minecraft.world.level.WorldGenLevel;
|
|
import net.minecraft.world.level.block.Block;
|
|
import net.minecraft.world.level.block.state.BlockBehaviour;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.chunk.ChunkGenerator;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.BlockColumnConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.BlockPileConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.BlockStateConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.ColumnFeatureConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.CountConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.DeltaFeatureConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.DiskConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.DripstoneClusterConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.EndGatewayConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.FallenTreeConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.GeodeConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.HugeMushroomFeatureConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.LargeDripstoneConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.LayerConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.MultifaceGrowthConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.NetherForestVegetationConfig;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.PointedDripstoneConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.ProbabilityFeatureConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.RandomBooleanFeatureConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.RandomFeatureConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.RandomPatchConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.ReplaceBlockConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.ReplaceSphereConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.RootSystemConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.SculkPatchConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.SimpleBlockConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.SimpleRandomFeatureConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.SpikeConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.SpringConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.TreeConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.TwistingVinesConfig;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.UnderwaterMagmaConfiguration;
|
|
import net.minecraft.world.level.levelgen.feature.configurations.VegetationPatchConfiguration;
|
|
|
|
public abstract class Feature<FC extends FeatureConfiguration> {
|
|
public static final Feature<NoneFeatureConfiguration> NO_OP = register("no_op", new NoOpFeature(NoneFeatureConfiguration.CODEC));
|
|
public static final Feature<TreeConfiguration> TREE = register("tree", new TreeFeature(TreeConfiguration.CODEC));
|
|
public static final Feature<FallenTreeConfiguration> FALLEN_TREE = register("fallen_tree", new FallenTreeFeature(FallenTreeConfiguration.CODEC));
|
|
public static final Feature<RandomPatchConfiguration> FLOWER = register("flower", new RandomPatchFeature(RandomPatchConfiguration.CODEC));
|
|
public static final Feature<RandomPatchConfiguration> NO_BONEMEAL_FLOWER = register(
|
|
"no_bonemeal_flower", new RandomPatchFeature(RandomPatchConfiguration.CODEC)
|
|
);
|
|
public static final Feature<RandomPatchConfiguration> RANDOM_PATCH = register("random_patch", new RandomPatchFeature(RandomPatchConfiguration.CODEC));
|
|
public static final Feature<BlockPileConfiguration> BLOCK_PILE = register("block_pile", new BlockPileFeature(BlockPileConfiguration.CODEC));
|
|
public static final Feature<SpringConfiguration> SPRING = register("spring_feature", new SpringFeature(SpringConfiguration.CODEC));
|
|
public static final Feature<NoneFeatureConfiguration> CHORUS_PLANT = register("chorus_plant", new ChorusPlantFeature(NoneFeatureConfiguration.CODEC));
|
|
public static final Feature<ReplaceBlockConfiguration> REPLACE_SINGLE_BLOCK = register(
|
|
"replace_single_block", new ReplaceBlockFeature(ReplaceBlockConfiguration.CODEC)
|
|
);
|
|
public static final Feature<NoneFeatureConfiguration> VOID_START_PLATFORM = register(
|
|
"void_start_platform", new VoidStartPlatformFeature(NoneFeatureConfiguration.CODEC)
|
|
);
|
|
public static final Feature<NoneFeatureConfiguration> DESERT_WELL = register("desert_well", new DesertWellFeature(NoneFeatureConfiguration.CODEC));
|
|
public static final Feature<FossilFeatureConfiguration> FOSSIL = register("fossil", new FossilFeature(FossilFeatureConfiguration.CODEC));
|
|
public static final Feature<HugeMushroomFeatureConfiguration> HUGE_RED_MUSHROOM = register(
|
|
"huge_red_mushroom", new HugeRedMushroomFeature(HugeMushroomFeatureConfiguration.CODEC)
|
|
);
|
|
public static final Feature<HugeMushroomFeatureConfiguration> HUGE_BROWN_MUSHROOM = register(
|
|
"huge_brown_mushroom", new HugeBrownMushroomFeature(HugeMushroomFeatureConfiguration.CODEC)
|
|
);
|
|
public static final Feature<NoneFeatureConfiguration> ICE_SPIKE = register("ice_spike", new IceSpikeFeature(NoneFeatureConfiguration.CODEC));
|
|
public static final Feature<NoneFeatureConfiguration> GLOWSTONE_BLOB = register("glowstone_blob", new GlowstoneFeature(NoneFeatureConfiguration.CODEC));
|
|
public static final Feature<NoneFeatureConfiguration> FREEZE_TOP_LAYER = register("freeze_top_layer", new SnowAndFreezeFeature(NoneFeatureConfiguration.CODEC));
|
|
public static final Feature<NoneFeatureConfiguration> VINES = register("vines", new VinesFeature(NoneFeatureConfiguration.CODEC));
|
|
public static final Feature<BlockColumnConfiguration> BLOCK_COLUMN = register("block_column", new BlockColumnFeature(BlockColumnConfiguration.CODEC));
|
|
public static final Feature<VegetationPatchConfiguration> VEGETATION_PATCH = register(
|
|
"vegetation_patch", new VegetationPatchFeature(VegetationPatchConfiguration.CODEC)
|
|
);
|
|
public static final Feature<VegetationPatchConfiguration> WATERLOGGED_VEGETATION_PATCH = register(
|
|
"waterlogged_vegetation_patch", new WaterloggedVegetationPatchFeature(VegetationPatchConfiguration.CODEC)
|
|
);
|
|
public static final Feature<RootSystemConfiguration> ROOT_SYSTEM = register("root_system", new RootSystemFeature(RootSystemConfiguration.CODEC));
|
|
public static final Feature<MultifaceGrowthConfiguration> MULTIFACE_GROWTH = register(
|
|
"multiface_growth", new MultifaceGrowthFeature(MultifaceGrowthConfiguration.CODEC)
|
|
);
|
|
public static final Feature<UnderwaterMagmaConfiguration> UNDERWATER_MAGMA = register(
|
|
"underwater_magma", new UnderwaterMagmaFeature(UnderwaterMagmaConfiguration.CODEC)
|
|
);
|
|
public static final Feature<NoneFeatureConfiguration> MONSTER_ROOM = register("monster_room", new MonsterRoomFeature(NoneFeatureConfiguration.CODEC));
|
|
public static final Feature<NoneFeatureConfiguration> BLUE_ICE = register("blue_ice", new BlueIceFeature(NoneFeatureConfiguration.CODEC));
|
|
public static final Feature<BlockStateConfiguration> ICEBERG = register("iceberg", new IcebergFeature(BlockStateConfiguration.CODEC));
|
|
public static final Feature<BlockStateConfiguration> FOREST_ROCK = register("forest_rock", new BlockBlobFeature(BlockStateConfiguration.CODEC));
|
|
public static final Feature<DiskConfiguration> DISK = register("disk", new DiskFeature(DiskConfiguration.CODEC));
|
|
public static final Feature<LakeFeature.Configuration> LAKE = register("lake", new LakeFeature(LakeFeature.Configuration.CODEC));
|
|
public static final Feature<OreConfiguration> ORE = register("ore", new OreFeature(OreConfiguration.CODEC));
|
|
public static final Feature<NoneFeatureConfiguration> END_PLATFORM = register("end_platform", new EndPlatformFeature(NoneFeatureConfiguration.CODEC));
|
|
public static final Feature<SpikeConfiguration> END_SPIKE = register("end_spike", new SpikeFeature(SpikeConfiguration.CODEC));
|
|
public static final Feature<NoneFeatureConfiguration> END_ISLAND = register("end_island", new EndIslandFeature(NoneFeatureConfiguration.CODEC));
|
|
public static final Feature<EndGatewayConfiguration> END_GATEWAY = register("end_gateway", new EndGatewayFeature(EndGatewayConfiguration.CODEC));
|
|
public static final SeagrassFeature SEAGRASS = register("seagrass", new SeagrassFeature(ProbabilityFeatureConfiguration.CODEC));
|
|
public static final Feature<NoneFeatureConfiguration> KELP = register("kelp", new KelpFeature(NoneFeatureConfiguration.CODEC));
|
|
public static final Feature<NoneFeatureConfiguration> CORAL_TREE = register("coral_tree", new CoralTreeFeature(NoneFeatureConfiguration.CODEC));
|
|
public static final Feature<NoneFeatureConfiguration> CORAL_MUSHROOM = register("coral_mushroom", new CoralMushroomFeature(NoneFeatureConfiguration.CODEC));
|
|
public static final Feature<NoneFeatureConfiguration> CORAL_CLAW = register("coral_claw", new CoralClawFeature(NoneFeatureConfiguration.CODEC));
|
|
public static final Feature<CountConfiguration> SEA_PICKLE = register("sea_pickle", new SeaPickleFeature(CountConfiguration.CODEC));
|
|
public static final Feature<SimpleBlockConfiguration> SIMPLE_BLOCK = register("simple_block", new SimpleBlockFeature(SimpleBlockConfiguration.CODEC));
|
|
public static final Feature<ProbabilityFeatureConfiguration> BAMBOO = register("bamboo", new BambooFeature(ProbabilityFeatureConfiguration.CODEC));
|
|
public static final Feature<HugeFungusConfiguration> HUGE_FUNGUS = register("huge_fungus", new HugeFungusFeature(HugeFungusConfiguration.CODEC));
|
|
public static final Feature<NetherForestVegetationConfig> NETHER_FOREST_VEGETATION = register(
|
|
"nether_forest_vegetation", new NetherForestVegetationFeature(NetherForestVegetationConfig.CODEC)
|
|
);
|
|
public static final Feature<NoneFeatureConfiguration> WEEPING_VINES = register("weeping_vines", new WeepingVinesFeature(NoneFeatureConfiguration.CODEC));
|
|
public static final Feature<TwistingVinesConfig> TWISTING_VINES = register("twisting_vines", new TwistingVinesFeature(TwistingVinesConfig.CODEC));
|
|
public static final Feature<ColumnFeatureConfiguration> BASALT_COLUMNS = register("basalt_columns", new BasaltColumnsFeature(ColumnFeatureConfiguration.CODEC));
|
|
public static final Feature<DeltaFeatureConfiguration> DELTA_FEATURE = register("delta_feature", new DeltaFeature(DeltaFeatureConfiguration.CODEC));
|
|
public static final Feature<ReplaceSphereConfiguration> REPLACE_BLOBS = register(
|
|
"netherrack_replace_blobs", new ReplaceBlobsFeature(ReplaceSphereConfiguration.CODEC)
|
|
);
|
|
public static final Feature<LayerConfiguration> FILL_LAYER = register("fill_layer", new FillLayerFeature(LayerConfiguration.CODEC));
|
|
public static final BonusChestFeature BONUS_CHEST = register("bonus_chest", new BonusChestFeature(NoneFeatureConfiguration.CODEC));
|
|
public static final Feature<NoneFeatureConfiguration> BASALT_PILLAR = register("basalt_pillar", new BasaltPillarFeature(NoneFeatureConfiguration.CODEC));
|
|
public static final Feature<OreConfiguration> SCATTERED_ORE = register("scattered_ore", new ScatteredOreFeature(OreConfiguration.CODEC));
|
|
public static final Feature<RandomFeatureConfiguration> RANDOM_SELECTOR = register(
|
|
"random_selector", new RandomSelectorFeature(RandomFeatureConfiguration.CODEC)
|
|
);
|
|
public static final Feature<SimpleRandomFeatureConfiguration> SIMPLE_RANDOM_SELECTOR = register(
|
|
"simple_random_selector", new SimpleRandomSelectorFeature(SimpleRandomFeatureConfiguration.CODEC)
|
|
);
|
|
public static final Feature<RandomBooleanFeatureConfiguration> RANDOM_BOOLEAN_SELECTOR = register(
|
|
"random_boolean_selector", new RandomBooleanSelectorFeature(RandomBooleanFeatureConfiguration.CODEC)
|
|
);
|
|
public static final Feature<GeodeConfiguration> GEODE = register("geode", new GeodeFeature(GeodeConfiguration.CODEC));
|
|
public static final Feature<DripstoneClusterConfiguration> DRIPSTONE_CLUSTER = register(
|
|
"dripstone_cluster", new DripstoneClusterFeature(DripstoneClusterConfiguration.CODEC)
|
|
);
|
|
public static final Feature<LargeDripstoneConfiguration> LARGE_DRIPSTONE = register(
|
|
"large_dripstone", new LargeDripstoneFeature(LargeDripstoneConfiguration.CODEC)
|
|
);
|
|
public static final Feature<PointedDripstoneConfiguration> POINTED_DRIPSTONE = register(
|
|
"pointed_dripstone", new PointedDripstoneFeature(PointedDripstoneConfiguration.CODEC)
|
|
);
|
|
public static final Feature<SculkPatchConfiguration> SCULK_PATCH = register("sculk_patch", new SculkPatchFeature(SculkPatchConfiguration.CODEC));
|
|
private final MapCodec<ConfiguredFeature<FC, Feature<FC>>> configuredCodec;
|
|
|
|
private static <C extends FeatureConfiguration, F extends Feature<C>> F register(String key, F value) {
|
|
return Registry.register(BuiltInRegistries.FEATURE, key, value);
|
|
}
|
|
|
|
public Feature(Codec<FC> codec) {
|
|
this.configuredCodec = codec.fieldOf("config").xmap(featureConfiguration -> new ConfiguredFeature<>(this, featureConfiguration), ConfiguredFeature::config);
|
|
}
|
|
|
|
public MapCodec<ConfiguredFeature<FC, Feature<FC>>> configuredCodec() {
|
|
return this.configuredCodec;
|
|
}
|
|
|
|
protected void setBlock(LevelWriter level, BlockPos pos, BlockState state) {
|
|
level.setBlock(pos, state, 3);
|
|
}
|
|
|
|
public static Predicate<BlockState> isReplaceable(TagKey<Block> blockTag) {
|
|
return blockState -> !blockState.is(blockTag);
|
|
}
|
|
|
|
protected void safeSetBlock(WorldGenLevel level, BlockPos pos, BlockState state, Predicate<BlockState> oldState) {
|
|
if (oldState.test(level.getBlockState(pos))) {
|
|
level.setBlock(pos, state, 2);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Places the given feature at the given location.
|
|
* During world generation, features are provided with a 3x3 region of chunks, centered on the chunk being generated, that they can safely generate into.
|
|
*
|
|
* @param context A context object with a reference to the level and the position the feature is being placed at
|
|
*/
|
|
public abstract boolean place(FeaturePlaceContext<FC> context);
|
|
|
|
public boolean place(FC config, WorldGenLevel level, ChunkGenerator chunkGenerator, RandomSource random, BlockPos origin) {
|
|
return level.ensureCanWrite(origin) ? this.place(new FeaturePlaceContext<>(Optional.empty(), level, chunkGenerator, random, origin, config)) : false;
|
|
}
|
|
|
|
protected static boolean isStone(BlockState state) {
|
|
return state.is(BlockTags.BASE_STONE_OVERWORLD);
|
|
}
|
|
|
|
public static boolean isDirt(BlockState state) {
|
|
return state.is(BlockTags.DIRT);
|
|
}
|
|
|
|
public static boolean isGrassOrDirt(LevelSimulatedReader level, BlockPos pos) {
|
|
return level.isStateAtPosition(pos, Feature::isDirt);
|
|
}
|
|
|
|
/**
|
|
* @return {@code true} if any of the six adjacent blocks to the block at {@code pos} return {@code true} to the given filter.
|
|
*
|
|
* @param adjacentStateAccessor An accessor for the adjacent blocks. Essentially {@code level::getBlockState}.
|
|
*/
|
|
public static boolean checkNeighbors(Function<BlockPos, BlockState> adjacentStateAccessor, BlockPos pos, Predicate<BlockState> filter) {
|
|
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
|
|
|
|
for (Direction direction : Direction.values()) {
|
|
mutableBlockPos.setWithOffset(pos, direction);
|
|
if (filter.test((BlockState)adjacentStateAccessor.apply(mutableBlockPos))) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @return {@code true} if any of the six adjacent blocks to the block at {@code pos} are air.
|
|
*
|
|
* @param adjacentStateAccessor An accessor for the adjacent blocks. Essentially {@code level::getBlockState}.
|
|
*/
|
|
public static boolean isAdjacentToAir(Function<BlockPos, BlockState> adjacentStateAccessor, BlockPos pos) {
|
|
return checkNeighbors(adjacentStateAccessor, pos, BlockBehaviour.BlockStateBase::isAir);
|
|
}
|
|
|
|
/**
|
|
* If the above two blocks are not air, marks them for post-processing.
|
|
* This is used to prevent floating grass during the generation of features that carve blocks out of the terrain, after other plant-like blocks have generated (such as lake features).
|
|
*/
|
|
protected void markAboveForPostProcessing(WorldGenLevel level, BlockPos basePos) {
|
|
BlockPos.MutableBlockPos mutableBlockPos = basePos.mutable();
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
mutableBlockPos.move(Direction.UP);
|
|
if (level.getBlockState(mutableBlockPos).isAir()) {
|
|
return;
|
|
}
|
|
|
|
level.getChunk(mutableBlockPos).markPosForPostprocessing(mutableBlockPos);
|
|
}
|
|
}
|
|
}
|