[21w07a]礦物與地下巖石生成機(jī)制詳解

在這兩周的快照中,礦物生成機(jī)制被修改以適應(yīng)21w06a修改的世界高度和噪聲洞穴等新地形。那么現(xiàn)在的礦物生成變成了什么樣子?接下來我將用比較詳細(xì)的語言解析新的礦物生成算法。
注意:該地形生成算法暫時(shí)只對最新快照21w07a-21w08b有效,Mojang對此地形生成表示為“Not Final”,也就是不能確定是否將來版本也能遵循該機(jī)制。但是根據(jù)開發(fā)的進(jìn)度,該地形生成應(yīng)該基本完全,Mojang只會對傳入?yún)?shù)進(jìn)行微調(diào)。如果在新快照中發(fā)現(xiàn)此生成機(jī)制已修改/參數(shù)微調(diào),這篇專欄也將適應(yīng)性修改直到無法修改或參數(shù)穩(wěn)定。
這篇專欄現(xiàn)在是以21w08b的礦物生成參數(shù)進(jìn)行編寫。
一.區(qū)塊裝飾生成階段
為了生成一個(gè)完整的區(qū)塊,Mojang將區(qū)塊的生成定義了一個(gè)一個(gè)的階段,每一個(gè)階段會進(jìn)行不同的工作。生成主要分三大步:生成指定高度基本地形->地形雕刻->世界裝飾。世界裝飾分為更細(xì)的階段,后面的階段能替換前方的方塊(這也是為什么有的時(shí)候廢棄礦坑有浮空草和浮空鐵軌的原因)裝飾階段都在一個(gè)枚舉中定義:
net.minecraft.world.level.levelgen.GenerationStep.Decoration

這里我們可以看到,礦物生成是在要塞生成之后,地下裝飾之前。而新增加的Deepslate則不同,它生成在基本巖石的生成階段。
二.垂直錨點(diǎn)(Vertical Anchor)
這是21w07a新增的內(nèi)容,用于輔助各種Feature(下文會說到)的Y軸定位。它在net.minecraft.world.level.levelgen中定義,是一個(gè)抽象類,子類定義在它的內(nèi)部。它有三種模式(同時(shí)也是內(nèi)部類的數(shù)量):Absolute(絕對坐標(biāo)值,用absolute靜態(tài)方法獲得實(shí)例),BelowTop(距離最大建筑限制高度的坐標(biāo),用belowTop靜態(tài)方法獲得)和AboveBottom(距離最低建筑限制高度的坐標(biāo),用aboveBottom靜態(tài)方法獲得)。此外,還有兩個(gè)常量:BOTTOM(最低建筑限制高度坐標(biāo))和TOP(最高建筑限制高度坐標(biāo))。垂直錨點(diǎn)有關(guān)于接下來的礦物高度和設(shè)置,也是這次更新的核心之一。

三.地物配置(Configured Feature)
地物配置地物并不是一個(gè)很新的概念了,在1.14都能看見它的身影。它用于存儲某種礦石或某種自然生成的方塊生成位置等信息。它常用的方法如下:
rarity:每次嘗試生成成功的幾率,傳入int
count:在此區(qū)塊上的嘗試生成次數(shù),傳入int
countRandom:隨機(jī)嘗試的最大次數(shù),傳入int
square:在區(qū)塊平面(XOZ平面)定義位置,無參
depthAverage:定義生成位置的高度,參數(shù)是一個(gè)垂直錨點(diǎn)和一個(gè)int
range:定義生成位置高度,參數(shù)為兩個(gè)垂直錨點(diǎn)
configured:生成地物的實(shí)際操作參數(shù),例如進(jìn)行放置礦石和結(jié)構(gòu)的參數(shù)
對于礦石和三種變質(zhì)巖,configured傳入的都是OreConfiguration,它傳入的是替換方塊類型列表(targetStates)、礦脈大?。╯ize)和掩埋概率(discardChanceOnAirExposure)。例如銅礦石,它放置的方塊就是銅礦石,替換的就是主世界基礎(chǔ)巖石(石頭和Deepslate),礦脈大小是10。礦脈大小不能決定最后生成的一定有多少礦石,只是指定了一次礦脈生成的礦石最大數(shù)量。
這個(gè)版本新增和修改的就是depthAverage和range這兩種配置,這也是下文將要說到的。
上文介紹了之后我們會用的概念和引入的參數(shù),下面來說這些方塊的生成和分布情況。
四.Deepslate生成
由于Deepslate比礦石生成要更早,所以我們要先說它的生成。它和石頭處在同一個(gè)階段生成,用了一個(gè)類net.minecraft.world.level.levelgen.DepthBasedReplacingBaseStoneSource判定在此生成的基礎(chǔ)巖石。

