糖果sweet
本帖最后由 糖果sweet 于 2022-11-26 17:29 编辑
简单矿物生成   by:糖果 如有问题请及时指出,谢谢阅读!



游戏里的世界地壳蕴藏着大量矿物,如煤矿石,1.17前矿脉还并未加入,但有团簇,他们是以团簇的形式生成的,一个团簇聚合着几个矿石。那么模组中的矿物应该如何加入到世界中去呢?本教程将以羊毛为例子教你添加矿物地形特征,以及简单的生成参数。

地形特征
地形特征会在世界中生成,上述的团簇便是一种地形特征,在源码中类路径为 net.minecraft.world.gen.feature.Feature,这个类中声明了大量的地形特征,其中 ORE 便是生成矿物的特征了,其声明如下:
public static final Feature<OreFeatureConfig> ORE = register("ore", new OreFeature(OreFeatureConfig::deserialize));
如果你善于看源码,通过查找用法不难发现它的创建方法,在 net.minecraft.world.biome.DefaultBiomeFeatures 类中提供了大量方便的默认方法,可以看出这些地形特征都是指定生物群系加入的,其中 addDefaultOres 方法为某群系添加默认的矿物,代码如下:
public static void addDefaultOres(Biome biome) {
   biome.addFeature(GenerationStep.Feature.UNDERGROUND_ORES, Feature.ORE
         .configure(new OreFeatureConfig(OreFeatureConfig.Target.NATURAL_STONE, COAL_ORE, 17))
         .createDecoratedFeature(Decorator.COUNT_RANGE.configure(new RangeDecoratorConfig(20, 0, 0, 128))));
   
biome.addFeature(GenerationStep.Feature.UNDERGROUND_ORES, Feature.ORE.configure(new OreFeatureConfig(OreFeatureConfig.Target.NATURAL_STONE, IRON_ORE, 9)).createDecoratedFeature(Decorator.COUNT_RANGE.configure(new RangeDecoratorConfig(20, 0, 0, 64))));
   biome.addFeature(GenerationStep.Feature.UNDERGROUND_ORES, Feature.ORE.configure(new OreFeatureConfig(OreFeatureConfig.Target.NATURAL_STONE, GOLD_ORE, 9)).createDecoratedFeature(Decorator.COUNT_RANGE.configure(new RangeDecoratorConfig(2, 0, 0, 32))));
   biome.addFeature(GenerationStep.Feature.UNDERGROUND_ORES, Feature.ORE.configure(new OreFeatureConfig(OreFeatureConfig.Target.NATURAL_STONE, REDSTONE_ORE, 8)).createDecoratedFeature(Decorator.COUNT_RANGE.configure(new RangeDecoratorConfig(8, 0, 0, 16))));
   biome.addFeature(GenerationStep.Feature.UNDERGROUND_ORES, Feature.ORE.configure(new OreFeatureConfig(OreFeatureConfig.Target.NATURAL_STONE, DIAMOND_ORE, 8)).createDecoratedFeature(Decorator.COUNT_RANGE.configure(new RangeDecoratorConfig(1, 0, 0, 16))));
   biome.addFeature(GenerationStep.Feature.UNDERGROUND_ORES, Feature.ORE.configure(new OreFeatureConfig(OreFeatureConfig.Target.NATURAL_STONE, LAPIS_ORE, 7)).createDecoratedFeature(Decorator.COUNT_DEPTH_AVERAGE.configure(new CountDepthDecoratorConfig(1, 16, 16))));
}
源码通过调用 biome 对象的 addFeature 方法,将地形特征加入其中,第一个参数是类型,地下矿物传入 GenerationStep.Feature.UNDERGROUND_ORES 即可;第二个是欲添加的地形特征,需要一个已配置的地形特征(ConfiguredFeature),这便是我们所关注的了,源码通过调用 Feature 类的 configure 方法创建已配置的地形特征,需要一个对应的特征配置,这里是 OreFeatureConfig,下面是它的构造器方法参数列表:
参数 解释
OreFeatureConfig.Target target生成该矿物可替换掉的方块,只有两种值可用:
NATURAL_STONE:主世界地壳方块;NETHERRACK:下界地壳方块。
BlockState state矿物方块,调用 block.getDefaultState() 获取。
int size每个矿簇最大的方块数量。


接下来连续调用 createDecoratedFeature 来为之添加装饰器,以设置矿簇在地壳中的发布状况,需要传入一个已配置的装饰器(ConfiguredDecorator),和地形特征一样,为选好的装饰器调用 configure 方法传入对应配置创建即可。下面是常见的矿物装饰器及其配置:
装饰器类型 配置及构造器
COUNT_RANGE
每个区块最大数量和范围
RangeDecoratorConfig
构造器:
int count:每个区块生成的最大数量
int bottomOffset:最低生成高度
int topOffset:最高高度偏移
int maximum :最高生成高度
(实际最高高度为 maximum - topOffset,
可能是为结构预留的高度)
COUNT_DEPTH_AVERAGE
每个区块最大数量和平均位置
CountDepthDecoratorConfig
构造器:
int count
int baseline:平均高度
int spread:蔓延范围
EMERALD_ORE
绿宝石矿石专用
固定为 DecoratorConfig.DEFAULT


这便是地形特征的创建方式,以下是我们的羊毛矿代码:
  1. private static final ConfiguredFeature<?, ?> WOOL_ORE = Feature.ORE.configure(new OreFeatureConfig(OreFeatureConfig.Target.NATURAL_STONE, Blocks.WOOL.getDefaultState(), 6)).createDecoratedFeature(Decorator.COUNT_RANGE.configure(new RangeDecoratorConfig(20, 0, 0, 64)));
复制代码


添加到世界
上述源码中使用 biome.addFeature 方法将地形特征加入到某群系中,我们可用通过 Fabric 提供的注册表方法遍历现有群系,然后注册一个侦听器,以供将来添加。
  1. @Override
  2. public void onInitialize() {
  3. Registry.BIOME.forEach(this::handleBiome);
  4. RegistryEntryAddedCallback.event(Registry.BIOME).register((i, identifier, biome) -> handleBiome(biome));
  5. //...
  6. }
复制代码
  1. private static void handleBiome(Biome biome) {
  2. if(biome.getCategory() != Biome.Category.NETHER && biome.getCategory() != Biome.Category.THEEND) {
  3.                         biome.addFeature(GenerationStep.Feature.UNDERGROUND_ORES, WOOL_ORE);
  4.                 }
  5.         }
复制代码
遍历代码中使用 biome.getCategory() != Biome.Category.NETHER && biome.getCategory() != Biome.Category.THEEND 判断是否为主世界的生物群系,还可以增加判断以在不同的生物群系生成不同规模的矿簇。
快创建世界看下成果吧!
使用右侧指令清除石头:/fill ~-8 0 ~-8 ~8 ~ ~8 minecraft:air replace minecraft:stone



Fabric Wiki 效果图





感谢阅读,编写不易,您的支持是我最大的动力!


第一页 上一页 下一页 最后一页