欢迎光临散文网 会员登陆 & 注册

[21w07a]矿物与地下岩石生成机制详解

2021-02-20 12:19 作者:Nickid2018  | 我要投稿

在这两周的快照中,矿物生成机制被修改以适应21w06a修改的世界高度和噪声洞穴等新地形。那么现在的矿物生成变成了什么样子?接下来我将用比较详细的语言解析新的矿物生成算法。

注意:该地形生成算法暂时只对最新快照21w07a-21w08b有效,Mojang对此地形生成表示为“Not Final”,也就是不能确定是否将来版本也能遵循该机制。但是根据开发的进度,该地形生成应该基本完全,Mojang只会对传入参数进行微调。如果在新快照中发现此生成机制已修改/参数微调,这篇专栏也将适应性修改直到无法修改或参数稳定。

这篇专栏现在是以21w08b的矿物生成参数进行编写。

一.区块装饰生成阶段

为了生成一个完整的区块,Mojang将区块的生成定义了一个一个的阶段,每一个阶段会进行不同的工作。生成主要分三大步:生成指定高度基本地形->地形雕刻->世界装饰。世界装饰分为更细的阶段,后面的阶段能替换前方的方块(这也是为什么有的时候废弃矿坑有浮空草和浮空铁轨的原因)装饰阶段都在一个枚举中定义:

net.minecraft.world.level.levelgen.GenerationStep.Decoration

所有装饰阶段,字段顺序即为阶段顺序

这里我们可以看到,矿物生成是在要塞生成之后,地下装饰之前。而新增加的Deepslate则不同,它生成在基本岩石的生成阶段。

二.垂直锚点(Vertical Anchor)

这是21w07a新增的内容,用于辅助各种Feature(下文会说到)的Y轴定位。它在net.minecraft.world.level.levelgen中定义,是一个抽象类,子类定义在它的内部。它有三种模式(同时也是内部类的数量):Absolute(绝对坐标值,用absolute静态方法获得实例),BelowTop(距离最大建筑限制高度的坐标,用belowTop静态方法获得)和AboveBottom(距离最低建筑限制高度的坐标,用aboveBottom静态方法获得)。此外,还有两个常量:BOTTOM(最低建筑限制高度坐标)和TOP(最高建筑限制高度坐标)。垂直锚点有关于接下来的矿物高度和设置,也是这次更新的核心之一。

垂直锚点(VerticalAnchor)的实现类型,resolveY就是转换Y轴坐标使用的

三.地物配置(Configured Feature)

地物配置地物并不是一个很新的概念了,在1.14都能看见它的身影。它用于存储某种矿石或某种自然生成的方块生成位置等信息。它常用的方法如下:

rarity:每次尝试生成成功的几率,传入int

count:在此区块上的尝试生成次数,传入int

countRandom:随机尝试的最大次数,传入int

square:在区块平面(XOZ平面)定义位置,无参

depthAverage:定义生成位置的高度,参数是一个垂直锚点和一个int

range:定义生成位置高度,参数为两个垂直锚点

configured:生成地物的实际操作参数,例如进行放置矿石和结构的参数

对于矿石和三种变质岩,configured传入的都是OreConfiguration,它传入的是替换方块类型列表(targetStates)、矿脉大小(size)和掩埋概率(discardChanceOnAirExposure)。例如铜矿石,它放置的方块就是铜矿石,替换的就是主世界基础岩石(石头和Deepslate),矿脉大小是10。矿脉大小不能决定最后生成的一定有多少矿石,只是指定了一次矿脉生成的矿石最大数量。

这个版本新增和修改的就是depthAverage和range这两种配置,这也是下文将要说到的。

上文介绍了之后我们会用的概念和引入的参数,下面来说这些方块的生成和分布情况。

四.Deepslate生成

由于Deepslate比矿石生成要更早,所以我们要先说它的生成。它和石头处在同一个阶段生成,用了一个类net.minecraft.world.level.levelgen.DepthBasedReplacingBaseStoneSource判定在此生成的基础岩石。

DepthBasedReplacingBaseStoneSource类,获取世界的基础岩石

当世界开始生成基础岩石的时候,噪声世界生成器会调用getBaseStone查询这里应该生成的基础岩石,传入的是这个方块所处的坐标和世界噪声设置。首先,方法会检查这个噪声设置是否支持了Deepslate的生成,如果不支持直接返回最基础的石头。接下来设置随机数种子,获得种子的算法如下图:

得到随机数种子

然后计算这个高度下的Deepslate生成概率:

不同高度下Deepslate的生成概率,可以看出-1到-7层逐渐增多最终全部替换

然后计算随机数,根据概率得到这个方块的类型,这样Deepslate就成功生成了。

Deepslate生成之后,就开始生成基岩、结构,然后开始矿物生成。矿物生成需要分为两部分说,一部分是矿脉原点的设置,另一部分是矿脉的矿石放置。

