本篇教程的视频

(待发布)

本篇教程的源代码

(待发布)

本篇教程目标

  • 理解原版的树的放置特征
  • 学会自己编写基本的树的放置特征

查看源代码

那么这一篇教程我们来讲树的世界生成,前面已经讲过了TreeConfiguredFeatures这个类

那么今天讲世界生成还要涉及一个TreePlacedFeatures,这个是树的放置特征,
意思就是这些树是以怎样的方式放置在世界中的

这里我们就来看看TreePlacedFeatures

1
public static final RegistryKey<PlacedFeature> OAK_CHECKED = PlacedFeatures.of("oak_checked");

还是以橡木相关的内容为例,这里有一个放置特征的注册键

PlacedFeatures.of方法同样是一个公共方法,但我们使用时还得带上模组的命名空间

再往下翻就能看到一个bootstrap方法,那还是用来数据生成的

1
2
3
public static void bootstrap(Registerable<PlacedFeature> featureRegisterable) {
...
}

这里面我们就看和橡木相关的内容

1
2
3
4
5
RegistryEntryLookup<ConfiguredFeature<?, ?>> registryEntryLookup = featureRegisterable.getRegistryLookup(RegistryKeys.CONFIGURED_FEATURE);

RegistryEntry<ConfiguredFeature<?, ?>> registryEntry3 = registryEntryLookup.getOrThrow(TreeConfiguredFeatures.OAK);

PlacedFeatures.register(featureRegisterable, OAK_CHECKED, registryEntry3, PlacedFeatures.wouldSurvive(Blocks.OAK_SAPLING));

首先先看第一个registryEntryLookup,这个方法就是获取注册键为RegistryKeys.CONFIGURED_FEATURE的注册表

然后registryEntry3则是获取注册表中,注册键为TreeConfiguredFeatures.OAK的注册表条目

最后,用PlacedFeatures.register方法则是注册一个放置特征

PlacedFeatures.register方法有三个参数,第一个是注册键,第二个是注册表条目,第三个是放置条件

不过我们实际写的时候,第三个参数是直接用植被的放置特征相关的方法来写的

这里我多提一嘴,按照上面的注册键继续深挖下去,我们就能看到它在VegetationConfiguredFeaturesbootstrap方法中,
也被调用了

植被这一大块也是有自己的构造特征放置特征的,稍微捋一下,植被是很多种植物组合在一起形成的,
比如繁花森林黑森林等等,而我们写的单个的树或者其他东西,它是植被中的一部分,所以深挖下去还能了解更多东西,
不过我们这里就不展开讲了,感兴趣的同学可以自行研究

注册世界生成

放置特征

这里我们来创建ModPlacedFeatures类,用来注册放置特征

1
2
3
public class ModPlacedFeatures {

}

同样的,我们还是先写一个注册键

1
2
3
4
5
public static final RegistryKey<PlacedFeature> ICE_ETHER_TREE_PLACED_KEY = ModPlacedFeatures.of("ice_ether_tree_placed");

public static RegistryKey<PlacedFeature> of(String id) {
return RegistryKey.of(RegistryKeys.PLACED_FEATURE, new Identifier(TutorialModRe.MOD_ID, id));
}

同样的,of方法也是用了原版的方法,但加上了模组的命名空间

当然,为了与前面的构造特征有所区分,我们这里注册名上可以加上一个placed

然后就是写一个bootstrap方法

1
2
3
public static void bootstrap(Registerable<PlacedFeature> featureRegisterable) {

}

参数上与原版的bootstrap方法一致

1
RegistryEntryLookup<ConfiguredFeature<?, ?>> registryEntryLookup = featureRegisterable.getRegistryLookup(RegistryKeys.CONFIGURED_FEATURE);

获取注册键为RegistryKeys.CONFIGURED_FEATURE的注册表

1
2
3
4
5
6
PlacedFeatures.register(featureRegisterable, ICE_ETHER_TREE_PLACED_KEY,
registryEntryLookup.getOrThrow(ModConfiguredFeatures.ICE_ETHER_TREE_KEY),
VegetationPlacedFeatures.treeModifiersWithWouldSurvive(
PlacedFeatures.createCountExtraModifier(2, 0.1f, 2),
ModBlocks.ICE_ETHER_TREE_SAPLING
));

然后我们就直接用PlacedFeatures.register来注册放置特征

第一个参数是注册键,第二个参数是注册表条目,第三个参数是放置条件

这里第三个参数我们用了VegetationPlacedFeatures.treeModifiersWithWouldSurvive方法,
PlacedFeatures.createCountExtraModifier则是用来修改生成的数量,以区块为单位

第一个参数是一个区块中基本的生成数量,第二个是额外生成的概率,第三个是额外生成的数量

后面就传入我们先前写的树苗方块即可

树的生成器

接下来我们还要写树的世界生成器,与前面写的树苗生成器不同,它是指定我们的树在哪些生物群系中生成

原版的地物配置已经写好了,所以这里我们要用Fabric API来注册

我们创建一个ModTreeGeneration

1
2
3
public class ModTreeGeneration {

}

然后在里面写一个registerTrees方法

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

在这里面我们用BiomeModifications.addFeature方法来添加一个生物群系特征,就是指定我们的树生成在哪些生物群系中

当然这种做法是会影响原版已经配置的地物生成,不过关系不大

第一个参数是生物群系选择器,这里我们用了BiomeSelectors.includeByKey方法,我们选择了平原森林

第二个参数是生成阶段,这里我们用了GenerationStep.Feature.VEGETAL_DECORATION,也就是在植被生成阶段,加入我们的树

第三个参数则是我们的放置特征的注册键

注册世界生成

接下来我们再写一个ModWorldGeneration类,注册世界生成

1
2
3
4
5
public class ModWorldGeneration {
public static void registerWorldGeneration() {
ModTreeGeneration.registerTrees();
}
}

里面写一个registerWorldGeneration方法,调用我们先前写的registerTrees方法

这个方法还要在主类调用

1
ModWorldGeneration.registerWorldGeneration();

数据生成

和前面一样,我们要配置数据生成

TutorialModReDataGenerator

在模组的数据生成主类中的buildRegistry方法下,添加一行代码

1
registryBuilder.addRegistry(RegistryKeys.PLACED_FEATURE, ModPlacedFeatures::bootstrap);

调用ModPlacedFeatures中的bootstrap方法

ModWorldGenerator

ModWorldGenerator类中的configure方法中,我们也要将放置特征的注册键加入

1
entries.addAll(wrapperLookup.getWrapperOrThrow(RegistryKeys.PLACED_FEATURE));

测试

随后我们就可以进行数据生成,同样它会在数据文件夹中的world_gen/placed_feature下生成一个树的放置特征文件

然后我们就可以在游戏中测试了,在平原和森林中,我们就可以看到我们的树了