當(dāng)世界開始生成基礎(chǔ)巖石的時(shí)候,噪聲世界生成器會調(diào)用getBaseStone查詢這里應(yīng)該生成的基礎(chǔ)巖石,傳入的是這個(gè)方塊所處的坐標(biāo)和世界噪聲設(shè)置。首先,方法會檢查這個(gè)噪聲設(shè)置是否支持了Deepslate的生成,如果不支持直接返回最基礎(chǔ)的石頭。接下來設(shè)置隨機(jī)數(shù)種子,獲得種子的算法如下圖:

然后計(jì)算這個(gè)高度下的Deepslate生成概率:

然后計(jì)算隨機(jī)數(shù),根據(jù)概率得到這個(gè)方塊的類型,這樣Deepslate就成功生成了。
Deepslate生成之后,就開始生成基巖、結(jié)構(gòu),然后開始礦物生成。礦物生成需要分為兩部分說,一部分是礦脈原點(diǎn)的設(shè)置,另一部分是礦脈的礦石放置。
五.判斷礦物生成位置
在剛才Deepslate生成和表面建造之后,區(qū)塊生成器調(diào)用Boime的generate開始世界裝飾。generate中會調(diào)用大量的地物(Feature)去進(jìn)行裝飾,這里面就包括了礦石。
當(dāng)generate調(diào)用到一個(gè)OreFeature,它首先進(jìn)行原點(diǎn)定位。原點(diǎn)定位就與剛才的地物配置有關(guān)。
下面來說一下剛才在配置屬性中沒有詳細(xì)介紹的range和depthAverage,它們有關(guān)于Y軸上的原點(diǎn)定位。
range:礦物在兩個(gè)垂直錨點(diǎn)間的區(qū)域等可能生成。
比如21w07a中的高山煤礦,它從136格絕對高度到最大建筑高度上生成,選中某一個(gè)高度的概率就是1/184(0.0054%)

depthAverage:礦物以基準(zhǔn)線為軸,向上下擴(kuò)散分布。傳入?yún)?shù)即為基準(zhǔn)線(baseline)和擴(kuò)散度(spread)
這個(gè)算法的代碼如下:

這里的代碼解釋像這樣:算兩次隨機(jī)數(shù)并加和,減去擴(kuò)散度再加上基準(zhǔn)線高度。
有些不好理解?那么舉一個(gè)例子:
假如你有一枚骰子,你把它拋出了兩次,并計(jì)算了兩次點(diǎn)數(shù)之和。計(jì)算每個(gè)值的概率,畫出圖像,你就能得到一個(gè)很像正態(tài)分布的圖像。

通過這個(gè)的理解,我們也能很快的計(jì)算出來一次生成中礦物原點(diǎn)放置垂直位置的概率計(jì)算公式,公式如下:

通過這個(gè)公式我們可以看到,概率最大的高度應(yīng)該是基準(zhǔn)線高度向下一格(h=b-1),而非基準(zhǔn)線高度,概率是P(H=b-1)=1/s。(所以我認(rèn)為這是Mojang沒計(jì)算好)
為什么公式推導(dǎo)式是這個(gè)?在Java中,nextInt返回的是0到參數(shù)值的左閉右開區(qū)間,比如nextInt(3)的返回值就是{0,1,2},所以公式推導(dǎo)為這個(gè)。
在原點(diǎn)判斷完之后,就是礦脈生成。
六.生成礦脈
在判斷完原點(diǎn)之后,就會調(diào)用OreFeature的place方法進(jìn)行礦脈放置。