五.判断矿物生成位置

在刚才Deepslate生成和表面建造之后,区块生成器调用Boime的generate开始世界装饰。generate中会调用大量的地物(Feature)去进行装饰,这里面就包括了矿石。

当generate调用到一个OreFeature,它首先进行原点定位。原点定位就与刚才的地物配置有关。

下面来说一下刚才在配置属性中没有详细介绍的range和depthAverage,它们有关于Y轴上的原点定位。

range:矿物在两个垂直锚点间的区域等可能生成。

比如21w07a中的高山煤矿,它从136格绝对高度到最大建筑高度上生成,选中某一个高度的概率就是1/184(0.0054%)

高山煤矿的生成

depthAverage:矿物以基准线为轴,向上下扩散分布。传入参数即为基准线(baseline)和扩散度(spread)

这个算法的代码如下:

Decorator是定位地物原点的类,这是depthAverage的实现

这里的代码解释像这样:算两次随机数并加和,减去扩散度再加上基准线高度。

有些不好理解?那么举一个例子:

假如你有一枚骰子,你把它抛出了两次,并计算了两次点数之和。计算每个值的概率,画出图像,你就能得到一个很像正态分布的图像。

一个投骰子的试验

通过这个的理解,我们也能很快的计算出来一次生成中矿物原点放置垂直位置的概率计算公式,公式如下:

H-矿物原点高度,b-基准线高度,s-扩散度

通过这个公式我们可以看到,概率最大的高度应该是基准线高度向下一格(h=b-1),而非基准线高度,概率是P(H=b-1)=1/s。(所以我认为这是Mojang没计算好)

为什么公式推导式是这个?在Java中,nextInt返回的是0到参数值的左闭右开区间,比如nextInt(3)的返回值就是{0,1,2},所以公式推导为这个。

在原点判断完之后,就是矿脉生成。

六.生成矿脉

在判断完原点之后,就会调用OreFeature的place方法进行矿脉放置。

place方法

简单说一下它的作用,先找出一个生成矿物的方向,然后根据矿物的规模决定生成一个矿脉的高度。然后调用doPlace,它是进行实际放置的方法,由于很复杂,解读都很麻烦,就不细说了。doPlace就是计算在此是否生成矿物,如果能,则判断是否可替换。为了在地下生成两种矿石,这里用到了一个叫TargetBlockState的类用于测试是否可替换现在的矿石。为了减小在空气中暴露的概率,加入了shouldSkipAirCheck等用于检查空气暴露的检查。在这些检查之后,如果可替换,就放置矿物。至此,矿物生成就结束了。

七.21w08b矿物分布

接下来,我们将计算21w08b中各种矿物的生成。下面的数据由各种生成方式尝试次数、矿脉大小和原点尝试概率等的积的和(不考虑暴露概率影响,暂且叫矿物生成常数OGC吧)作为参考依据考虑最佳的挖掘高度,这个值越大,生成概率就越高,它相当于一个完全合法由可替换方块组成的区块的Y轴某个平面上你能挖到的某种矿物数量平均值。在实际的生成中,由于每个区块都不是完全由可替换方块组成,所以真正的值要比预测值小。

1)钻石

钻石只有一个生成规律,每个区块尝试4次,矿脉大小为8,生成规律为depthAverage,基准线为-64,扩展度为80,掩埋概率为50%,所以最高生成原点高度为14。由于-64到-60层为基岩,所以最佳的挖掘高度为-59(不考虑岩浆层影响),OGC=0.37。

2)红石

红石具有两个生成规律:第一种是平常生成规律,尝试6次,矿脉大小为8,生成规律为range,从-64到15都有生成,OGC恒等为0.6;第二种为深层生成规律,尝试12次,矿脉大小为8,生成规律为depthAverage,基准线为-64,扩展度32,与钻石一样,在-59层挖掘最佳,这时该生成规律OGC为2.4375。所以总体看来,-59层挖掘最佳(不考虑岩浆层影响),OGC=3.0375。

3)铁矿石

铁矿石具有三个生成。在高处的生成尝试40次,矿脉大小为9,生成规律为depthAverage,基准线在256,扩展度为128,所以高处的生成理应为255层最多,期望OGC在2.8125。但是因为高山地形的另一项参数:可替换方块数的减小,使得生成失败概率很大,所以不推荐去高山挖矿。而在低处的生成会尝试20次,矿脉大小为9,分布也是depthAverage,基准线为32,扩散度为48,所以在31层挖矿最佳,OGC=3.75。在最底部还有减小矿石数的生成,尝试四次,矿脉大小为4,分布为range,在-64到-8生成,OGC为0.286。

4)铜矿石

铜矿石只有一种生成,尝试20次,矿脉大小为10,分布为depthAverage,基准线为48,扩散度为48。挖铜矿高度最佳为47,OGC=4.167。

5)煤矿石

