本篇教程的视频

(待发布)

本篇教程的源代码

(待发布)

本篇教程目标

  • 理解原版花的构造特征和放置特征
  • 学会自己编写花的构造特征和放置特征

查看源代码

像花这种小植物,在游戏中是以一种叫随机斑块的形式出现的,也就是一些小植被,它也是地物的一种,所以它们也具有构造特征和放置特征

构造特征

构造特征我们可以在VegetationConfiguredFeatures类中找到

1
2
3
4
5
6
7
8
public static final RegistryKey<ConfiguredFeature<?, ?>> FLOWER_DEFAULT = ConfiguredFeatures.of("flower_default");
public static final RegistryKey<ConfiguredFeature<?, ?>> FLOWER_FLOWER_FOREST = ConfiguredFeatures.of("flower_flower_forest");
public static final RegistryKey<ConfiguredFeature<?, ?>> FLOWER_SWAMP = ConfiguredFeatures.of("flower_swamp");
public static final RegistryKey<ConfiguredFeature<?, ?>> FLOWER_PLAIN = ConfiguredFeatures.of("flower_plain");
public static final RegistryKey<ConfiguredFeature<?, ?>> FLOWER_MEADOW = ConfiguredFeatures.of("flower_meadow");
public static final RegistryKey<ConfiguredFeature<?, ?>> FLOWER_CHERRY = ConfiguredFeatures.of("flower_cherry");
public static final RegistryKey<ConfiguredFeature<?, ?>> FOREST_FLOWERS = ConfiguredFeatures.of("forest_flowers");
...

光是涉及的,就有很多种

默认的是FLOWER_DEFAULT

1
2
3
4
5
6
7
8
ConfiguredFeatures.register(
featureRegisterable,
FLOWER_DEFAULT,
Feature.FLOWER,
createRandomPatchFeatureConfig(
new WeightedBlockStateProvider(DataPool.<BlockState>builder().add(Blocks.POPPY.getDefaultState(), 2).add(Blocks.DANDELION.getDefaultState(), 1)), 64
)
);

在下面的bootstrap方法中,我们可以看到蒲公英的构造特征

其中的createRandomPatchFeatureConfig方法,就是创建一个随机斑块

第一个参数是方块的提供器,第二个是尝试生成的次数,以区块为单位

当然,我们在写时候,和这个并不完全一样

放置特征

放置特征我们可以在VegetationPlacedFeatures类中找到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static final RegistryKey<PlacedFeature> FLOWER_DEFAULT = PlacedFeatures.of("flower_default");
...
// 下面三段在bootstrap方法中
RegistryEntryLookup<ConfiguredFeature<?, ?>> registryEntryLookup = featureRegisterable.getRegistryLookup(RegistryKeys.CONFIGURED_FEATURE);

RegistryEntry<ConfiguredFeature<?, ?>> registryEntry20 = registryEntryLookup.getOrThrow(VegetationConfiguredFeatures.FLOWER_DEFAULT);

PlacedFeatures.register(
featureRegisterable,
FLOWER_DEFAULT,
registryEntry20,
RarityFilterPlacementModifier.of(32),
SquarePlacementModifier.of(),
PlacedFeatures.MOTION_BLOCKING_HEIGHTMAP,
BiomePlacementModifier.of()
);

同样的,它也是差不多的,一个注册键,bootstrap方法中注册

RarityFilterPlacementModifier.of方法是生成几率,这个就是百分数了

SquarePlacementModifier.of()是生成方式,这个就是方块为单位了,应该指按照一个方形平面放置(联想一下笔刷

PlacedFeatures.MOTION_BLOCKING_HEIGHTMAP是高度图,按照高度来放置

BiomePlacementModifier.of()是生物群系,按照生物群系来放置

这些其实就是在世界生成时,尝试生成的一些方法规则

注册花的世界生成

注册构造特征

我们回到之前的ModConfiguredFeatures类中

首先写一个注册键

1
public static final RegistryKey<ConfiguredFeature<?, ?>> SIMPLE_FLOWER_KEY = of("simple_flower");

之后在bootstrap方法中注册构造特征

1
2
3
4
ConfiguredFeatures.register(featureRegisterable, SIMPLE_FLOWER_KEY, Feature.FLOWER,
new RandomPatchFeatureConfig(20, 4, 3,
PlacedFeatures.createEntry(Feature.SIMPLE_BLOCK,
new SimpleBlockFeatureConfig(BlockStateProvider.of(ModBlocks.SIMPLE_FLOWER)))));

这里的随机斑块方法,我们就直接实例化RandomPatchFeatureConfig

第一个参数是尝试生成的次数,第二个参数是xz方向上拓展的距离,第三个参数是y方向上拓展的距离,第四个参数是注册表项

注册表项提供一个简单方块特征和它的配置参数

注册放置特征

我们回到之前的ModPlacedFeatures类中

同样的一个注册键

1
public static final RegistryKey<PlacedFeature> SIMPLE_FLOWER_PLACED_KEY = ModPlacedFeatures.of("simple_flower_placed");

之后在bootstrap方法中注册放置特征

1
2
3
4
PlacedFeatures.register(featureRegisterable, SIMPLE_FLOWER_PLACED_KEY,
registryEntryLookup.getOrThrow(ModConfiguredFeatures.SIMPLE_FLOWER_KEY),
RarityFilterPlacementModifier.of(4), SquarePlacementModifier.of(),
PlacedFeatures.MOTION_BLOCKING_HEIGHTMAP, BiomePlacementModifier.of());

这里的写法和原版的差不多,可以仿照原版的方法来写

花的世界生成器

接下来我们还要创建一个ModFlowerGeneration

1
2
3
public class ModFlowerGeneration {

}

和前面写树一样,我们要用Fabric API来让花生成在某一个生物群系

1
2
3
4
public static void registerFlowers() {
BiomeModifications.addFeature(BiomeSelectors.includeByKey(BiomeKeys.PLAINS, BiomeKeys.FOREST),
GenerationStep.Feature.VEGETAL_DECORATION, ModPlacedFeatures.SIMPLE_FLOWER_PLACED_KEY);
}

这里的BiomeSelectors.includeByKey方法,就是让花生成在指定的生物群系中,和前面讲到树的时候一样

registerFlowers方法要在ModWorldGeneration类中调用

1
ModFlowerGeneration.registerFlowers();

测试

在此之后,我们就可以跑数据生成,然后得到对应的构造json文件和放置json文件,之后我们就可以进入游戏进行测试了