簡單說一下它的作用,先找出一個(gè)生成礦物的方向,然后根據(jù)礦物的規(guī)模決定生成一個(gè)礦脈的高度。然后調(diào)用doPlace,它是進(jìn)行實(shí)際放置的方法,由于很復(fù)雜,解讀都很麻煩,就不細(xì)說了。doPlace就是計(jì)算在此是否生成礦物,如果能,則判斷是否可替換。為了在地下生成兩種礦石,這里用到了一個(gè)叫TargetBlockState的類用于測試是否可替換現(xiàn)在的礦石。為了減小在空氣中暴露的概率,加入了shouldSkipAirCheck等用于檢查空氣暴露的檢查。在這些檢查之后,如果可替換,就放置礦物。至此,礦物生成就結(jié)束了。
七.21w08b礦物分布
接下來,我們將計(jì)算21w08b中各種礦物的生成。下面的數(shù)據(jù)由各種生成方式嘗試次數(shù)、礦脈大小和原點(diǎn)嘗試概率等的積的和(不考慮暴露概率影響,暫且叫礦物生成常數(shù)OGC吧)作為參考依據(jù)考慮最佳的挖掘高度,這個(gè)值越大,生成概率就越高,它相當(dāng)于一個(gè)完全合法由可替換方塊組成的區(qū)塊的Y軸某個(gè)平面上你能挖到的某種礦物數(shù)量平均值。在實(shí)際的生成中,由于每個(gè)區(qū)塊都不是完全由可替換方塊組成,所以真正的值要比預(yù)測值小。
1)鉆石
鉆石只有一個(gè)生成規(guī)律,每個(gè)區(qū)塊嘗試4次,礦脈大小為8,生成規(guī)律為depthAverage,基準(zhǔn)線為-64,擴(kuò)展度為80,掩埋概率為50%,所以最高生成原點(diǎn)高度為14。由于-64到-60層為基巖,所以最佳的挖掘高度為-59(不考慮巖漿層影響),OGC=0.37。
2)紅石
紅石具有兩個(gè)生成規(guī)律:第一種是平常生成規(guī)律,嘗試6次,礦脈大小為8,生成規(guī)律為range,從-64到15都有生成,OGC恒等為0.6;第二種為深層生成規(guī)律,嘗試12次,礦脈大小為8,生成規(guī)律為depthAverage,基準(zhǔn)線為-64,擴(kuò)展度32,與鉆石一樣,在-59層挖掘最佳,這時(shí)該生成規(guī)律OGC為2.4375。所以總體看來,-59層挖掘最佳(不考慮巖漿層影響),OGC=3.0375。
3)鐵礦石
鐵礦石具有三個(gè)生成。在高處的生成嘗試40次,礦脈大小為9,生成規(guī)律為depthAverage,基準(zhǔn)線在256,擴(kuò)展度為128,所以高處的生成理應(yīng)為255層最多,期望OGC在2.8125。但是因?yàn)楦呱降匦蔚牧硪豁?xiàng)參數(shù):可替換方塊數(shù)的減小,使得生成失敗概率很大,所以不推薦去高山挖礦。而在低處的生成會嘗試20次,礦脈大小為9,分布也是depthAverage,基準(zhǔn)線為32,擴(kuò)散度為48,所以在31層挖礦最佳,OGC=3.75。在最底部還有減小礦石數(shù)的生成,嘗試四次,礦脈大小為4,分布為range,在-64到-8生成,OGC為0.286。
4)銅礦石
銅礦石只有一種生成,嘗試20次,礦脈大小為10,分布為depthAverage,基準(zhǔn)線為48,擴(kuò)散度為48。挖銅礦高度最佳為47,OGC=4.167。
5)煤礦石
煤礦石有兩個(gè)生成規(guī)律。第一種是高山上的生成,嘗試30次,礦脈大小為17,分布為range,從136到383分布,OGC恒等于2.056。第二種為低層面的生成,嘗試20次,礦脈大小為17,分布為depthAverage,基準(zhǔn)線為96,擴(kuò)散度為96。由于兩種方式有重疊,所以要計(jì)算兩個(gè)位置的OGC。在Y=136,OGC=4.546;在Y=95,OGC=5.3125。所以,在95層挖煤最好,但是由于山地限制,生成成功概率較小,建議還是在地面淺表進(jìn)行采掘(Y=60-63)
6)金礦石(主世界)
金礦只有一種生成規(guī)律,嘗試4次,礦脈大小為8,50%掩埋概率,分布為depthAverage,基準(zhǔn)線為-16,擴(kuò)散度為48。在-17層采掘最好,OGC=0.667。
7)青金石
青金石有外露和不外露的兩種生成規(guī)律。不外露方式嘗試1次,礦脈大小為7,分布為range,從-64到64進(jìn)行分布,OGC恒為0.054。外露方式嘗試1次,礦脈大小為7,分布為depthAverage,基準(zhǔn)線為0,擴(kuò)散度為32。所以最佳挖掘高度在-1,此時(shí)OGC=0.273。
8)綠寶石
綠寶石只在高山地形生成,嘗試6-16次不等,單個(gè)出現(xiàn),分布為depthAverage,基準(zhǔn)線為256,擴(kuò)散度為224。理論生成在255層的最多,OGC為0.023-0.063,平均OGC為0.043。
9)安山巖
安山巖等巖石它們也是和礦石生成規(guī)律差不多。它會嘗試生成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)泥土(地下)
泥土?xí)L試生成15次,礦脈大小為33,分布為range,散列在0-319,OGC=1.549。
14)下界金礦石(三角洲區(qū)域)
這次修改不止修改了主世界的礦石,下界的礦石也被修改(但是生成的概率沒有改變)。在三角洲區(qū)域的下界金礦嘗試生成20次,礦脈大小為10,分布規(guī)律為range,分布在10-117層,OGC=1.852。
15)下界石英(三角洲區(qū)域)
三角洲區(qū)域下界石英嘗試生成32次,礦脈大小為14,分布為range,在10-117層,OGC=4.148。
16)下界金礦石(其他區(qū)域)
普通下界金礦石嘗試生成10次,礦脈大小為10,分布為range,在10-117層分布,OGC=0.926。
17)下界石英(其他區(qū)域)
普通下界石英礦石嘗試生成16次,礦脈大小為14,分布為range,在10-117分布,OGC=2.074。
18)遠(yuǎn)古殘骸
遠(yuǎn)古殘骸有兩個(gè)生成規(guī)律。大型礦脈嘗試生成1次,礦脈大小為3,分布為depthAverage,基準(zhǔn)線為16,擴(kuò)散度為8,在Y=15時(shí)生成概率最大,OGC=0.188。小型礦脈嘗試生成1次,分布為range,在8-119分布,OGC恒為0.019。所以在Y=15采掘遠(yuǎn)古殘骸最好,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)凝灰?guī)r
凝灰?guī)r在21w08b里面不再是紫水晶洞的外圍,而是代替了07a安山巖在底層巖石的生成。它嘗試2次,礦脈大小64,分布于-64到0層,OGC=2.0。
這些就是世界中可生成的所有礦物類方塊的生成分布??梢钥闯?,理論上,綠寶石仍然是MC中最難挖到的礦石,OGC僅為0.043(avg.);而最容易挖到的是巖漿塊,OGC達(dá)到了驚人的13.2,只要你知道了它的分布位置很快就能挖回來一大堆。

這篇專欄到這里也就結(jié)束了,礦石生成只是MC眾多生成規(guī)律的一部分,但是也是和我們最貼近的一個(gè)生成。
代碼源:21w07a(1),21w08b(2),以Mojang Name反混淆
反混淆器:MCDynamicExchanger(現(xiàn)在有一點(diǎn)小bug,正在修)
[項(xiàng)目地址 https://github.com/Nickid2018/MCDynamicExchanger]
反編譯器:CFK,F(xiàn)ernFlower
第一次修改:
如果發(fā)現(xiàn)了文章中有問題,可以在評論區(qū)指正,在下一個(gè)快照發(fā)布時(shí)修改。