煤矿石有两个生成规律。第一种是高山上的生成,尝试30次,矿脉大小为17,分布为range,从136到383分布,OGC恒等于2.056。第二种为低层面的生成,尝试20次,矿脉大小为17,分布为depthAverage,基准线为96,扩散度为96。由于两种方式有重叠,所以要计算两个位置的OGC。在Y=136,OGC=4.546;在Y=95,OGC=5.3125。所以,在95层挖煤最好,但是由于山地限制,生成成功概率较小,建议还是在地面浅表进行采掘(Y=60-63)

6)金矿石(主世界)

金矿只有一种生成规律,尝试4次,矿脉大小为8,50%掩埋概率,分布为depthAverage,基准线为-16,扩散度为48。在-17层采掘最好,OGC=0.667。

7)青金石

青金石有外露和不外露的两种生成规律。不外露方式尝试1次,矿脉大小为7,分布为range,从-64到64进行分布,OGC恒为0.054。外露方式尝试1次,矿脉大小为7,分布为depthAverage,基准线为0,扩散度为32。所以最佳挖掘高度在-1,此时OGC=0.273。

8)绿宝石

绿宝石只在高山地形生成,尝试6-16次不等,单个出现,分布为depthAverage,基准线为256,扩散度为224。理论生成在255层的最多,OGC为0.023-0.063,平均OGC为0.043。

9)安山岩

安山岩等岩石它们也是和矿石生成规律差不多。它会尝试生成2次,矿脉大小为64,分布range,在0到79层,OGC为1.6。

10)闪长岩

闪长岩会尝试生成2次,矿脉大小为64,分布为range,从0到79,OGC为1.6。

11)花岗岩

花岗岩尝试生成2次,矿脉大小64,分布为range,0-79分布,OGC=1.6。

12)砂砾(主世界)

砂砾会尝试生成12次,矿脉大小为33,分布为range,分布在0-319,OGC=1.238。

13)泥土(地下)

泥土会尝试生成15次,矿脉大小为33,分布为range,散列在0-319,OGC=1.549。

14)下界金矿石(三角洲区域)

这次修改不止修改了主世界的矿石,下界的矿石也被修改(但是生成的概率没有改变)。在三角洲区域的下界金矿尝试生成20次,矿脉大小为10,分布规律为range,分布在10-117层,OGC=1.852。

15)下界石英(三角洲区域)

三角洲区域下界石英尝试生成32次,矿脉大小为14,分布为range,在10-117层,OGC=4.148。

16)下界金矿石(其他区域)

普通下界金矿石尝试生成10次,矿脉大小为10,分布为range,在10-117层分布,OGC=0.926。

17)下界石英(其他区域)

普通下界石英矿石尝试生成16次,矿脉大小为14,分布为range,在10-117分布,OGC=2.074。

18)远古残骸

远古残骸有两个生成规律。大型矿脉尝试生成1次,矿脉大小为3,分布为depthAverage,基准线为16,扩散度为8,在Y=15时生成概率最大,OGC=0.188。小型矿脉尝试生成1次,分布为range,在8-119分布,OGC恒为0.019。所以在Y=15采掘远古残骸最好,OGC=0.207。

19)砂砾(下界)

在下界中,砂砾尝试生成2次,矿脉大小为33,分布为range,从5到41层之间分布,OGC=1.784。

20)灵魂沙(非灵魂沙峡谷的矿石类生成)

灵魂沙尝试生成12次,矿脉大小为12,分布为range,0-31层之间生成,OGC=4.5。

21)岩浆块(下界)

岩浆块尝试生成4次,矿脉大小33,分布为range,在27-36层分布,OGC=13.2。

22)黑石

黑石生成会尝试2次,矿脉大小为33,分布为range,在5-31层分布,OGC=2.444。

23)凝灰岩

凝灰岩在21w08b里面不再是紫水晶洞的外围,而是代替了07a安山岩在底层岩石的生成。它尝试2次,矿脉大小64,分布于-64到0层,OGC=2.0。

这些就是世界中可生成的所有矿物类方块的生成分布。可以看出,理论上,绿宝石仍然是MC中最难挖到的矿石,OGC仅为0.043(avg.);而最容易挖到的是岩浆块,OGC达到了惊人的13.2,只要你知道了它的分布位置很快就能挖回来一大堆。

这篇专栏到这里也就结束了,矿石生成只是MC众多生成规律的一部分,但是也是和我们最贴近的一个生成。

代码源:21w07a(1),21w08b(2),以Mojang Name反混淆

反混淆器:MCDynamicExchanger(现在有一点小bug,正在修)

[项目地址 https://github.com/Nickid2018/MCDynamicExchanger]

反编译器:CFK,FernFlower

第一次修改:

如果发现了文章中有问题,可以在评论区指正,在下一个快照发布时修改。

[21w07a]矿物与地下岩石生成机制详解的评论 (共 条)

分享到微博请遵守国家法律